| Index: chrome/common/extensions/extension.cc
|
| ===================================================================
|
| --- chrome/common/extensions/extension.cc (revision 123221)
|
| +++ chrome/common/extensions/extension.cc (working copy)
|
| @@ -18,6 +18,7 @@
|
| #include "base/string16.h"
|
| #include "base/string_number_conversions.h"
|
| #include "base/string_piece.h"
|
| +#include "base/string_split.h"
|
| #include "base/string_util.h"
|
| #include "base/utf_string_conversions.h"
|
| #include "base/values.h"
|
| @@ -41,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"
|
| @@ -218,6 +220,104 @@
|
| Extension::TtsVoice::TtsVoice() {}
|
| Extension::TtsVoice::~TtsVoice() {}
|
|
|
| +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()) {
|
| + *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
|
| + errors::kInvalidKeyBinding,
|
| + base::IntToString(index),
|
| + "Missing");
|
| + return false;
|
| + }
|
| +
|
| + 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);
|
| + if (tokens.size() < 2 || tokens.size() > 3) {
|
| + *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
|
| + errors::kInvalidKeyBinding,
|
| + base::IntToString(index),
|
| + original_keybinding);
|
| + return false;
|
| + }
|
| +
|
| + // Now, parse it into an accelerator.
|
| + bool ctrl = false;
|
| + bool alt = false;
|
| + bool shift = false;
|
| + ui::KeyboardCode key = ui::VKEY_UNKNOWN;
|
| + for (size_t i = 0; i < tokens.size(); i++) {
|
| + if (tokens[i] == "ctrl") {
|
| + ctrl = true;
|
| + } else if (tokens[i] == "alt") {
|
| + alt = true;
|
| + } else if (tokens[i] == "shift") {
|
| + shift = true;
|
| + } else if (tokens[i].size() == 1 &&
|
| + base::ToUpperASCII(tokens[i][0]) >= ui::VKEY_A &&
|
| + base::ToUpperASCII(tokens[i][0]) <= ui::VKEY_Z) {
|
| + if (key != ui::VKEY_UNKNOWN) {
|
| + // Multiple key assignments.
|
| + key = ui::VKEY_UNKNOWN;
|
| + break;
|
| + }
|
| +
|
| + key = static_cast<ui::KeyboardCode>(
|
| + ui::VKEY_A + (base::ToUpperASCII(tokens[i][0]) - ui::VKEY_A));
|
| + } else {
|
| + *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
|
| + errors::kInvalidKeyBinding,
|
| + base::IntToString(index),
|
| + original_keybinding);
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + // 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.
|
| + if (key == ui::VKEY_UNKNOWN || (ctrl == true && alt == true)) {
|
| + *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
|
| + errors::kInvalidKeyBinding,
|
| + base::IntToString(index),
|
| + original_keybinding);
|
| + return false;
|
| + }
|
| +
|
| + accelerator_ = 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()) {
|
| + *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
|
| + errors::kInvalidKeyBindingDescription,
|
| + base::IntToString(index));
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + command_name_ = command_name;
|
| + return true;
|
| +}
|
| +
|
| //
|
| // Extension
|
| //
|
| @@ -857,7 +957,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;
|
| @@ -1158,7 +1258,7 @@
|
| !one_service->GetList(keys::kIntentType, &mime_types) ||
|
| mime_types->GetSize() == 0) {
|
| *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
|
| - errors::kInvalidIntentType,*iter);
|
| + errors::kInvalidIntentType, *iter);
|
| return false;
|
| }
|
|
|
| @@ -1173,7 +1273,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;
|
| @@ -1181,7 +1281,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);
|
| @@ -1715,6 +1815,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, command_index, error))
|
| + return false; // |error| already set.
|
| +
|
| + commands_.push_back(binding);
|
| + }
|
| + }
|
| +
|
| // Initialize icons (if present).
|
| if (manifest->HasKey(keys::kIcons)) {
|
| DictionaryValue* icons_value = NULL;
|
| @@ -2872,7 +3001,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;
|
| @@ -3028,7 +3157,6 @@
|
| // their positions should sync.
|
| return location_ == Extension::INTERNAL ||
|
| ShouldDisplayInLauncher();
|
| -
|
| }
|
|
|
| bool Extension::ShouldDisplayInLauncher() const {
|
|
|