OLD | NEW |
---|---|
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" |
(...skipping 24 matching lines...) Expand all Loading... | |
35 #include "chrome/common/extensions/file_browser_handler.h" | 35 #include "chrome/common/extensions/file_browser_handler.h" |
36 #include "chrome/common/extensions/manifest.h" | 36 #include "chrome/common/extensions/manifest.h" |
37 #include "chrome/common/extensions/user_script.h" | 37 #include "chrome/common/extensions/user_script.h" |
38 #include "chrome/common/url_constants.h" | 38 #include "chrome/common/url_constants.h" |
39 #include "googleurl/src/url_util.h" | 39 #include "googleurl/src/url_util.h" |
40 #include "grit/chromium_strings.h" | 40 #include "grit/chromium_strings.h" |
41 #include "grit/generated_resources.h" | 41 #include "grit/generated_resources.h" |
42 #include "grit/theme_resources.h" | 42 #include "grit/theme_resources.h" |
43 #include "net/base/registry_controlled_domain.h" | 43 #include "net/base/registry_controlled_domain.h" |
44 #include "third_party/skia/include/core/SkBitmap.h" | 44 #include "third_party/skia/include/core/SkBitmap.h" |
45 #include "ui/base/keycodes/keyboard_codes.h" | |
45 #include "ui/base/l10n/l10n_util.h" | 46 #include "ui/base/l10n/l10n_util.h" |
46 #include "ui/base/resource/resource_bundle.h" | 47 #include "ui/base/resource/resource_bundle.h" |
47 #include "webkit/glue/image_decoder.h" | 48 #include "webkit/glue/image_decoder.h" |
48 #include "webkit/glue/web_intent_service_data.h" | 49 #include "webkit/glue/web_intent_service_data.h" |
49 | 50 |
50 namespace keys = extension_manifest_keys; | 51 namespace keys = extension_manifest_keys; |
51 namespace values = extension_manifest_values; | 52 namespace values = extension_manifest_values; |
52 namespace errors = extension_manifest_errors; | 53 namespace errors = extension_manifest_errors; |
53 | 54 |
54 using extensions::csp_validator::ContentSecurityPolicyIsLegal; | 55 using extensions::csp_validator::ContentSecurityPolicyIsLegal; |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
212 shortcut_alt(false), | 213 shortcut_alt(false), |
213 shortcut_ctrl(false), | 214 shortcut_ctrl(false), |
214 shortcut_shift(false) { | 215 shortcut_shift(false) { |
215 } | 216 } |
216 | 217 |
217 Extension::InputComponentInfo::~InputComponentInfo() {} | 218 Extension::InputComponentInfo::~InputComponentInfo() {} |
218 | 219 |
219 Extension::TtsVoice::TtsVoice() {} | 220 Extension::TtsVoice::TtsVoice() {} |
220 Extension::TtsVoice::~TtsVoice() {} | 221 Extension::TtsVoice::~TtsVoice() {} |
221 | 222 |
223 Extension::ExtensionKeybinding::ExtensionKeybinding() {} | |
224 Extension::ExtensionKeybinding::~ExtensionKeybinding() {} | |
225 | |
226 bool Extension::ExtensionKeybinding::Parse(DictionaryValue* command, | |
227 const std::string& event_name, | |
228 string16* error, | |
229 int index) { | |
Matt Perry
2012/02/21 23:13:39
outparams (error) should go last
| |
230 std::string key_binding; | |
231 if (!command->GetString(keys::kKey, &key_binding)) { | |
232 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( | |
233 errors::kInvalidKeyBinding, | |
234 base::IntToString(index), | |
235 "Missing"); | |
236 return false; | |
237 } | |
238 | |
239 std::string original_keybinding = key_binding; | |
240 // Normalize '-' to '+'. | |
241 for (size_t pos = key_binding.find('-'); | |
242 pos != std::string::npos; | |
243 pos = key_binding.find('-')) { | |
244 key_binding.replace(pos, 1, "+"); | |
245 } | |
246 // Remove all spaces. | |
247 for (size_t pos = key_binding.find(' '); | |
248 pos != std::string::npos; | |
249 pos = key_binding.find(' ')) { | |
250 key_binding.replace(pos, 1, ""); | |
251 } | |
Matt Perry
2012/02/21 23:13:39
base::ReplaceSubstringsAfterOffset(&key_binding, 0
| |
252 // And finally, lower-case it. | |
253 key_binding = StringToLowerASCII(key_binding); | |
254 | |
255 // Now, parse it into an accelerator. | |
256 bool ctrl = false; | |
257 bool alt = false; | |
258 bool shift = false; | |
259 ui::KeyboardCode key = ui::VKEY_UNKNOWN; | |
260 // We support Ctrl+foo, Alt+foo, Ctrl+Shift+foo, Alt+Shift+foo, but not | |
261 // Ctrl+Alt+foo. For a more detailed reason why we don't support Ctrl+Alt+foo: | |
262 // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/29/101121.aspx. | |
263 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
| |
264 if ((position = key_binding.find("ctrl+")) != std::string::npos) { | |
265 ctrl = true; | |
266 key_binding = key_binding.replace(position, 5, ""); | |
267 } else if ((position = key_binding.find("alt+")) != std::string::npos) { | |
268 alt = true; | |
269 key_binding = key_binding.replace(position, 4, ""); | |
270 } | |
271 if ((position = key_binding.find("shift+")) != std::string::npos) { | |
272 shift = true; | |
273 key_binding = key_binding.replace(position, 6, ""); | |
274 } | |
275 // We've stripped everything from the string but the letter. | |
276 if (key_binding.size() != 1) { | |
277 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( | |
278 errors::kInvalidKeyBinding, | |
279 base::IntToString(index), | |
280 original_keybinding); | |
281 return false; | |
282 } | |
283 | |
284 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
| |
285 else if (key_binding.compare("b") == 0) key = ui::VKEY_B; | |
286 else if (key_binding.compare("c") == 0) key = ui::VKEY_C; | |
287 else if (key_binding.compare("d") == 0) key = ui::VKEY_D; | |
288 else if (key_binding.compare("e") == 0) key = ui::VKEY_E; | |
289 else if (key_binding.compare("f") == 0) key = ui::VKEY_F; | |
290 else if (key_binding.compare("g") == 0) key = ui::VKEY_G; | |
291 else if (key_binding.compare("h") == 0) key = ui::VKEY_H; | |
292 else if (key_binding.compare("i") == 0) key = ui::VKEY_I; | |
293 else if (key_binding.compare("j") == 0) key = ui::VKEY_J; | |
294 else if (key_binding.compare("k") == 0) key = ui::VKEY_K; | |
295 else if (key_binding.compare("l") == 0) key = ui::VKEY_L; | |
296 else if (key_binding.compare("m") == 0) key = ui::VKEY_M; | |
297 else if (key_binding.compare("n") == 0) key = ui::VKEY_N; | |
298 else if (key_binding.compare("o") == 0) key = ui::VKEY_O; | |
299 else if (key_binding.compare("p") == 0) key = ui::VKEY_P; | |
300 else if (key_binding.compare("q") == 0) key = ui::VKEY_Q; | |
301 else if (key_binding.compare("r") == 0) key = ui::VKEY_R; | |
302 else if (key_binding.compare("s") == 0) key = ui::VKEY_S; | |
303 else if (key_binding.compare("t") == 0) key = ui::VKEY_T; | |
304 else if (key_binding.compare("u") == 0) key = ui::VKEY_U; | |
305 else if (key_binding.compare("v") == 0) key = ui::VKEY_V; | |
306 else if (key_binding.compare("x") == 0) key = ui::VKEY_X; | |
307 else if (key_binding.compare("y") == 0) key = ui::VKEY_Y; | |
308 else if (key_binding.compare("z") == 0) key = ui::VKEY_Z; | |
309 | |
310 accelerator_ = ui::Accelerator(key, shift, ctrl, alt); | |
311 if (!command->GetString(keys::kDescription, &description_)) { | |
312 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( | |
313 errors::kInvalidKeyBindingDescription, | |
314 base::IntToString(index)); | |
315 return false; | |
316 } | |
317 | |
318 event_name_ = event_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 Loading... | |
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 Loading... | |
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 Loading... | |
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, error, command_index)) | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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) {} |
OLD | NEW |