Chromium Code Reviews| Index: chrome/common/extensions/extension.cc |
| =================================================================== |
| --- chrome/common/extensions/extension.cc (revision 122745) |
| +++ chrome/common/extensions/extension.cc (working copy) |
| @@ -42,6 +42,7 @@ |
| #include "grit/theme_resources.h" |
| #include "net/base/registry_controlled_domain.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| +#include "ui/base/keycodes/keyboard_codes.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #include "webkit/glue/image_decoder.h" |
| @@ -219,6 +220,105 @@ |
| Extension::TtsVoice::TtsVoice() {} |
| Extension::TtsVoice::~TtsVoice() {} |
| +Extension::ExtensionKeybinding::ExtensionKeybinding() {} |
| +Extension::ExtensionKeybinding::~ExtensionKeybinding() {} |
| + |
| +bool Extension::ExtensionKeybinding::Parse(DictionaryValue* command, |
| + const std::string& event_name, |
| + string16* error, |
| + int index) { |
|
Matt Perry
2012/02/21 23:13:39
outparams (error) should go last
|
| + std::string key_binding; |
| + if (!command->GetString(keys::kKey, &key_binding)) { |
| + *error = ExtensionErrorUtils::FormatErrorMessageUTF16( |
| + errors::kInvalidKeyBinding, |
| + base::IntToString(index), |
| + "Missing"); |
| + return false; |
| + } |
| + |
| + std::string original_keybinding = key_binding; |
| + // Normalize '-' to '+'. |
| + for (size_t pos = key_binding.find('-'); |
| + pos != std::string::npos; |
| + pos = key_binding.find('-')) { |
| + key_binding.replace(pos, 1, "+"); |
| + } |
| + // Remove all spaces. |
| + for (size_t pos = key_binding.find(' '); |
| + pos != std::string::npos; |
| + pos = key_binding.find(' ')) { |
| + key_binding.replace(pos, 1, ""); |
| + } |
|
Matt Perry
2012/02/21 23:13:39
base::ReplaceSubstringsAfterOffset(&key_binding, 0
|
| + // And finally, lower-case it. |
| + key_binding = StringToLowerASCII(key_binding); |
| + |
| + // Now, parse it into an accelerator. |
| + bool ctrl = false; |
| + bool alt = false; |
| + bool shift = false; |
| + ui::KeyboardCode key = ui::VKEY_UNKNOWN; |
| + // We support Ctrl+foo, Alt+foo, Ctrl+Shift+foo, Alt+Shift+foo, but not |
| + // Ctrl+Alt+foo. For a more detailed reason why we don't support Ctrl+Alt+foo: |
| + // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/29/101121.aspx. |
| + size_t position; |
|
Matt Perry
2012/02/21 23:13:39
Should we support Shift+Alt+foo? If so, it might b
Finnur
2012/02/22 23:45:22
Good idea.
On 2012/02/21 23:13:39, Matt Perry wro
|
| + if ((position = key_binding.find("ctrl+")) != std::string::npos) { |
| + ctrl = true; |
| + key_binding = key_binding.replace(position, 5, ""); |
| + } else if ((position = key_binding.find("alt+")) != std::string::npos) { |
| + alt = true; |
| + key_binding = key_binding.replace(position, 4, ""); |
| + } |
| + if ((position = key_binding.find("shift+")) != std::string::npos) { |
| + shift = true; |
| + key_binding = key_binding.replace(position, 6, ""); |
| + } |
| + // We've stripped everything from the string but the letter. |
| + if (key_binding.size() != 1) { |
| + *error = ExtensionErrorUtils::FormatErrorMessageUTF16( |
| + errors::kInvalidKeyBinding, |
| + base::IntToString(index), |
| + original_keybinding); |
| + return false; |
| + } |
| + |
| + if (key_binding.compare("a") == 0) key = ui::VKEY_A; |
|
Matt Perry
2012/02/21 23:13:39
Are we guaranteed for VKEY_A through _Z to be cont
|
| + else if (key_binding.compare("b") == 0) key = ui::VKEY_B; |
| + else if (key_binding.compare("c") == 0) key = ui::VKEY_C; |
| + else if (key_binding.compare("d") == 0) key = ui::VKEY_D; |
| + else if (key_binding.compare("e") == 0) key = ui::VKEY_E; |
| + else if (key_binding.compare("f") == 0) key = ui::VKEY_F; |
| + else if (key_binding.compare("g") == 0) key = ui::VKEY_G; |
| + else if (key_binding.compare("h") == 0) key = ui::VKEY_H; |
| + else if (key_binding.compare("i") == 0) key = ui::VKEY_I; |
| + else if (key_binding.compare("j") == 0) key = ui::VKEY_J; |
| + else if (key_binding.compare("k") == 0) key = ui::VKEY_K; |
| + else if (key_binding.compare("l") == 0) key = ui::VKEY_L; |
| + else if (key_binding.compare("m") == 0) key = ui::VKEY_M; |
| + else if (key_binding.compare("n") == 0) key = ui::VKEY_N; |
| + else if (key_binding.compare("o") == 0) key = ui::VKEY_O; |
| + else if (key_binding.compare("p") == 0) key = ui::VKEY_P; |
| + else if (key_binding.compare("q") == 0) key = ui::VKEY_Q; |
| + else if (key_binding.compare("r") == 0) key = ui::VKEY_R; |
| + else if (key_binding.compare("s") == 0) key = ui::VKEY_S; |
| + else if (key_binding.compare("t") == 0) key = ui::VKEY_T; |
| + else if (key_binding.compare("u") == 0) key = ui::VKEY_U; |
| + else if (key_binding.compare("v") == 0) key = ui::VKEY_V; |
| + else if (key_binding.compare("x") == 0) key = ui::VKEY_X; |
| + else if (key_binding.compare("y") == 0) key = ui::VKEY_Y; |
| + else if (key_binding.compare("z") == 0) key = ui::VKEY_Z; |
| + |
| + accelerator_ = ui::Accelerator(key, shift, ctrl, alt); |
| + if (!command->GetString(keys::kDescription, &description_)) { |
| + *error = ExtensionErrorUtils::FormatErrorMessageUTF16( |
| + errors::kInvalidKeyBindingDescription, |
| + base::IntToString(index)); |
| + return false; |
| + } |
| + |
| + event_name_ = event_name; |
| + return true; |
| +} |
| + |
| // |
| // Extension |
| // |
| @@ -858,7 +958,7 @@ |
| // Read the file browser action |default_icon| (optional). |
| if (file_browser_handler->HasKey(keys::kPageActionDefaultIcon)) { |
| if (!file_browser_handler->GetString( |
| - keys::kPageActionDefaultIcon,&default_icon) || |
| + keys::kPageActionDefaultIcon, &default_icon) || |
| default_icon.empty()) { |
| *error = ASCIIToUTF16(errors::kInvalidPageActionIconPath); |
| return NULL; |
| @@ -1162,7 +1262,7 @@ |
| !one_service->GetList(keys::kIntentType, &mime_types) || |
| mime_types->GetSize() == 0) { |
| *error = ExtensionErrorUtils::FormatErrorMessageUTF16( |
| - errors::kInvalidIntentType,*iter); |
| + errors::kInvalidIntentType, *iter); |
| return false; |
| } |
| @@ -1177,7 +1277,7 @@ |
| if (!service_url.is_valid() || |
| !(web_extent().MatchesURL(service_url))) { |
| *error = ExtensionErrorUtils::FormatErrorMessageUTF16( |
| - errors::kInvalidIntentPageInHostedApp,*iter); |
| + errors::kInvalidIntentPageInHostedApp, *iter); |
| return false; |
| } |
| service.service_url = service_url; |
| @@ -1185,7 +1285,7 @@ |
| // We do not allow absolute intent URLs in non-hosted apps. |
| if (GURL(value).is_valid()) { |
| *error =ExtensionErrorUtils::FormatErrorMessageUTF16( |
| - errors::kCannotAccessPage,value.c_str()); |
| + errors::kCannotAccessPage, value.c_str()); |
| return false; |
| } |
| service.service_url = GetResourceURL(value); |
| @@ -1719,6 +1819,35 @@ |
| manifest->GetBoolean(keys::kConvertedFromUserScript, |
| &converted_from_user_script_); |
| + // Initialize commands (if present). |
| + if (manifest->HasKey(keys::kCommands)) { |
| + DictionaryValue* commands = NULL; |
| + if (!manifest->GetDictionary(keys::kCommands, &commands)) { |
| + *error = ASCIIToUTF16(errors::kInvalidCommandsKey); |
| + return false; |
| + } |
| + |
| + int command_index = 0; |
| + for (DictionaryValue::key_iterator iter = commands->begin_keys(); |
| + iter != commands->end_keys(); ++iter) { |
| + ++command_index; |
| + |
| + DictionaryValue* command = NULL; |
| + if (!commands->GetDictionary(*iter, &command)) { |
| + *error = ExtensionErrorUtils::FormatErrorMessageUTF16( |
| + errors::kInvalidKeyBindingDictionary, |
| + base::IntToString(command_index)); |
| + return false; |
| + } |
| + |
| + ExtensionKeybinding binding; |
| + if (!binding.Parse(command, *iter, error, command_index)) |
| + return false; // |error| already set. |
| + |
| + commands_.push_back(binding); |
| + } |
| + } |
| + |
| // Initialize icons (if present). |
| if (manifest->HasKey(keys::kIcons)) { |
| DictionaryValue* icons_value = NULL; |
| @@ -2882,7 +3011,7 @@ |
| bool supports_type = false; |
| switch (GetType()) { |
| - case TYPE_USER_SCRIPT: // Pass through. |
| + case TYPE_USER_SCRIPT: // Pass through. |
| case TYPE_EXTENSION: |
| supports_type = permission->supports_extensions(); |
| break; |
| @@ -3038,7 +3167,6 @@ |
| // their positions should sync. |
| return location_ == Extension::INTERNAL || |
| ShouldDisplayInLauncher(); |
| - |
| } |
| bool Extension::ShouldDisplayInLauncher() const { |