Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10039)

Unified Diff: chrome/common/extensions/extension.cc

Issue 9812008: Polish the keybinding implementation a bit. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/common/extensions/extension.h ('k') | chrome/common/extensions/extension_manifest_constants.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/common/extensions/extension.cc
===================================================================
--- chrome/common/extensions/extension.cc (revision 129600)
+++ chrome/common/extensions/extension.cc (working copy)
@@ -244,37 +244,32 @@
Extension::ExtensionKeybinding::ExtensionKeybinding() {}
Extension::ExtensionKeybinding::~ExtensionKeybinding() {}
-bool Extension::ExtensionKeybinding::Parse(DictionaryValue* command,
- const std::string& command_name,
- int index,
- string16* error) {
- DCHECK(!command_name.empty());
- std::string key_binding;
- if (!command->GetString(keys::kKey, &key_binding) ||
- key_binding.empty()) {
+ui::Accelerator Extension::ExtensionKeybinding::ParseImpl(
+ const std::string& shortcut,
+ const std::string& platform_key,
+ int index,
+ string16* error) {
+ if (platform_key != values::kKeybindingPlatformWin &&
+ platform_key != values::kKeybindingPlatformMac &&
+ platform_key != values::kKeybindingPlatformChromeOs &&
+ platform_key != values::kKeybindingPlatformLinux &&
+ platform_key != values::kKeybindingPlatformDefault) {
*error = ExtensionErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidKeyBinding,
+ errors::kInvalidKeyBindingUnknownPlatform,
base::IntToString(index),
- "Missing");
- return false;
+ platform_key);
+ return ui::Accelerator();
}
- std::string original_keybinding = key_binding;
- // Normalize '-' to '+'.
- ReplaceSubstringsAfterOffset(&key_binding, 0, "-", "+");
- // Remove all spaces.
- ReplaceSubstringsAfterOffset(&key_binding, 0, " ", "");
- // And finally, lower-case it.
- key_binding = StringToLowerASCII(key_binding);
-
std::vector<std::string> tokens;
- base::SplitString(key_binding, '+', &tokens);
+ base::SplitString(shortcut, '+', &tokens);
if (tokens.size() < 2 || tokens.size() > 3) {
*error = ExtensionErrorUtils::FormatErrorMessageUTF16(
errors::kInvalidKeyBinding,
base::IntToString(index),
- original_keybinding);
- return false;
+ platform_key,
+ shortcut);
+ return ui::Accelerator();
}
// Now, parse it into an accelerator.
@@ -283,27 +278,32 @@
bool shift = false;
ui::KeyboardCode key = ui::VKEY_UNKNOWN;
for (size_t i = 0; i < tokens.size(); i++) {
- if (tokens[i] == "ctrl") {
+ if (tokens[i] == "Ctrl") {
ctrl = true;
- } else if (tokens[i] == "alt") {
+ } else if (tokens[i] == "Alt") {
alt = true;
- } else if (tokens[i] == "shift") {
+ } else if (tokens[i] == "Shift") {
shift = true;
+ } else if (tokens[i] == "Command" && platform_key == "mac") {
+ // TODO(finnur): Implement for Mac.
+ } else if (tokens[i] == "Option" && platform_key == "mac") {
+ // TODO(finnur): Implement for Mac.
} else if (tokens[i].size() == 1 &&
- tokens[i][0] >= 'a' && tokens[i][0] <= 'z') {
+ tokens[i][0] >= 'A' && tokens[i][0] <= 'Z') {
if (key != ui::VKEY_UNKNOWN) {
// Multiple key assignments.
key = ui::VKEY_UNKNOWN;
break;
}
- key = static_cast<ui::KeyboardCode>(ui::VKEY_A + (tokens[i][0] - 'a'));
+ key = static_cast<ui::KeyboardCode>(ui::VKEY_A + (tokens[i][0] - 'A'));
} else {
*error = ExtensionErrorUtils::FormatErrorMessageUTF16(
errors::kInvalidKeyBinding,
base::IntToString(index),
- original_keybinding);
- return false;
+ platform_key,
+ shortcut);
+ return ui::Accelerator();
}
}
@@ -314,26 +314,124 @@
*error = ExtensionErrorUtils::FormatErrorMessageUTF16(
errors::kInvalidKeyBinding,
base::IntToString(index),
- original_keybinding);
- return false;
+ platform_key,
+ shortcut);
+ return ui::Accelerator();
}
- accelerator_ = ui::Accelerator(key, shift, ctrl, alt);
+ return ui::Accelerator(key, shift, ctrl, alt);
+}
- if (command_name !=
- extension_manifest_values::kPageActionKeybindingEvent &&
- command_name !=
- extension_manifest_values::kBrowserActionKeybindingEvent) {
- if (!command->GetString(keys::kDescription, &description_) ||
- description_.empty()) {
+bool Extension::ExtensionKeybinding::Parse(DictionaryValue* command,
+ const std::string& command_name,
+ int index,
+ string16* error) {
+ DCHECK(!command_name.empty());
+
+ // We'll build up a map of platform-to-shortcut suggestions.
+ std::map<const std::string, std::string> suggestions;
+
+ // First try to parse the |suggested_key| as a dictionary.
+ DictionaryValue* suggested_key_dict;
+ if (command->GetDictionary(keys::kSuggestedKey, &suggested_key_dict)) {
+ DictionaryValue::key_iterator iter = suggested_key_dict->begin_keys();
+ for ( ; iter != suggested_key_dict->end_keys(); ++iter) {
+ // For each item in the dictionary, extract the platforms specified.
+ std::string suggested_key_string;
+ if (suggested_key_dict->GetString(*iter, &suggested_key_string) &&
+ !suggested_key_string.empty()) {
+ // Found a platform, add it to the suggestions list.
+ suggestions[*iter] = suggested_key_string;
+ } else {
+ *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidKeyBinding,
+ base::IntToString(index),
+ keys::kSuggestedKey,
+ "Missing");
+ return false;
+ }
+ }
+ } else {
+ // No dictionary was found, fall back to using just a string, so developers
+ // don't have to specify a dictionary if they just want to use one default
+ // for all platforms.
+ std::string suggested_key_string;
+ if (command->GetString(keys::kSuggestedKey, &suggested_key_string) &&
+ !suggested_key_string.empty()) {
+ // If only a signle string is provided, it must be default for all.
+ suggestions["default"] = suggested_key_string;
+ } else {
*error = ExtensionErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidKeyBindingDescription,
- base::IntToString(index));
+ errors::kInvalidKeyBinding,
+ base::IntToString(index),
+ keys::kSuggestedKey,
+ "Missing");
+ return false;
+ }
+ }
+
+ std::string platform =
+#if defined(OS_WIN)
+ values::kKeybindingPlatformWin;
+#elif defined(OS_MACOSX)
+ values::kKeybindingPlatformMac;
+#elif defined(OS_CHROMEOS)
+ values::kKeybindingPlatformChromeOs;
+#elif defined(OS_LINUX)
+ values::kKeybindingPlatformLinux;
+#else
+ "";
+#endif
+
+ std::string key = platform;
+ if (suggestions.find(key) == suggestions.end())
+ key = values::kKeybindingPlatformDefault;
+ if (suggestions.find(key) == suggestions.end()) {
+ *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidKeyBindingMissingPlatform,
+ base::IntToString(index),
+ keys::kSuggestedKey,
+ platform);
+ return false; // No platform specified and no fallback. Bail.
+ }
+
+ // For developer convenience, we parse all the suggestions (and complain about
+ // errors for platforms other than the current one) but use only what we need.
+ std::map<const std::string, std::string>::const_iterator iter =
+ suggestions.begin();
+ for ( ; iter != suggestions.end(); ++iter) {
+ // Note that we pass iter->first to pretend we are on a platform we're not
+ // on.
+ ui::Accelerator accelerator =
+ ParseImpl(iter->second, iter->first, index, error);
+ if (accelerator.key_code() == ui::VKEY_UNKNOWN) {
+ *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidKeyBinding,
+ base::IntToString(index),
+ iter->first,
+ iter->second);
return false;
}
+
+ if (iter->first == key) {
+ // This platform is our platform, so grab this key.
+ accelerator_ = accelerator;
+ command_name_ = command_name;
+
+ if (command_name !=
+ extension_manifest_values::kPageActionKeybindingEvent &&
+ command_name !=
+ extension_manifest_values::kBrowserActionKeybindingEvent) {
+ if (!command->GetString(keys::kDescription, &description_) ||
+ description_.empty()) {
+ *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidKeyBindingDescription,
+ base::IntToString(index));
+ return false;
+ }
+ }
+ }
}
-
- command_name_ = command_name;
return true;
}
@@ -1526,11 +1624,20 @@
return false;
}
- ExtensionKeybinding binding;
- if (!binding.Parse(command, *iter, command_index, error))
+ scoped_ptr<Extension::ExtensionKeybinding> binding(
+ new ExtensionKeybinding());
+ if (!binding->Parse(command, *iter, command_index, error))
return false; // |error| already set.
- commands_.push_back(binding);
+ std::string command_name = binding->command_name();
+ if (command_name == values::kPageActionKeybindingEvent) {
+ page_action_command_.reset(binding.release());
+ } else if (command_name == values::kBrowserActionKeybindingEvent) {
+ browser_action_command_.reset(binding.release());
+ } else {
+ if (command_name[0] != '_') // All commands w/underscore are reserved.
+ named_commands_[command_name] = *binding.release();
+ }
}
}
return true;
« no previous file with comments | « chrome/common/extensions/extension.h ('k') | chrome/common/extensions/extension_manifest_constants.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698