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

Side by Side Diff: chrome/common/extensions/extension.cc

Issue 9402018: Experimental Extension Keybinding (first cut). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Comments addressed Created 8 years, 10 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/common/extensions/extension.h ('k') | chrome/common/extensions/extension_constants.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/common/extensions/extension.h" 5 #include "chrome/common/extensions/extension.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/base64.h" 9 #include "base/base64.h"
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/file_path.h" 12 #include "base/file_path.h"
13 #include "base/file_util.h" 13 #include "base/file_util.h"
14 #include "base/i18n/rtl.h" 14 #include "base/i18n/rtl.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/memory/singleton.h" 16 #include "base/memory/singleton.h"
17 #include "base/stl_util.h" 17 #include "base/stl_util.h"
18 #include "base/string16.h" 18 #include "base/string16.h"
19 #include "base/string_number_conversions.h" 19 #include "base/string_number_conversions.h"
20 #include "base/string_piece.h" 20 #include "base/string_piece.h"
21 #include "base/string_split.h"
21 #include "base/string_util.h" 22 #include "base/string_util.h"
22 #include "base/utf_string_conversions.h" 23 #include "base/utf_string_conversions.h"
23 #include "base/values.h" 24 #include "base/values.h"
24 #include "base/version.h" 25 #include "base/version.h"
25 #include "crypto/sha2.h" 26 #include "crypto/sha2.h"
26 #include "chrome/common/chrome_constants.h" 27 #include "chrome/common/chrome_constants.h"
27 #include "chrome/common/chrome_switches.h" 28 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/chrome_version_info.h" 29 #include "chrome/common/chrome_version_info.h"
29 #include "chrome/common/extensions/csp_validator.h" 30 #include "chrome/common/extensions/csp_validator.h"
30 #include "chrome/common/extensions/extension_action.h" 31 #include "chrome/common/extensions/extension_action.h"
31 #include "chrome/common/extensions/extension_constants.h" 32 #include "chrome/common/extensions/extension_constants.h"
32 #include "chrome/common/extensions/extension_error_utils.h" 33 #include "chrome/common/extensions/extension_error_utils.h"
33 #include "chrome/common/extensions/extension_l10n_util.h" 34 #include "chrome/common/extensions/extension_l10n_util.h"
34 #include "chrome/common/extensions/extension_resource.h" 35 #include "chrome/common/extensions/extension_resource.h"
35 #include "chrome/common/extensions/file_browser_handler.h" 36 #include "chrome/common/extensions/file_browser_handler.h"
36 #include "chrome/common/extensions/manifest.h" 37 #include "chrome/common/extensions/manifest.h"
37 #include "chrome/common/extensions/user_script.h" 38 #include "chrome/common/extensions/user_script.h"
38 #include "chrome/common/url_constants.h" 39 #include "chrome/common/url_constants.h"
39 #include "googleurl/src/url_util.h" 40 #include "googleurl/src/url_util.h"
40 #include "grit/chromium_strings.h" 41 #include "grit/chromium_strings.h"
41 #include "grit/generated_resources.h" 42 #include "grit/generated_resources.h"
42 #include "grit/theme_resources.h" 43 #include "grit/theme_resources.h"
43 #include "net/base/registry_controlled_domain.h" 44 #include "net/base/registry_controlled_domain.h"
44 #include "third_party/skia/include/core/SkBitmap.h" 45 #include "third_party/skia/include/core/SkBitmap.h"
46 #include "ui/base/keycodes/keyboard_codes.h"
45 #include "ui/base/l10n/l10n_util.h" 47 #include "ui/base/l10n/l10n_util.h"
46 #include "ui/base/resource/resource_bundle.h" 48 #include "ui/base/resource/resource_bundle.h"
47 #include "webkit/glue/image_decoder.h" 49 #include "webkit/glue/image_decoder.h"
48 #include "webkit/glue/web_intent_service_data.h" 50 #include "webkit/glue/web_intent_service_data.h"
49 51
50 namespace keys = extension_manifest_keys; 52 namespace keys = extension_manifest_keys;
51 namespace values = extension_manifest_values; 53 namespace values = extension_manifest_values;
52 namespace errors = extension_manifest_errors; 54 namespace errors = extension_manifest_errors;
53 55
54 using extensions::csp_validator::ContentSecurityPolicyIsLegal; 56 using extensions::csp_validator::ContentSecurityPolicyIsLegal;
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 shortcut_alt(false), 214 shortcut_alt(false),
213 shortcut_ctrl(false), 215 shortcut_ctrl(false),
214 shortcut_shift(false) { 216 shortcut_shift(false) {
215 } 217 }
216 218
217 Extension::InputComponentInfo::~InputComponentInfo() {} 219 Extension::InputComponentInfo::~InputComponentInfo() {}
218 220
219 Extension::TtsVoice::TtsVoice() {} 221 Extension::TtsVoice::TtsVoice() {}
220 Extension::TtsVoice::~TtsVoice() {} 222 Extension::TtsVoice::~TtsVoice() {}
221 223
224 Extension::ExtensionKeybinding::ExtensionKeybinding() {}
225 Extension::ExtensionKeybinding::~ExtensionKeybinding() {}
226
227 bool Extension::ExtensionKeybinding::Parse(DictionaryValue* command,
228 const std::string& command_name,
229 int index,
230 string16* error) {
231 DCHECK(!command_name.empty());
232 std::string key_binding;
233 if (!command->GetString(keys::kKey, &key_binding) ||
234 key_binding.empty()) {
235 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
236 errors::kInvalidKeyBinding,
237 base::IntToString(index),
238 "Missing");
239 return false;
240 }
241
242 std::string original_keybinding = key_binding;
243 // Normalize '-' to '+'.
244 ReplaceSubstringsAfterOffset(&key_binding, 0, "-", "+");
245 // Remove all spaces.
246 ReplaceSubstringsAfterOffset(&key_binding, 0, " ", "");
247 // And finally, lower-case it.
248 key_binding = StringToLowerASCII(key_binding);
249
250 std::vector<std::string> tokens;
251 base::SplitString(key_binding, '+', &tokens);
252 if (tokens.size() < 2 || tokens.size() > 3) {
253 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
254 errors::kInvalidKeyBinding,
255 base::IntToString(index),
256 original_keybinding);
257 return false;
258 }
259
260 // Now, parse it into an accelerator.
261 bool ctrl = false;
262 bool alt = false;
263 bool shift = false;
264 ui::KeyboardCode key = ui::VKEY_UNKNOWN;
265 for (size_t i = 0; i < tokens.size(); i++) {
266 if (tokens[i] == "ctrl") {
267 ctrl = true;
268 } else if (tokens[i] == "alt") {
269 alt = true;
270 } else if (tokens[i] == "shift") {
271 shift = true;
272 } else if (tokens[i].size() == 1 &&
273 base::ToUpperASCII(tokens[i][0]) >= ui::VKEY_A &&
Matt Perry 2012/02/22 23:59:42 Just use 'a' so you don't have to uppercase it. Al
274 base::ToUpperASCII(tokens[i][0]) <= ui::VKEY_Z) {
275 if (key != ui::VKEY_UNKNOWN) {
276 // Multiple key assignments.
277 key = ui::VKEY_UNKNOWN;
278 break;
279 }
280
281 key = static_cast<ui::KeyboardCode>(
282 ui::VKEY_A + (base::ToUpperASCII(tokens[i][0]) - ui::VKEY_A));
Matt Perry 2012/02/22 23:59:42 see above, second VKEY_A => 'a'
283 } else {
284 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
285 errors::kInvalidKeyBinding,
286 base::IntToString(index),
287 original_keybinding);
288 return false;
289 }
290 }
291
292 // We support Ctrl+foo, Alt+foo, Ctrl+Shift+foo, Alt+Shift+foo, but not
293 // Ctrl+Alt+foo. For a more detailed reason why we don't support Ctrl+Alt+foo:
294 // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/29/101121.aspx.
295 if (key == ui::VKEY_UNKNOWN || ctrl == true && alt == true) {
Matt Perry 2012/02/22 23:59:42 Please add parens around (ctrl == true && alt == t
296 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
297 errors::kInvalidKeyBinding,
298 base::IntToString(index),
299 original_keybinding);
300 return false;
301 }
302
303 accelerator_ = ui::Accelerator(key, shift, ctrl, alt);
304
305 if (command_name !=
306 extension_manifest_values::kPageActionKeybindingEvent &&
307 command_name !=
308 extension_manifest_values::kBrowserActionKeybindingEvent) {
309 if (!command->GetString(keys::kDescription, &description_) ||
310 description_.empty()) {
311 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
312 errors::kInvalidKeyBindingDescription,
313 base::IntToString(index));
314 return false;
315 }
316 }
317
318 command_name_ = command_name;
319 return true;
320 }
321
222 // 322 //
223 // Extension 323 // Extension
224 // 324 //
225 325
226 // static 326 // static
227 scoped_refptr<Extension> Extension::Create(const FilePath& path, 327 scoped_refptr<Extension> Extension::Create(const FilePath& path,
228 Location location, 328 Location location,
229 const DictionaryValue& value, 329 const DictionaryValue& value,
230 int flags, 330 int flags,
231 std::string* utf8_error) { 331 std::string* utf8_error) {
(...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 errors::kInvalidURLPatternError, filter); 951 errors::kInvalidURLPatternError, filter);
852 return NULL; 952 return NULL;
853 } 953 }
854 result->AddPattern(pattern); 954 result->AddPattern(pattern);
855 } 955 }
856 956
857 std::string default_icon; 957 std::string default_icon;
858 // Read the file browser action |default_icon| (optional). 958 // Read the file browser action |default_icon| (optional).
859 if (file_browser_handler->HasKey(keys::kPageActionDefaultIcon)) { 959 if (file_browser_handler->HasKey(keys::kPageActionDefaultIcon)) {
860 if (!file_browser_handler->GetString( 960 if (!file_browser_handler->GetString(
861 keys::kPageActionDefaultIcon,&default_icon) || 961 keys::kPageActionDefaultIcon, &default_icon) ||
862 default_icon.empty()) { 962 default_icon.empty()) {
863 *error = ASCIIToUTF16(errors::kInvalidPageActionIconPath); 963 *error = ASCIIToUTF16(errors::kInvalidPageActionIconPath);
864 return NULL; 964 return NULL;
865 } 965 }
866 result->set_icon_path(default_icon); 966 result->set_icon_path(default_icon);
867 } 967 }
868 968
869 return result.release(); 969 return result.release();
870 } 970 }
871 971
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
1155 *error = ASCIIToUTF16(errors::kInvalidIntent); 1255 *error = ASCIIToUTF16(errors::kInvalidIntent);
1156 return false; 1256 return false;
1157 } 1257 }
1158 service.action = UTF8ToUTF16(*iter); 1258 service.action = UTF8ToUTF16(*iter);
1159 1259
1160 ListValue* mime_types = NULL; 1260 ListValue* mime_types = NULL;
1161 if (!one_service->HasKey(keys::kIntentType) || 1261 if (!one_service->HasKey(keys::kIntentType) ||
1162 !one_service->GetList(keys::kIntentType, &mime_types) || 1262 !one_service->GetList(keys::kIntentType, &mime_types) ||
1163 mime_types->GetSize() == 0) { 1263 mime_types->GetSize() == 0) {
1164 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( 1264 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1165 errors::kInvalidIntentType,*iter); 1265 errors::kInvalidIntentType, *iter);
1166 return false; 1266 return false;
1167 } 1267 }
1168 1268
1169 if (one_service->HasKey(keys::kIntentPath)) { 1269 if (one_service->HasKey(keys::kIntentPath)) {
1170 if (!one_service->GetString(keys::kIntentPath, &value)) { 1270 if (!one_service->GetString(keys::kIntentPath, &value)) {
1171 *error = ASCIIToUTF16(errors::kInvalidIntentPath); 1271 *error = ASCIIToUTF16(errors::kInvalidIntentPath);
1172 return false; 1272 return false;
1173 } 1273 }
1174 if (is_hosted_app()) { 1274 if (is_hosted_app()) {
1175 // Hosted apps require an absolute URL for intents. 1275 // Hosted apps require an absolute URL for intents.
1176 GURL service_url(value); 1276 GURL service_url(value);
1177 if (!service_url.is_valid() || 1277 if (!service_url.is_valid() ||
1178 !(web_extent().MatchesURL(service_url))) { 1278 !(web_extent().MatchesURL(service_url))) {
1179 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( 1279 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1180 errors::kInvalidIntentPageInHostedApp,*iter); 1280 errors::kInvalidIntentPageInHostedApp, *iter);
1181 return false; 1281 return false;
1182 } 1282 }
1183 service.service_url = service_url; 1283 service.service_url = service_url;
1184 } else { 1284 } else {
1185 // We do not allow absolute intent URLs in non-hosted apps. 1285 // We do not allow absolute intent URLs in non-hosted apps.
1186 if (GURL(value).is_valid()) { 1286 if (GURL(value).is_valid()) {
1187 *error =ExtensionErrorUtils::FormatErrorMessageUTF16( 1287 *error =ExtensionErrorUtils::FormatErrorMessageUTF16(
1188 errors::kCannotAccessPage,value.c_str()); 1288 errors::kCannotAccessPage, value.c_str());
1189 return false; 1289 return false;
1190 } 1290 }
1191 service.service_url = GetResourceURL(value); 1291 service.service_url = GetResourceURL(value);
1192 } 1292 }
1193 } 1293 }
1194 1294
1195 if (one_service->HasKey(keys::kIntentTitle) && 1295 if (one_service->HasKey(keys::kIntentTitle) &&
1196 !one_service->GetString(keys::kIntentTitle, &service.title)) { 1296 !one_service->GetString(keys::kIntentTitle, &service.title)) {
1197 *error = ASCIIToUTF16(errors::kInvalidIntentTitle); 1297 *error = ASCIIToUTF16(errors::kInvalidIntentTitle);
1198 return false; 1298 return false;
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
1712 minimum_version_string); 1812 minimum_version_string);
1713 return false; 1813 return false;
1714 } 1814 }
1715 } 1815 }
1716 1816
1717 // Initialize converted_from_user_script (if present) 1817 // Initialize converted_from_user_script (if present)
1718 if (manifest->HasKey(keys::kConvertedFromUserScript)) 1818 if (manifest->HasKey(keys::kConvertedFromUserScript))
1719 manifest->GetBoolean(keys::kConvertedFromUserScript, 1819 manifest->GetBoolean(keys::kConvertedFromUserScript,
1720 &converted_from_user_script_); 1820 &converted_from_user_script_);
1721 1821
1822 // Initialize commands (if present).
1823 if (manifest->HasKey(keys::kCommands)) {
1824 DictionaryValue* commands = NULL;
1825 if (!manifest->GetDictionary(keys::kCommands, &commands)) {
1826 *error = ASCIIToUTF16(errors::kInvalidCommandsKey);
1827 return false;
1828 }
1829
1830 int command_index = 0;
1831 for (DictionaryValue::key_iterator iter = commands->begin_keys();
1832 iter != commands->end_keys(); ++iter) {
1833 ++command_index;
1834
1835 DictionaryValue* command = NULL;
1836 if (!commands->GetDictionary(*iter, &command)) {
1837 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1838 errors::kInvalidKeyBindingDictionary,
1839 base::IntToString(command_index));
1840 return false;
1841 }
1842
1843 ExtensionKeybinding binding;
1844 if (!binding.Parse(command, *iter, command_index, error))
1845 return false; // |error| already set.
1846
1847 commands_.push_back(binding);
1848 }
1849 }
1850
1722 // Initialize icons (if present). 1851 // Initialize icons (if present).
1723 if (manifest->HasKey(keys::kIcons)) { 1852 if (manifest->HasKey(keys::kIcons)) {
1724 DictionaryValue* icons_value = NULL; 1853 DictionaryValue* icons_value = NULL;
1725 if (!manifest->GetDictionary(keys::kIcons, &icons_value)) { 1854 if (!manifest->GetDictionary(keys::kIcons, &icons_value)) {
1726 *error = ASCIIToUTF16(errors::kInvalidIcons); 1855 *error = ASCIIToUTF16(errors::kInvalidIcons);
1727 return false; 1856 return false;
1728 } 1857 }
1729 1858
1730 for (size_t i = 0; i < arraysize(kIconSizes); ++i) { 1859 for (size_t i = 0; i < arraysize(kIconSizes); ++i) {
1731 std::string key = base::IntToString(kIconSizes[i]); 1860 std::string key = base::IntToString(kIconSizes[i]);
(...skipping 1143 matching lines...) Expand 10 before | Expand all | Expand 10 after
2875 3004
2876 if (permission->id() == ExtensionAPIPermission::kExperimental) { 3005 if (permission->id() == ExtensionAPIPermission::kExperimental) {
2877 if (!CanSpecifyExperimentalPermission()) { 3006 if (!CanSpecifyExperimentalPermission()) {
2878 *error = ASCIIToUTF16(errors::kExperimentalFlagRequired); 3007 *error = ASCIIToUTF16(errors::kExperimentalFlagRequired);
2879 return false; 3008 return false;
2880 } 3009 }
2881 } 3010 }
2882 3011
2883 bool supports_type = false; 3012 bool supports_type = false;
2884 switch (GetType()) { 3013 switch (GetType()) {
2885 case TYPE_USER_SCRIPT: // Pass through. 3014 case TYPE_USER_SCRIPT: // Pass through.
2886 case TYPE_EXTENSION: 3015 case TYPE_EXTENSION:
2887 supports_type = permission->supports_extensions(); 3016 supports_type = permission->supports_extensions();
2888 break; 3017 break;
2889 case TYPE_HOSTED_APP: 3018 case TYPE_HOSTED_APP:
2890 supports_type = permission->supports_hosted_apps(); 3019 supports_type = permission->supports_hosted_apps();
2891 break; 3020 break;
2892 case TYPE_PACKAGED_APP: 3021 case TYPE_PACKAGED_APP:
2893 supports_type = permission->supports_packaged_apps(); 3022 supports_type = permission->supports_packaged_apps();
2894 break; 3023 break;
2895 case TYPE_PLATFORM_APP: 3024 case TYPE_PLATFORM_APP:
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
3031 } 3160 }
3032 } 3161 }
3033 3162
3034 bool Extension::IsSyncable() const { 3163 bool Extension::IsSyncable() const {
3035 // TODO(akalin): Figure out if we need to allow some other types. 3164 // TODO(akalin): Figure out if we need to allow some other types.
3036 3165
3037 // We want to sync any extensions that are shown in the luancher because 3166 // We want to sync any extensions that are shown in the luancher because
3038 // their positions should sync. 3167 // their positions should sync.
3039 return location_ == Extension::INTERNAL || 3168 return location_ == Extension::INTERNAL ||
3040 ShouldDisplayInLauncher(); 3169 ShouldDisplayInLauncher();
3041
3042 } 3170 }
3043 3171
3044 bool Extension::ShouldDisplayInLauncher() const { 3172 bool Extension::ShouldDisplayInLauncher() const {
3045 // All apps should be displayed on the NTP except for the Cloud Print App. 3173 // All apps should be displayed on the NTP except for the Cloud Print App.
3046 return is_app() && id() != extension_misc::kCloudPrintAppId; 3174 return is_app() && id() != extension_misc::kCloudPrintAppId;
3047 } 3175 }
3048 3176
3049 ExtensionInfo::ExtensionInfo(const DictionaryValue* manifest, 3177 ExtensionInfo::ExtensionInfo(const DictionaryValue* manifest,
3050 const std::string& id, 3178 const std::string& id,
3051 const FilePath& path, 3179 const FilePath& path,
(...skipping 29 matching lines...) Expand all
3081 already_disabled(false), 3209 already_disabled(false),
3082 extension(extension) {} 3210 extension(extension) {}
3083 3211
3084 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( 3212 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo(
3085 const Extension* extension, 3213 const Extension* extension,
3086 const ExtensionPermissionSet* permissions, 3214 const ExtensionPermissionSet* permissions,
3087 Reason reason) 3215 Reason reason)
3088 : reason(reason), 3216 : reason(reason),
3089 extension(extension), 3217 extension(extension),
3090 permissions(permissions) {} 3218 permissions(permissions) {}
OLDNEW
« no previous file with comments | « chrome/common/extensions/extension.h ('k') | chrome/common/extensions/extension_constants.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698