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

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

Issue 9424009: Cleaning up Extension::InitFromValue() (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Requested changed made 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 unified diff | Download patch
« no previous file with comments | « chrome/common/extensions/extension.h ('k') | no next file » | 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"
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 utf8_error); 326 utf8_error);
327 } 327 }
328 328
329 scoped_refptr<Extension> Extension::Create(const FilePath& path, 329 scoped_refptr<Extension> Extension::Create(const FilePath& path,
330 Location location, 330 Location location,
331 const DictionaryValue& value, 331 const DictionaryValue& value,
332 int flags, 332 int flags,
333 const std::string& explicit_id, 333 const std::string& explicit_id,
334 std::string* utf8_error) { 334 std::string* utf8_error) {
335 DCHECK(utf8_error); 335 DCHECK(utf8_error);
336
337 string16 error; 336 string16 error;
338 scoped_ptr<extensions::Manifest> manifest( 337 scoped_ptr<extensions::Manifest> manifest(
339 new extensions::Manifest( 338 new extensions::Manifest(
340 location, 339 location,
341 scoped_ptr<DictionaryValue>(value.DeepCopy()))); 340 scoped_ptr<DictionaryValue>(value.DeepCopy())));
342 341
343 if (!InitExtensionID(manifest.get(), path, explicit_id, flags, &error) || 342 if (!InitExtensionID(manifest.get(), path, explicit_id, flags, &error) ||
344 !manifest->ValidateManifest(&error)) { 343 !manifest->ValidateManifest(&error)) {
345 *utf8_error = UTF16ToUTF8(error); 344 *utf8_error = UTF16ToUTF8(error);
346 return NULL; 345 return NULL;
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 DCHECK(StartsWithASCII(ret_val.spec(), extension_url.spec(), false)); 472 DCHECK(StartsWithASCII(ret_val.spec(), extension_url.spec(), false));
474 473
475 return ret_val; 474 return ret_val;
476 } 475 }
477 476
478 bool Extension::is_platform_app() const { 477 bool Extension::is_platform_app() const {
479 return manifest_->IsPlatformApp(); 478 return manifest_->IsPlatformApp();
480 } 479 }
481 480
482 bool Extension::is_hosted_app() const { 481 bool Extension::is_hosted_app() const {
483 return manifest()->IsHostedApp(); 482 return manifest()->IsHostedApp();
484 } 483 }
485 484
486 bool Extension::is_packaged_app() const { 485 bool Extension::is_packaged_app() const {
487 return manifest()->IsPackagedApp(); 486 return manifest()->IsPackagedApp();
488 } 487 }
489 488
490 bool Extension::is_theme() const { 489 bool Extension::is_theme() const {
491 return manifest()->IsTheme(); 490 return manifest()->IsTheme();
492 } 491 }
493 492
494 GURL Extension::GetBackgroundURL() const { 493 GURL Extension::GetBackgroundURL() const {
495 if (!background_scripts_.empty()) { 494 if (!background_scripts_.empty()) {
496 return GetResourceURL( 495 return GetResourceURL(
497 extension_filenames::kGeneratedBackgroundPageFilename); 496 extension_filenames::kGeneratedBackgroundPageFilename);
(...skipping 30 matching lines...) Expand all
528 *output = StringToLowerASCII(base::HexEncode(hash, sizeof(hash))); 527 *output = StringToLowerASCII(base::HexEncode(hash, sizeof(hash)));
529 ConvertHexadecimalToIDAlphabet(output); 528 ConvertHexadecimalToIDAlphabet(output);
530 529
531 return true; 530 return true;
532 } 531 }
533 532
534 // Helper method that loads a UserScript object from a dictionary in the 533 // Helper method that loads a UserScript object from a dictionary in the
535 // content_script list of the manifest. 534 // content_script list of the manifest.
536 bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script, 535 bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
537 int definition_index, 536 int definition_index,
538 int flags,
539 string16* error, 537 string16* error,
540 UserScript* result) { 538 UserScript* result) {
541 // run_at 539 // run_at
542 if (content_script->HasKey(keys::kRunAt)) { 540 if (content_script->HasKey(keys::kRunAt)) {
543 std::string run_location; 541 std::string run_location;
544 if (!content_script->GetString(keys::kRunAt, &run_location)) { 542 if (!content_script->GetString(keys::kRunAt, &run_location)) {
545 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( 543 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
546 errors::kInvalidRunAt, 544 errors::kInvalidRunAt,
547 base::IntToString(definition_index)); 545 base::IntToString(definition_index));
548 return false; 546 return false;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 errors::kInvalidMatch, 607 errors::kInvalidMatch,
610 base::IntToString(definition_index), 608 base::IntToString(definition_index),
611 base::IntToString(j), 609 base::IntToString(j),
612 URLPattern::GetParseResultString(parse_result)); 610 URLPattern::GetParseResultString(parse_result));
613 return false; 611 return false;
614 } 612 }
615 613
616 if (pattern.MatchesScheme(chrome::kFileScheme) && 614 if (pattern.MatchesScheme(chrome::kFileScheme) &&
617 !CanExecuteScriptEverywhere()) { 615 !CanExecuteScriptEverywhere()) {
618 wants_file_access_ = true; 616 wants_file_access_ = true;
619 if (!(flags & ALLOW_FILE_ACCESS)) 617 if (!(creation_flags_ & ALLOW_FILE_ACCESS))
620 pattern.SetValidSchemes( 618 pattern.SetValidSchemes(
621 pattern.valid_schemes() & ~URLPattern::SCHEME_FILE); 619 pattern.valid_schemes() & ~URLPattern::SCHEME_FILE);
622 } 620 }
623 621
624 result->add_url_pattern(pattern); 622 result->add_url_pattern(pattern);
625 } 623 }
626 624
627 // exclude_matches 625 // exclude_matches
628 if (content_script->HasKey(keys::kExcludeMatches)) { // optional 626 if (content_script->HasKey(keys::kExcludeMatches)) { // optional
629 ListValue* exclude_matches = NULL; 627 ListValue* exclude_matches = NULL;
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 result->SetPopupUrl(ExtensionAction::kDefaultTabId, url); 883 result->SetPopupUrl(ExtensionAction::kDefaultTabId, url);
886 } else { 884 } else {
887 DCHECK(!result->HasPopup(ExtensionAction::kDefaultTabId)) 885 DCHECK(!result->HasPopup(ExtensionAction::kDefaultTabId))
888 << "Shouldn't be possible for the popup to be set."; 886 << "Shouldn't be possible for the popup to be set.";
889 } 887 }
890 } 888 }
891 889
892 return result.release(); 890 return result.release();
893 } 891 }
894 892
895 Extension::FileBrowserHandlerList* Extension::LoadFileBrowserHandlers( 893 // static
896 const ListValue* extension_actions, string16* error) { 894 bool Extension::InitExtensionID(extensions::Manifest* manifest,
897 scoped_ptr<FileBrowserHandlerList> result( 895 const FilePath& path,
898 new FileBrowserHandlerList()); 896 const std::string& explicit_id,
899 for (ListValue::const_iterator iter = extension_actions->begin(); 897 int creation_flags,
900 iter != extension_actions->end(); 898 string16* error) {
901 ++iter) { 899 if (!explicit_id.empty()) {
902 if (!(*iter)->IsType(Value::TYPE_DICTIONARY)) { 900 manifest->set_extension_id(explicit_id);
903 *error = ASCIIToUTF16(errors::kInvalidFileBrowserHandler); 901 return true;
904 return NULL; 902 }
903
904 if (manifest->HasKey(keys::kPublicKey)) {
905 std::string public_key;
906 std::string public_key_bytes;
907 std::string extension_id;
908 if (!manifest->GetString(keys::kPublicKey, &public_key) ||
909 !ParsePEMKeyBytes(public_key, &public_key_bytes) ||
910 !GenerateId(public_key_bytes, &extension_id)) {
911 *error = ASCIIToUTF16(errors::kInvalidKey);
912 return false;
905 } 913 }
906 scoped_ptr<FileBrowserHandler> action( 914 manifest->set_extension_id(extension_id);
907 LoadFileBrowserHandler( 915 return true;
908 reinterpret_cast<DictionaryValue*>(*iter), error));
909 if (!action.get())
910 return NULL; // Failed to parse file browser action definition.
911 result->push_back(linked_ptr<FileBrowserHandler>(action.release()));
912 } 916 }
913 return result.release(); 917
918 if (creation_flags & REQUIRE_KEY) {
919 *error = ASCIIToUTF16(errors::kInvalidKey);
920 return false;
921 } else {
922 // If there is a path, we generate the ID from it. This is useful for
923 // development mode, because it keeps the ID stable across restarts and
924 // reloading the extension.
925 std::string extension_id = GenerateIdForPath(path);
926 if (extension_id.empty()) {
927 NOTREACHED() << "Could not create ID from path.";
928 return false;
929 }
930 manifest->set_extension_id(extension_id);
931 return true;
932 }
914 } 933 }
915 934
916 FileBrowserHandler* Extension::LoadFileBrowserHandler( 935 bool Extension::CheckMinimumChromeVersion(string16* error) {
917 const DictionaryValue* file_browser_handler, string16* error) { 936 if (!manifest_->HasKey(keys::kMinimumChromeVersion))
918 scoped_ptr<FileBrowserHandler> result( 937 return true;
919 new FileBrowserHandler()); 938 std::string minimum_version_string;
920 result->set_extension_id(id()); 939 if (!manifest_->GetString(keys::kMinimumChromeVersion,
921 940 &minimum_version_string)) {
922 std::string id; 941 *error = ASCIIToUTF16(errors::kInvalidMinimumChromeVersion);
923 // Read the file action |id| (mandatory). 942 return false;
924 if (!file_browser_handler->HasKey(keys::kPageActionId) ||
925 !file_browser_handler->GetString(keys::kPageActionId, &id)) {
926 *error = ASCIIToUTF16(errors::kInvalidPageActionId);
927 return NULL;
928 }
929 result->set_id(id);
930
931 // Read the page action title from |default_title| (mandatory).
932 std::string title;
933 if (!file_browser_handler->HasKey(keys::kPageActionDefaultTitle) ||
934 !file_browser_handler->GetString(keys::kPageActionDefaultTitle, &title)) {
935 *error = ASCIIToUTF16(errors::kInvalidPageActionDefaultTitle);
936 return NULL;
937 }
938 result->set_title(title);
939
940 // Initialize file filters (mandatory).
941 ListValue* list_value = NULL;
942 if (!file_browser_handler->HasKey(keys::kFileFilters) ||
943 !file_browser_handler->GetList(keys::kFileFilters, &list_value) ||
944 list_value->empty()) {
945 *error = ASCIIToUTF16(errors::kInvalidFileFiltersList);
946 return NULL;
947 }
948 for (size_t i = 0; i < list_value->GetSize(); ++i) {
949 std::string filter;
950 if (!list_value->GetString(i, &filter)) {
951 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
952 errors::kInvalidFileFilterValue, base::IntToString(i));
953 return NULL;
954 }
955 StringToLowerASCII(&filter);
956 URLPattern pattern(URLPattern::SCHEME_FILESYSTEM);
957 if (pattern.Parse(filter) != URLPattern::PARSE_SUCCESS) {
958 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
959 errors::kInvalidURLPatternError, filter);
960 return NULL;
961 }
962 std::string path = pattern.path();
963 bool allowed = path == "*" || path == "*.*" ||
964 (path.compare(0, 2, "*.") == 0 &&
965 path.find_first_of('*', 2) == std::string::npos);
966 if (!allowed) {
967 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
968 errors::kInvalidURLPatternError, filter);
969 return NULL;
970 }
971 result->AddPattern(pattern);
972 } 943 }
973 944
974 std::string default_icon; 945 scoped_ptr<Version> minimum_version(
975 // Read the file browser action |default_icon| (optional). 946 Version::GetVersionFromString(minimum_version_string));
976 if (file_browser_handler->HasKey(keys::kPageActionDefaultIcon)) { 947 if (!minimum_version.get()) {
977 if (!file_browser_handler->GetString( 948 *error = ASCIIToUTF16(errors::kInvalidMinimumChromeVersion);
978 keys::kPageActionDefaultIcon, &default_icon) || 949 return false;
979 default_icon.empty()) {
980 *error = ASCIIToUTF16(errors::kInvalidPageActionIconPath);
981 return NULL;
982 }
983 result->set_icon_path(default_icon);
984 } 950 }
985 951
986 return result.release(); 952 chrome::VersionInfo current_version_info;
953 if (!current_version_info.is_valid()) {
954 NOTREACHED();
955 return false;
956 }
957
958 scoped_ptr<Version> current_version(
959 Version::GetVersionFromString(current_version_info.Version()));
960 if (!current_version.get()) {
961 DCHECK(false);
962 return false;
963 }
964
965 if (current_version->CompareTo(*minimum_version) < 0) {
966 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
967 errors::kChromeVersionTooLow,
968 l10n_util::GetStringUTF8(IDS_PRODUCT_NAME),
969 minimum_version_string);
970 return false;
971 }
972 return true;
973 }
974
975 bool Extension::LoadRequiredFeatures(string16* error) {
Yoyo Zhou 2012/03/02 20:20:07 So, the required features are actually name and ve
Devlin 2012/03/07 04:18:54 Done.
976 if (!LoadName(error) ||
977 !LoadDescription(error))
978 return false;
979 return true;
980 }
981
982 bool Extension::LoadName(string16* error) {
983 string16 localized_name;
984 if (!manifest_->GetString(keys::kName, &localized_name)) {
985 *error = ASCIIToUTF16(errors::kInvalidName);
986 return false;
987 }
988 base::i18n::AdjustStringForLocaleDirection(&localized_name);
989 name_ = UTF16ToUTF8(localized_name);
990 return true;
991 }
992
993 bool Extension::LoadDescription(string16* error) {
994 if (manifest_->HasKey(keys::kDescription) &&
995 !manifest_->GetString(keys::kDescription, &description_)) {
996 *error = ASCIIToUTF16(errors::kInvalidDescription);
997 return false;
998 }
999 return true;
1000 }
1001
1002 bool Extension::LoadAppFeatures(string16* error) {
1003 if (!LoadExtent(keys::kWebURLs, &extent_,
1004 errors::kInvalidWebURLs, errors::kInvalidWebURL, error) ||
1005 !LoadLaunchURL(error) ||
1006 !LoadLaunchContainer(error))
1007 return false;
1008
1009 if (is_platform_app()) {
Yoyo Zhou 2012/03/02 20:20:07 This block looks like it should go in LoadLaunchCo
Devlin 2012/03/07 04:18:54 Done.
1010 if (launch_container() != extension_misc::LAUNCH_SHELL) {
Yoyo Zhou 2012/03/02 20:20:07 style nit: Can you change these to launch_containe
Devlin 2012/03/07 04:18:54 Done.
1011 *error = ASCIIToUTF16(errors::kInvalidLaunchContainerForPlatform);
1012 return false;
1013 }
1014 } else if (launch_container() == extension_misc::LAUNCH_SHELL) {
1015 *error = ASCIIToUTF16(errors::kInvalidLaunchContainerForNonPlatform);
1016 return false;
1017 }
1018
1019 return true;
987 } 1020 }
988 1021
989 bool Extension::LoadExtent(const char* key, 1022 bool Extension::LoadExtent(const char* key,
990 URLPatternSet* extent, 1023 URLPatternSet* extent,
991 const char* list_error, 1024 const char* list_error,
992 const char* value_error, 1025 const char* value_error,
993 string16* error) { 1026 string16* error) {
994 Value* temp = NULL; 1027 Value* temp = NULL;
995 if (!manifest_->Get(key, &temp)) 1028 if (!manifest_->Get(key, &temp))
996 return true; 1029 return true;
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 GURL::Replacements replacements; 1193 GURL::Replacements replacements;
1161 replacements.SetPathStr(path); 1194 replacements.SetPathStr(path);
1162 GURL cloud_print_enable_connector_url = 1195 GURL cloud_print_enable_connector_url =
1163 cloud_print_service_url.ReplaceComponents(replacements); 1196 cloud_print_service_url.ReplaceComponents(replacements);
1164 OverrideLaunchUrl(cloud_print_enable_connector_url); 1197 OverrideLaunchUrl(cloud_print_enable_connector_url);
1165 } 1198 }
1166 } 1199 }
1167 return true; 1200 return true;
1168 } 1201 }
1169 1202
1170 bool ReadLaunchDimension(const extensions::Manifest* manifest, 1203 bool ReadLaunchDimension(const extensions::Manifest* manifest,
Yoyo Zhou 2012/03/02 20:20:07 Functions like this should go in the anonymous nam
Devlin 2012/03/07 04:18:54 Done.
1171 const char* key, 1204 const char* key,
1172 int* target, 1205 int* target,
1173 bool is_valid_container, 1206 bool is_valid_container,
1174 string16* error) { 1207 string16* error) {
1175 Value* temp = NULL; 1208 Value* temp = NULL;
1176 if (manifest->Get(key, &temp)) { 1209 if (manifest->Get(key, &temp)) {
1177 if (!is_valid_container) { 1210 if (!is_valid_container) {
1178 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( 1211 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1179 errors::kInvalidLaunchValueContainer, 1212 errors::kInvalidLaunchValueContainer,
1180 key); 1213 key);
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1286 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( 1319 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1287 errors::kInvalidLaunchValue, 1320 errors::kInvalidLaunchValue,
1288 keys::kLaunchMaxHeight); 1321 keys::kLaunchMaxHeight);
1289 return false; 1322 return false;
1290 } 1323 }
1291 } 1324 }
1292 1325
1293 return true; 1326 return true;
1294 } 1327 }
1295 1328
1296 bool Extension::LoadAppIsolation(string16* error) { 1329 bool Extension::LoadSharedFeatures(
1297 Value* temp = NULL; 1330 const ExtensionAPIPermissionSet& api_permissions,
1298 if (!manifest_->Get(keys::kIsolation, &temp)) 1331 string16* error) {
1299 return true; 1332 if (!LoadVersion(error) ||
1300 1333 !LoadManifestVersion(error) ||
1301 if (temp->GetType() != Value::TYPE_LIST) { 1334 !LoadHomepageURL(error) ||
1302 *error = ASCIIToUTF16(errors::kInvalidIsolation); 1335 !LoadUpdateURL(error) ||
1303 return false; 1336 !LoadIcons(error) ||
1304 } 1337 !LoadCommands(error) ||
1305 1338 !LoadPlugins(error) ||
1306 ListValue* isolation_list = static_cast<ListValue*>(temp); 1339 !LoadNaClModules(error) ||
1307 for (size_t i = 0; i < isolation_list->GetSize(); ++i) { 1340 !LoadWebAccessibleResources(error) ||
1308 std::string isolation_string; 1341 !LoadRequirements(error) ||
1309 if (!isolation_list->GetString(i, &isolation_string)) { 1342 !LoadDefaultLocale(error) ||
1310 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( 1343 !LoadOfflineEnabled(error) ||
1311 errors::kInvalidIsolationValue, 1344 !LoadOptionsPage(error) ||
1312 base::UintToString(i)); 1345 // LoadBackgroundScripts() must be called before LoadBackgroundPage().
1313 return false; 1346 !LoadBackgroundScripts(error) ||
1314 } 1347 !LoadBackgroundPage(api_permissions, error) ||
1315 1348 !LoadBackgroundPersistent(api_permissions, error) ||
1316 // Check for isolated storage. 1349 !LoadWebIntentServices(error))
1317 if (isolation_string == values::kIsolatedStorage) { 1350 return false;
1318 is_storage_isolated_ = true; 1351
1319 } else { 1352 return true;
1320 DLOG(WARNING) << "Did not recognize isolation type: " 1353 }
1321 << isolation_string; 1354
1322 } 1355 bool Extension::LoadVersion(string16* error) {
1323 } 1356 std::string version_str;
1324 return true; 1357 if (!manifest_->GetString(keys::kVersion, &version_str)) {
1325 } 1358 *error = ASCIIToUTF16(errors::kInvalidVersion);
1326 1359 return false;
1327 bool Extension::LoadWebIntentServices(string16* error) { 1360 }
1328 DCHECK(error); 1361 version_.reset(Version::GetVersionFromString(version_str));
1329 1362 if (!version_.get() ||
1330 if (!manifest_->HasKey(keys::kIntents)) 1363 version_->components().size() > 4) {
1331 return true; 1364 *error = ASCIIToUTF16(errors::kInvalidVersion);
1332 1365 return false;
1333 DictionaryValue* all_services = NULL; 1366 }
1334 if (!manifest_->GetDictionary(keys::kIntents, &all_services)) { 1367 return true;
1335 *error = ASCIIToUTF16(errors::kInvalidIntents); 1368 }
1336 return false; 1369
1337 } 1370 bool Extension::LoadManifestVersion(string16* error) {
1338 1371 // Get the original value out of the dictionary so that we can validate it
1339 std::string value; 1372 // more strictly.
1340 for (DictionaryValue::key_iterator iter(all_services->begin_keys()); 1373 if (manifest_->value()->HasKey(keys::kManifestVersion)) {
1341 iter != all_services->end_keys(); ++iter) { 1374 int manifest_version = 1;
1342 webkit_glue::WebIntentServiceData service; 1375 if (!manifest_->GetInteger(keys::kManifestVersion, &manifest_version) ||
1343 1376 manifest_version < 1) {
1344 DictionaryValue* one_service = NULL; 1377 *error = ASCIIToUTF16(errors::kInvalidManifestVersion);
1345 if (!all_services->GetDictionaryWithoutPathExpansion(*iter, &one_service)) { 1378 return false;
1346 *error = ASCIIToUTF16(errors::kInvalidIntent); 1379 }
1347 return false; 1380 }
1348 } 1381
1349 service.action = UTF8ToUTF16(*iter); 1382 manifest_version_ = manifest_->GetManifestVersion();
1350 1383 if (creation_flags_ & REQUIRE_MODERN_MANIFEST_VERSION &&
1351 ListValue* mime_types = NULL; 1384 manifest_version_ < kModernManifestVersion &&
1352 if (!one_service->HasKey(keys::kIntentType) || 1385 !CommandLine::ForCurrentProcess()->HasSwitch(
1353 !one_service->GetList(keys::kIntentType, &mime_types) || 1386 switches::kAllowLegacyExtensionManifests)) {
1354 mime_types->GetSize() == 0) { 1387 *error = ASCIIToUTF16(errors::kInvalidManifestVersion);
1355 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( 1388 return false;
1356 errors::kInvalidIntentType, *iter); 1389 }
1357 return false; 1390
1358 } 1391 return true;
1359 1392 }
1360 if (one_service->HasKey(keys::kIntentPath)) { 1393
1361 if (!one_service->GetString(keys::kIntentPath, &value)) { 1394 bool Extension::LoadHomepageURL(string16* error) {
1362 *error = ASCIIToUTF16(errors::kInvalidIntentPath); 1395 if (!manifest_->HasKey(keys::kHomepageURL))
1396 return true;
1397 std::string tmp;
1398 if (!manifest_->GetString(keys::kHomepageURL, &tmp)) {
1399 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1400 errors::kInvalidHomepageURL, "");
1401 return false;
1402 }
1403 homepage_url_ = GURL(tmp);
1404 if (!homepage_url_.is_valid() ||
1405 (!homepage_url_.SchemeIs("http") &&
1406 !homepage_url_.SchemeIs("https"))) {
1407 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1408 errors::kInvalidHomepageURL, tmp);
1409 return false;
1410 }
1411 return true;
1412 }
1413
1414 bool Extension::LoadUpdateURL(string16* error) {
1415 if (!manifest_->HasKey(keys::kUpdateURL))
1416 return true;
1417 std::string tmp;
1418 if (!manifest_->GetString(keys::kUpdateURL, &tmp)) {
1419 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1420 errors::kInvalidUpdateURL, "");
1421 return false;
1422 }
1423 update_url_ = GURL(tmp);
1424 if (!update_url_.is_valid() ||
1425 update_url_.has_ref()) {
1426 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1427 errors::kInvalidUpdateURL, tmp);
1428 return false;
1429 }
1430 return true;
1431 }
1432
1433 bool Extension::LoadIcons(string16* error) {
1434 if (!manifest_->HasKey(keys::kIcons))
1435 return true;
1436 DictionaryValue* icons_value = NULL;
1437 if (!manifest_->GetDictionary(keys::kIcons, &icons_value)) {
1438 *error = ASCIIToUTF16(errors::kInvalidIcons);
1439 return false;
1440 }
1441
1442 for (size_t i = 0; i < ExtensionIconSet::kNumIconSizes; ++i) {
1443 std::string key = base::IntToString(ExtensionIconSet::kIconSizes[i]);
1444 if (icons_value->HasKey(key)) {
1445 std::string icon_path;
1446 if (!icons_value->GetString(key, &icon_path)) {
1447 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1448 errors::kInvalidIconPath, key);
1363 return false; 1449 return false;
1364 } 1450 }
1365 if (is_hosted_app()) { 1451
1366 // Hosted apps require an absolute URL for intents. 1452 if (!icon_path.empty() && icon_path[0] == '/')
1367 GURL service_url(value); 1453 icon_path = icon_path.substr(1);
1368 if (!service_url.is_valid() || 1454
1369 !(web_extent().MatchesURL(service_url))) { 1455 if (icon_path.empty()) {
1370 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( 1456 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1371 errors::kInvalidIntentPageInHostedApp, *iter); 1457 errors::kInvalidIconPath, key);
1372 return false;
1373 }
1374 service.service_url = service_url;
1375 } else {
1376 // We do not allow absolute intent URLs in non-hosted apps.
1377 if (GURL(value).is_valid()) {
1378 *error =ExtensionErrorUtils::FormatErrorMessageUTF16(
1379 errors::kCannotAccessPage, value.c_str());
1380 return false;
1381 }
1382 service.service_url = GetResourceURL(value);
1383 }
1384 }
1385
1386 if (one_service->HasKey(keys::kIntentTitle) &&
1387 !one_service->GetString(keys::kIntentTitle, &service.title)) {
1388 *error = ASCIIToUTF16(errors::kInvalidIntentTitle);
1389 return false;
1390 }
1391
1392 if (one_service->HasKey(keys::kIntentDisposition)) {
1393 if (!one_service->GetString(keys::kIntentDisposition, &value) ||
1394 (value != values::kIntentDispositionWindow &&
1395 value != values::kIntentDispositionInline)) {
1396 *error = ASCIIToUTF16(errors::kInvalidIntentDisposition);
1397 return false; 1458 return false;
1398 } 1459 }
1399 if (value == values::kIntentDispositionInline) { 1460 icons_.Add(ExtensionIconSet::kIconSizes[i], icon_path);
1400 service.disposition = 1461 }
1401 webkit_glue::WebIntentServiceData::DISPOSITION_INLINE; 1462 }
1402 } else { 1463 return true;
1403 service.disposition = 1464 }
1404 webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW; 1465
1405 } 1466 bool Extension::LoadCommands(string16* error) {
1406 } 1467 if (manifest_->HasKey(keys::kCommands)) {
1407 1468 DictionaryValue* commands = NULL;
1408 for (size_t i = 0; i < mime_types->GetSize(); ++i) { 1469 if (!manifest_->GetDictionary(keys::kCommands, &commands)) {
1409 if (!mime_types->GetString(i, &service.type)) { 1470 *error = ASCIIToUTF16(errors::kInvalidCommandsKey);
1471 return false;
1472 }
1473
1474 int command_index = 0;
1475 for (DictionaryValue::key_iterator iter = commands->begin_keys();
1476 iter != commands->end_keys(); ++iter) {
1477 ++command_index;
1478
1479 DictionaryValue* command = NULL;
1480 if (!commands->GetDictionary(*iter, &command)) {
1410 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( 1481 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1411 errors::kInvalidIntentTypeElement, *iter, 1482 errors::kInvalidKeyBindingDictionary,
1412 std::string(base::IntToString(i))); 1483 base::IntToString(command_index));
1413 return false; 1484 return false;
1414 } 1485 }
1415 intents_services_.push_back(service); 1486
1416 } 1487 ExtensionKeybinding binding;
1417 } 1488 if (!binding.Parse(command, *iter, command_index, error))
1418 return true; 1489 return false; // |error| already set.
1419 } 1490
1420 1491 commands_.push_back(binding);
1492 }
1493 }
1494 return true;
1495 }
1496
1497 bool Extension::LoadPlugins(string16* error) {
1498 if (!manifest_->HasKey(keys::kPlugins))
1499 return true;
1500 ListValue* list_value = NULL;
1501 if (!manifest_->GetList(keys::kPlugins, &list_value)) {
1502 *error = ASCIIToUTF16(errors::kInvalidPlugins);
1503 return false;
1504 }
1505
1506 for (size_t i = 0; i < list_value->GetSize(); ++i) {
1507 DictionaryValue* plugin_value = NULL;
1508 std::string path_str;
1509 bool is_public = false;
1510 if (!list_value->GetDictionary(i, &plugin_value)) {
1511 *error = ASCIIToUTF16(errors::kInvalidPlugins);
1512 return false;
1513 }
1514 // Get plugins[i].path.
1515 if (!plugin_value->GetString(keys::kPluginsPath, &path_str)) {
1516 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1517 errors::kInvalidPluginsPath, base::IntToString(i));
1518 return false;
1519 }
1520
1521 // Get plugins[i].content (optional).
1522 if (plugin_value->HasKey(keys::kPluginsPublic)) {
1523 if (!plugin_value->GetBoolean(keys::kPluginsPublic, &is_public)) {
1524 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1525 errors::kInvalidPluginsPublic, base::IntToString(i));
1526 return false;
1527 }
1528 }
1529
1530 // We don't allow extension plugins to run on Chrome OS. We still
1531 // parse the manifest entry so that error messages are consistently
1532 // displayed across platforms.
1533 #if !defined(OS_CHROMEOS)
1534 plugins_.push_back(PluginInfo());
1535 plugins_.back().path = path().Append(FilePath::FromUTF8Unsafe(path_str));
1536 plugins_.back().is_public = is_public;
1537 #endif
1538 }
1539 return true;
1540 }
1541
1542 bool Extension::LoadNaClModules(string16* error) {
1543 if (!manifest_->HasKey(keys::kNaClModules))
1544 return true;
1545 ListValue* list_value = NULL;
1546 if (!manifest_->GetList(keys::kNaClModules, &list_value)) {
1547 *error = ASCIIToUTF16(errors::kInvalidNaClModules);
1548 return false;
1549 }
1550
1551 for (size_t i = 0; i < list_value->GetSize(); ++i) {
1552 DictionaryValue* module_value = NULL;
1553 std::string path_str;
1554 std::string mime_type;
1555
1556 if (!list_value->GetDictionary(i, &module_value)) {
1557 *error = ASCIIToUTF16(errors::kInvalidNaClModules);
1558 return false;
1559 }
1560
1561 // Get nacl_modules[i].path.
1562 if (!module_value->GetString(keys::kNaClModulesPath, &path_str)) {
1563 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1564 errors::kInvalidNaClModulesPath, base::IntToString(i));
1565 return false;
1566 }
1567
1568 // Get nacl_modules[i].mime_type.
1569 if (!module_value->GetString(keys::kNaClModulesMIMEType, &mime_type)) {
1570 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1571 errors::kInvalidNaClModulesMIMEType, base::IntToString(i));
1572 return false;
1573 }
1574
1575 nacl_modules_.push_back(NaClModuleInfo());
1576 nacl_modules_.back().url = GetResourceURL(path_str);
1577 nacl_modules_.back().mime_type = mime_type;
1578 }
1579
1580 return true;
1581 }
1582
1583 bool Extension::LoadWebAccessibleResources(string16* error) {
1584 if (!manifest_->HasKey(keys::kWebAccessibleResources))
1585 return true;
1586 ListValue* list_value;
1587 if (!manifest_->GetList(keys::kWebAccessibleResources, &list_value)) {
1588 *error = ASCIIToUTF16(errors::kInvalidWebAccessibleResourcesList);
1589 return false;
1590 }
1591 for (size_t i = 0; i < list_value->GetSize(); ++i) {
1592 std::string relative_path;
1593 if (!list_value->GetString(i, &relative_path)) {
1594 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1595 errors::kInvalidWebAccessibleResource, base::IntToString(i));
1596 return false;
1597 }
1598 if (relative_path[0] != '/')
1599 relative_path = '/' + relative_path;
1600 web_accessible_resources_.insert(relative_path);
1601 }
1602
1603 return true;
1604 }
1605
1606 // These are not actually persisted (they're only used by the store), but
1607 // still validated.
1608 bool Extension::LoadRequirements(string16* error) {
Yoyo Zhou 2012/03/02 20:20:07 Likewise I might rename this one to CheckRequireme
Devlin 2012/03/07 04:18:54 Done.
1609 if (!manifest_->HasKey(keys::kRequirements))
1610 return true;
1611 DictionaryValue* requirements_value = NULL;
1612 if (!manifest_->GetDictionary(keys::kRequirements, &requirements_value)) {
1613 *error = ASCIIToUTF16(errors::kInvalidRequirements);
1614 return false;
1615 }
1616
1617 for (DictionaryValue::key_iterator it = requirements_value->begin_keys();
1618 it != requirements_value->end_keys(); ++it) {
1619 DictionaryValue* requirement_value;
1620 if (!requirements_value->GetDictionaryWithoutPathExpansion(
1621 *it, &requirement_value)) {
1622 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1623 errors::kInvalidRequirement, *it);
1624 return false;
1625 }
1626 }
1627 return true;
1628 }
1629
1630 bool Extension::LoadDefaultLocale(string16* error) {
1631 if (!manifest_->HasKey(keys::kDefaultLocale))
1632 return true;
1633 if (!manifest_->GetString(keys::kDefaultLocale, &default_locale_) ||
1634 !l10n_util::IsValidLocaleSyntax(default_locale_)) {
1635 *error = ASCIIToUTF16(errors::kInvalidDefaultLocale);
1636 return false;
1637 }
1638 return true;
1639 }
1640
1641 bool Extension::LoadOfflineEnabled(string16* error) {
1642 // Defaults to false.
1643 if (manifest_->HasKey(keys::kOfflineEnabled) &&
1644 !manifest_->GetBoolean(keys::kOfflineEnabled, &offline_enabled_)) {
1645 *error = ASCIIToUTF16(errors::kInvalidOfflineEnabled);
1646 return false;
1647 }
1648 return true;
1649 }
1650
1651 bool Extension::LoadOptionsPage(string16* error) {
1652 if (!manifest_->HasKey(keys::kOptionsPage))
1653 return true;
1654 std::string options_str;
1655 if (!manifest_->GetString(keys::kOptionsPage, &options_str)) {
1656 *error = ASCIIToUTF16(errors::kInvalidOptionsPage);
1657 return false;
1658 }
1659
1660 if (is_hosted_app()) {
1661 // hosted apps require an absolute URL.
1662 GURL options_url(options_str);
1663 if (!options_url.is_valid() ||
1664 !(options_url.SchemeIs("http") || options_url.SchemeIs("https"))) {
1665 *error = ASCIIToUTF16(errors::kInvalidOptionsPageInHostedApp);
1666 return false;
1667 }
1668 options_url_ = options_url;
1669 } else {
1670 GURL absolute(options_str);
1671 if (absolute.is_valid()) {
1672 *error = ASCIIToUTF16(errors::kInvalidOptionsPageExpectUrlInPackage);
1673 return false;
1674 }
1675 options_url_ = GetResourceURL(options_str);
1676 if (!options_url_.is_valid()) {
1677 *error = ASCIIToUTF16(errors::kInvalidOptionsPage);
1678 return false;
1679 }
1680 }
1681
1682 return true;
1683 }
1684
1421 bool Extension::LoadBackgroundScripts(string16* error) { 1685 bool Extension::LoadBackgroundScripts(string16* error) {
1422 Value* background_scripts_value = NULL; 1686 Value* background_scripts_value = NULL;
1423 if (!manifest_->Get(keys::kBackgroundScripts, &background_scripts_value)) 1687 if (!manifest_->Get(keys::kBackgroundScripts, &background_scripts_value))
1424 return true; 1688 return true;
1425 1689
1426 CHECK(background_scripts_value); 1690 CHECK(background_scripts_value);
1427 if (background_scripts_value->GetType() != Value::TYPE_LIST) { 1691 if (background_scripts_value->GetType() != Value::TYPE_LIST) {
1428 *error = ASCIIToUTF16(errors::kInvalidBackgroundScripts); 1692 *error = ASCIIToUTF16(errors::kInvalidBackgroundScripts);
1429 return false; 1693 return false;
1430 } 1694 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1508 } 1772 }
1509 1773
1510 if (!has_background_page()) { 1774 if (!has_background_page()) {
1511 *error = ASCIIToUTF16(errors::kInvalidBackgroundPersistentNoPage); 1775 *error = ASCIIToUTF16(errors::kInvalidBackgroundPersistentNoPage);
1512 return false; 1776 return false;
1513 } 1777 }
1514 1778
1515 return true; 1779 return true;
1516 } 1780 }
1517 1781
1782 bool Extension::LoadWebIntentServices(string16* error) {
1783 DCHECK(error);
1784
1785 if (!manifest_->HasKey(keys::kIntents))
1786 return true;
1787
1788 DictionaryValue* all_services = NULL;
1789 if (!manifest_->GetDictionary(keys::kIntents, &all_services)) {
1790 *error = ASCIIToUTF16(errors::kInvalidIntents);
1791 return false;
1792 }
1793
1794 std::string value;
1795 for (DictionaryValue::key_iterator iter(all_services->begin_keys());
1796 iter != all_services->end_keys(); ++iter) {
1797 webkit_glue::WebIntentServiceData service;
1798
1799 DictionaryValue* one_service = NULL;
1800 if (!all_services->GetDictionaryWithoutPathExpansion(*iter, &one_service)) {
1801 *error = ASCIIToUTF16(errors::kInvalidIntent);
1802 return false;
1803 }
1804 service.action = UTF8ToUTF16(*iter);
1805
1806 ListValue* mime_types = NULL;
1807 if (!one_service->HasKey(keys::kIntentType) ||
1808 !one_service->GetList(keys::kIntentType, &mime_types) ||
1809 mime_types->GetSize() == 0) {
1810 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1811 errors::kInvalidIntentType, *iter);
1812 return false;
1813 }
1814
1815 if (one_service->HasKey(keys::kIntentPath)) {
1816 if (!one_service->GetString(keys::kIntentPath, &value)) {
1817 *error = ASCIIToUTF16(errors::kInvalidIntentPath);
1818 return false;
1819 }
1820 if (is_hosted_app()) {
1821 // Hosted apps require an absolute URL for intents.
1822 GURL service_url(value);
1823 if (!service_url.is_valid() ||
1824 !(web_extent().MatchesURL(service_url))) {
1825 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1826 errors::kInvalidIntentPageInHostedApp, *iter);
1827 return false;
1828 }
1829 service.service_url = service_url;
1830 } else {
1831 // We do not allow absolute intent URLs in non-hosted apps.
1832 if (GURL(value).is_valid()) {
1833 *error =ExtensionErrorUtils::FormatErrorMessageUTF16(
1834 errors::kCannotAccessPage, value.c_str());
1835 return false;
1836 }
1837 service.service_url = GetResourceURL(value);
1838 }
1839 }
1840
1841 if (one_service->HasKey(keys::kIntentTitle) &&
1842 !one_service->GetString(keys::kIntentTitle, &service.title)) {
1843 *error = ASCIIToUTF16(errors::kInvalidIntentTitle);
1844 return false;
1845 }
1846
1847 if (one_service->HasKey(keys::kIntentDisposition)) {
1848 if (!one_service->GetString(keys::kIntentDisposition, &value) ||
1849 (value != values::kIntentDispositionWindow &&
1850 value != values::kIntentDispositionInline)) {
1851 *error = ASCIIToUTF16(errors::kInvalidIntentDisposition);
1852 return false;
1853 }
1854 if (value == values::kIntentDispositionInline) {
1855 service.disposition =
1856 webkit_glue::WebIntentServiceData::DISPOSITION_INLINE;
1857 } else {
1858 service.disposition =
1859 webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW;
1860 }
1861 }
1862
1863 for (size_t i = 0; i < mime_types->GetSize(); ++i) {
1864 if (!mime_types->GetString(i, &service.type)) {
1865 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1866 errors::kInvalidIntentTypeElement, *iter,
1867 std::string(base::IntToString(i)));
1868 return false;
1869 }
1870 intents_services_.push_back(service);
1871 }
1872 }
1873 return true;
1874 }
1875
1876 bool Extension::LoadExtensionFeatures(
1877 const ExtensionAPIPermissionSet& api_permissions,
1878 string16* error) {
1879 if (manifest_->HasKey(keys::kConvertedFromUserScript))
1880 manifest_->GetBoolean(keys::kConvertedFromUserScript,
1881 &converted_from_user_script_);
1882
1883 if (!LoadDevToolsPage(error) ||
1884 !LoadInputComponents(api_permissions, error) ||
1885 !LoadContentScripts(error) ||
1886 !LoadPageAction(error) ||
1887 !LoadBrowserAction(error) ||
1888 !LoadFileBrowserHandlers(error) ||
1889 !LoadChromeURLOverrides(error) ||
1890 !LoadOmnibox(error) ||
1891 !LoadTextToSpeechVoices(error) ||
1892 !LoadIncognitoMode(error) ||
1893 !LoadContentSecurityPolicy(error))
1894 return false;
1895
1896 return true;
1897 }
1898
1899 bool Extension::LoadDevToolsPage(string16* error) {
1900 if (!manifest_->HasKey(keys::kDevToolsPage))
1901 return true;
1902 std::string devtools_str;
1903 if (!manifest_->GetString(keys::kDevToolsPage, &devtools_str)) {
1904 *error = ASCIIToUTF16(errors::kInvalidDevToolsPage);
1905 return false;
1906 }
1907 devtools_url_ = GetResourceURL(devtools_str);
1908 return true;
1909 }
1910
1911 bool Extension::LoadInputComponents(
1912 const ExtensionAPIPermissionSet& api_permissions,
1913 string16* error) {
1914 if (!manifest_->HasKey(keys::kInputComponents))
1915 return true;
1916 ListValue* list_value = NULL;
1917 if (!manifest_->GetList(keys::kInputComponents, &list_value)) {
1918 *error = ASCIIToUTF16(errors::kInvalidInputComponents);
1919 return false;
1920 }
1921
1922 for (size_t i = 0; i < list_value->GetSize(); ++i) {
1923 DictionaryValue* module_value = NULL;
1924 std::string name_str;
1925 InputComponentType type;
1926 std::string id_str;
1927 std::string description_str;
1928 std::string language_str;
1929 std::set<std::string> layouts;
1930 std::string shortcut_keycode_str;
1931 bool shortcut_alt = false;
1932 bool shortcut_ctrl = false;
1933 bool shortcut_shift = false;
1934
1935 if (!list_value->GetDictionary(i, &module_value)) {
1936 *error = ASCIIToUTF16(errors::kInvalidInputComponents);
1937 return false;
1938 }
1939
1940 // Get input_components[i].name.
1941 if (!module_value->GetString(keys::kName, &name_str)) {
1942 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1943 errors::kInvalidInputComponentName, base::IntToString(i));
1944 return false;
1945 }
1946
1947 // Get input_components[i].type.
1948 std::string type_str;
1949 if (module_value->GetString(keys::kType, &type_str)) {
1950 if (type_str == "ime") {
1951 type = INPUT_COMPONENT_TYPE_IME;
1952 } else if (type_str == "virtual_keyboard") {
1953 if (!api_permissions.count(ExtensionAPIPermission::kExperimental)) {
1954 // Virtual Keyboards require the experimental flag.
1955 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1956 errors::kInvalidInputComponentType, base::IntToString(i));
1957 return false;
1958 }
1959 type = INPUT_COMPONENT_TYPE_VIRTUAL_KEYBOARD;
1960 } else {
1961 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1962 errors::kInvalidInputComponentType, base::IntToString(i));
1963 return false;
1964 }
1965 } else {
1966 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1967 errors::kInvalidInputComponentType, base::IntToString(i));
1968 return false;
1969 }
1970
1971 // Get input_components[i].id.
1972 if (!module_value->GetString(keys::kId, &id_str)) {
1973 id_str = "";
1974 }
1975
1976 // Get input_components[i].description.
1977 if (!module_value->GetString(keys::kDescription, &description_str)) {
1978 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1979 errors::kInvalidInputComponentDescription, base::IntToString(i));
1980 return false;
1981 }
1982 // Get input_components[i].language.
1983 if (!module_value->GetString(keys::kLanguage, &language_str)) {
1984 language_str = "";
1985 }
1986
1987 // Get input_components[i].layouts.
1988 ListValue* layouts_value = NULL;
1989 if (!module_value->GetList(keys::kLayouts, &layouts_value)) {
1990 *error = ASCIIToUTF16(errors::kInvalidInputComponentLayouts);
1991 return false;
1992 }
1993
1994 for (size_t j = 0; j < layouts_value->GetSize(); ++j) {
1995 std::string layout_name_str;
1996 if (!layouts_value->GetString(j, &layout_name_str)) {
1997 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1998 errors::kInvalidInputComponentLayoutName, base::IntToString(i),
1999 base::IntToString(j));
2000 return false;
2001 }
2002 layouts.insert(layout_name_str);
2003 }
2004
2005 if (module_value->HasKey(keys::kShortcutKey)) {
2006 DictionaryValue* shortcut_value = NULL;
2007 if (!module_value->GetDictionary(keys::kShortcutKey, &shortcut_value)) {
2008 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2009 errors::kInvalidInputComponentShortcutKey, base::IntToString(i));
2010 return false;
2011 }
2012
2013 // Get input_components[i].shortcut_keycode.
2014 if (!shortcut_value->GetString(keys::kKeycode, &shortcut_keycode_str)) {
2015 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2016 errors::kInvalidInputComponentShortcutKeycode,
2017 base::IntToString(i));
2018 return false;
2019 }
2020
2021 // Get input_components[i].shortcut_alt.
2022 if (!shortcut_value->GetBoolean(keys::kAltKey, &shortcut_alt)) {
2023 shortcut_alt = false;
2024 }
2025
2026 // Get input_components[i].shortcut_ctrl.
2027 if (!shortcut_value->GetBoolean(keys::kCtrlKey, &shortcut_ctrl)) {
2028 shortcut_ctrl = false;
2029 }
2030
2031 // Get input_components[i].shortcut_shift.
2032 if (!shortcut_value->GetBoolean(keys::kShiftKey, &shortcut_shift)) {
2033 shortcut_shift = false;
2034 }
2035 }
2036
2037 input_components_.push_back(InputComponentInfo());
2038 input_components_.back().name = name_str;
2039 input_components_.back().type = type;
2040 input_components_.back().id = id_str;
2041 input_components_.back().description = description_str;
2042 input_components_.back().language = language_str;
2043 input_components_.back().layouts.insert(layouts.begin(), layouts.end());
2044 input_components_.back().shortcut_keycode = shortcut_keycode_str;
2045 input_components_.back().shortcut_alt = shortcut_alt;
2046 input_components_.back().shortcut_ctrl = shortcut_ctrl;
2047 input_components_.back().shortcut_shift = shortcut_shift;
2048 }
2049
2050 return true;
2051 }
2052
2053 bool Extension::LoadContentScripts(string16* error) {
2054 if (!manifest_->HasKey(keys::kContentScripts))
2055 return true;
2056 ListValue* list_value;
2057 if (!manifest_->GetList(keys::kContentScripts, &list_value)) {
2058 *error = ASCIIToUTF16(errors::kInvalidContentScriptsList);
2059 return false;
2060 }
2061
2062 for (size_t i = 0; i < list_value->GetSize(); ++i) {
2063 DictionaryValue* content_script = NULL;
2064 if (!list_value->GetDictionary(i, &content_script)) {
2065 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2066 errors::kInvalidContentScript, base::IntToString(i));
2067 return false;
2068 }
2069
2070 UserScript script;
2071 if (!LoadUserScriptHelper(content_script, i, error, &script))
2072 return false; // Failed to parse script context definition.
2073 script.set_extension_id(id());
2074 if (converted_from_user_script_) {
2075 script.set_emulate_greasemonkey(true);
2076 script.set_match_all_frames(true); // Greasemonkey matches all frames.
2077 }
2078 content_scripts_.push_back(script);
2079 }
2080 return true;
2081 }
2082
2083 bool Extension::LoadPageAction(string16* error) {
2084 DictionaryValue* page_action_value = NULL;
2085
2086 if (manifest_->HasKey(keys::kPageActions)) {
2087 ListValue* list_value = NULL;
2088 if (!manifest_->GetList(keys::kPageActions, &list_value)) {
2089 *error = ASCIIToUTF16(errors::kInvalidPageActionsList);
2090 return false;
2091 }
2092
2093 size_t list_value_length = list_value->GetSize();
2094
2095 if (list_value_length == 0u) {
2096 // A list with zero items is allowed, and is equivalent to not having
2097 // a page_actions key in the manifest. Don't set |page_action_value|.
2098 } else if (list_value_length == 1u) {
2099 if (!list_value->GetDictionary(0, &page_action_value)) {
2100 *error = ASCIIToUTF16(errors::kInvalidPageAction);
2101 return false;
2102 }
2103 } else { // list_value_length > 1u.
2104 *error = ASCIIToUTF16(errors::kInvalidPageActionsListSize);
2105 return false;
2106 }
2107 } else if (manifest_->HasKey(keys::kPageAction)) {
2108 if (!manifest_->GetDictionary(keys::kPageAction, &page_action_value)) {
2109 *error = ASCIIToUTF16(errors::kInvalidPageAction);
2110 return false;
2111 }
2112 }
2113
2114 // If page_action_value is not NULL, then there was a valid page action.
2115 if (page_action_value) {
2116 page_action_.reset(
2117 LoadExtensionActionHelper(page_action_value, error));
2118 if (!page_action_.get())
2119 return false; // Failed to parse page action definition.
2120 }
2121
2122 return true;
2123 }
2124
2125 bool Extension::LoadBrowserAction(string16* error) {
2126 if (!manifest_->HasKey(keys::kBrowserAction))
2127 return true;
2128 DictionaryValue* browser_action_value = NULL;
2129 if (!manifest_->GetDictionary(keys::kBrowserAction, &browser_action_value)) {
2130 *error = ASCIIToUTF16(errors::kInvalidBrowserAction);
2131 return false;
2132 }
2133
2134 browser_action_.reset(
2135 LoadExtensionActionHelper(browser_action_value, error));
2136 if (!browser_action_.get())
2137 return false; // Failed to parse browser action definition.
2138 return true;
2139 }
2140
2141 bool Extension::LoadFileBrowserHandlers(string16* error) {
2142 if (!manifest_->HasKey(keys::kFileBrowserHandlers))
2143 return true;
2144 ListValue* file_browser_handlers_value = NULL;
2145 if (!manifest_->GetList(keys::kFileBrowserHandlers,
2146 &file_browser_handlers_value)) {
2147 *error = ASCIIToUTF16(errors::kInvalidFileBrowserHandler);
2148 return false;
2149 }
2150 file_browser_handlers_.reset(
2151 LoadFileBrowserHandlersHelper(file_browser_handlers_value, error));
2152 if (!file_browser_handlers_.get())
2153 return false; // Failed to parse file browser actions definition.
2154 return true;
2155 }
2156
2157 Extension::FileBrowserHandlerList* Extension::LoadFileBrowserHandlersHelper(
2158 const ListValue* extension_actions, string16* error) {
2159 scoped_ptr<FileBrowserHandlerList> result(
2160 new FileBrowserHandlerList());
2161 for (ListValue::const_iterator iter = extension_actions->begin();
2162 iter != extension_actions->end();
2163 ++iter) {
2164 if (!(*iter)->IsType(Value::TYPE_DICTIONARY)) {
2165 *error = ASCIIToUTF16(errors::kInvalidFileBrowserHandler);
2166 return NULL;
2167 }
2168 scoped_ptr<FileBrowserHandler> action(
2169 LoadFileBrowserHandler(
2170 reinterpret_cast<DictionaryValue*>(*iter), error));
2171 if (!action.get())
2172 return NULL; // Failed to parse file browser action definition.
2173 result->push_back(linked_ptr<FileBrowserHandler>(action.release()));
2174 }
2175 return result.release();
2176 }
2177
2178 FileBrowserHandler* Extension::LoadFileBrowserHandler(
2179 const DictionaryValue* file_browser_handler, string16* error) {
2180 scoped_ptr<FileBrowserHandler> result(
2181 new FileBrowserHandler());
2182 result->set_extension_id(id());
2183
2184 std::string id;
2185 // Read the file action |id| (mandatory).
2186 if (!file_browser_handler->HasKey(keys::kPageActionId) ||
2187 !file_browser_handler->GetString(keys::kPageActionId, &id)) {
2188 *error = ASCIIToUTF16(errors::kInvalidPageActionId);
2189 return NULL;
2190 }
2191 result->set_id(id);
2192
2193 // Read the page action title from |default_title| (mandatory).
2194 std::string title;
2195 if (!file_browser_handler->HasKey(keys::kPageActionDefaultTitle) ||
2196 !file_browser_handler->GetString(keys::kPageActionDefaultTitle, &title)) {
2197 *error = ASCIIToUTF16(errors::kInvalidPageActionDefaultTitle);
2198 return NULL;
2199 }
2200 result->set_title(title);
2201
2202 // Initialize file filters (mandatory).
2203 ListValue* list_value = NULL;
2204 if (!file_browser_handler->HasKey(keys::kFileFilters) ||
2205 !file_browser_handler->GetList(keys::kFileFilters, &list_value) ||
2206 list_value->empty()) {
2207 *error = ASCIIToUTF16(errors::kInvalidFileFiltersList);
2208 return NULL;
2209 }
2210 for (size_t i = 0; i < list_value->GetSize(); ++i) {
2211 std::string filter;
2212 if (!list_value->GetString(i, &filter)) {
2213 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2214 errors::kInvalidFileFilterValue, base::IntToString(i));
2215 return NULL;
2216 }
2217 StringToLowerASCII(&filter);
2218 URLPattern pattern(URLPattern::SCHEME_FILESYSTEM);
2219 if (pattern.Parse(filter) != URLPattern::PARSE_SUCCESS) {
2220 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2221 errors::kInvalidURLPatternError, filter);
2222 return NULL;
2223 }
2224 std::string path = pattern.path();
2225 bool allowed = path == "*" || path == "*.*" ||
2226 (path.compare(0, 2, "*.") == 0 &&
2227 path.find_first_of('*', 2) == std::string::npos);
2228 if (!allowed) {
2229 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2230 errors::kInvalidURLPatternError, filter);
2231 return NULL;
2232 }
2233 result->AddPattern(pattern);
2234 }
2235
2236 std::string default_icon;
2237 // Read the file browser action |default_icon| (optional).
2238 if (file_browser_handler->HasKey(keys::kPageActionDefaultIcon)) {
2239 if (!file_browser_handler->GetString(
2240 keys::kPageActionDefaultIcon, &default_icon) ||
2241 default_icon.empty()) {
2242 *error = ASCIIToUTF16(errors::kInvalidPageActionIconPath);
2243 return NULL;
2244 }
2245 result->set_icon_path(default_icon);
2246 }
2247
2248 return result.release();
2249 }
2250
2251 bool Extension::LoadChromeURLOverrides(string16* error) {
2252 if (!manifest_->HasKey(keys::kChromeURLOverrides))
2253 return true;
2254 DictionaryValue* overrides = NULL;
2255 if (!manifest_->GetDictionary(keys::kChromeURLOverrides, &overrides)) {
2256 *error = ASCIIToUTF16(errors::kInvalidChromeURLOverrides);
2257 return false;
2258 }
2259
2260 // Validate that the overrides are all strings
2261 for (DictionaryValue::key_iterator iter = overrides->begin_keys();
2262 iter != overrides->end_keys(); ++iter) {
2263 std::string page = *iter;
2264 std::string val;
2265 // Restrict override pages to a list of supported URLs.
2266 if ((page != chrome::kChromeUINewTabHost &&
2267 #if defined(USE_VIRTUAL_KEYBOARD)
2268 page != chrome::kChromeUIKeyboardHost &&
2269 #endif
2270 #if defined(OS_CHROMEOS)
2271 page != chrome::kChromeUIActivationMessageHost &&
2272 #endif
2273 page != chrome::kChromeUIBookmarksHost &&
2274 page != chrome::kChromeUIHistoryHost
2275 #if defined(FILE_MANAGER_EXTENSION)
2276 &&
2277 !(location() == COMPONENT &&
2278 page == chrome::kChromeUIFileManagerHost)
2279 #endif
2280 ) ||
2281 !overrides->GetStringWithoutPathExpansion(*iter, &val)) {
2282 *error = ASCIIToUTF16(errors::kInvalidChromeURLOverrides);
2283 return false;
2284 }
2285 // Replace the entry with a fully qualified chrome-extension:// URL.
2286 chrome_url_overrides_[page] = GetResourceURL(val);
2287 }
2288
2289 // An extension may override at most one page.
2290 if (overrides->size() > 1) {
2291 *error = ASCIIToUTF16(errors::kMultipleOverrides);
2292 return false;
2293 }
2294
2295 return true;
2296 }
2297
2298 bool Extension::LoadOmnibox(string16* error) {
2299 if (!manifest_->HasKey(keys::kOmnibox))
2300 return true;
2301 if (!manifest_->GetString(keys::kOmniboxKeyword, &omnibox_keyword_) ||
2302 omnibox_keyword_.empty()) {
Yoyo Zhou 2012/03/02 20:20:07 indent -1 The style guide doesn't treat leading un
Devlin 2012/03/07 04:18:54 Done.
2303 *error = ASCIIToUTF16(errors::kInvalidOmniboxKeyword);
2304 return false;
2305 }
2306 return true;
2307 }
2308
2309 bool Extension::LoadTextToSpeechVoices(string16* error) {
2310 if (!manifest_->HasKey(keys::kTtsEngine))
2311 return true;
2312 DictionaryValue* tts_dict = NULL;
2313 if (!manifest_->GetDictionary(keys::kTtsEngine, &tts_dict)) {
2314 *error = ASCIIToUTF16(errors::kInvalidTts);
2315 return false;
2316 }
2317
2318 if (tts_dict->HasKey(keys::kTtsVoices)) {
2319 ListValue* tts_voices = NULL;
2320 if (!tts_dict->GetList(keys::kTtsVoices, &tts_voices)) {
2321 *error = ASCIIToUTF16(errors::kInvalidTtsVoices);
2322 return false;
2323 }
2324
2325 for (size_t i = 0; i < tts_voices->GetSize(); i++) {
2326 DictionaryValue* one_tts_voice = NULL;
2327 if (!tts_voices->GetDictionary(i, &one_tts_voice)) {
2328 *error = ASCIIToUTF16(errors::kInvalidTtsVoices);
2329 return false;
2330 }
2331
2332 TtsVoice voice_data;
2333 if (one_tts_voice->HasKey(keys::kTtsVoicesVoiceName)) {
2334 if (!one_tts_voice->GetString(
2335 keys::kTtsVoicesVoiceName, &voice_data.voice_name)) {
2336 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesVoiceName);
2337 return false;
2338 }
2339 }
2340 if (one_tts_voice->HasKey(keys::kTtsVoicesLang)) {
2341 if (!one_tts_voice->GetString(
2342 keys::kTtsVoicesLang, &voice_data.lang) ||
2343 !l10n_util::IsValidLocaleSyntax(voice_data.lang)) {
2344 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesLang);
2345 return false;
2346 }
2347 }
2348 if (one_tts_voice->HasKey(keys::kTtsVoicesGender)) {
2349 if (!one_tts_voice->GetString(
2350 keys::kTtsVoicesGender, &voice_data.gender) ||
2351 (voice_data.gender != keys::kTtsGenderMale &&
2352 voice_data.gender != keys::kTtsGenderFemale)) {
2353 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesGender);
2354 return false;
2355 }
2356 }
2357 if (one_tts_voice->HasKey(keys::kTtsVoicesEventTypes)) {
2358 ListValue* event_types_list;
2359 if (!one_tts_voice->GetList(
2360 keys::kTtsVoicesEventTypes, &event_types_list)) {
2361 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
2362 return false;
2363 }
2364 for (size_t i = 0; i < event_types_list->GetSize(); i++) {
2365 std::string event_type;
2366 if (!event_types_list->GetString(i, &event_type)) {
2367 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
2368 return false;
2369 }
2370 if (event_type != keys::kTtsVoicesEventTypeEnd &&
2371 event_type != keys::kTtsVoicesEventTypeError &&
2372 event_type != keys::kTtsVoicesEventTypeMarker &&
2373 event_type != keys::kTtsVoicesEventTypeSentence &&
2374 event_type != keys::kTtsVoicesEventTypeStart &&
2375 event_type != keys::kTtsVoicesEventTypeWord) {
2376 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
2377 return false;
2378 }
2379 if (voice_data.event_types.find(event_type) !=
2380 voice_data.event_types.end()) {
2381 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
2382 return false;
2383 }
2384 voice_data.event_types.insert(event_type);
2385 }
2386 }
2387
2388 tts_voices_.push_back(voice_data);
2389 }
2390 }
2391 return true;
2392 }
2393
2394 bool Extension::LoadIncognitoMode(string16* error) {
2395 // Apps default to split mode, extensions default to spanning.
2396 incognito_split_mode_ = is_app();
2397 if (!manifest_->HasKey(keys::kIncognito))
2398 return true;
2399 std::string value;
2400 if (!manifest_->GetString(keys::kIncognito, &value)) {
2401 *error = ASCIIToUTF16(errors::kInvalidIncognitoBehavior);
2402 return false;
2403 }
2404 if (value == values::kIncognitoSpanning) {
2405 incognito_split_mode_ = false;
2406 } else if (value == values::kIncognitoSplit) {
2407 incognito_split_mode_ = true;
2408 } else {
2409 *error = ASCIIToUTF16(errors::kInvalidIncognitoBehavior);
2410 return false;
2411 }
2412 return true;
2413 }
2414
2415 bool Extension::LoadContentSecurityPolicy(string16* error) {
2416 if (manifest_->HasKey(keys::kContentSecurityPolicy)) {
2417 std::string content_security_policy;
2418 if (!manifest_->GetString(keys::kContentSecurityPolicy,
2419 &content_security_policy)) {
2420 *error = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
2421 return false;
2422 }
2423 if (!ContentSecurityPolicyIsLegal(content_security_policy)) {
2424 *error = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
2425 return false;
2426 }
2427 if (manifest_version_ >= 2 &&
2428 !ContentSecurityPolicyIsSecure(content_security_policy)) {
2429 *error = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
2430 return false;
2431 }
2432
2433 content_security_policy_ = content_security_policy;
2434 } else if (manifest_version_ >= 2) {
2435 // Manifest version 2 introduced a default Content-Security-Policy.
2436 // TODO(abarth): Should we continue to let extensions override the
2437 // default Content-Security-Policy?
2438 content_security_policy_ = kDefaultContentSecurityPolicy;
2439 CHECK(ContentSecurityPolicyIsSecure(content_security_policy_));
2440 }
2441 return true;
2442 }
2443
2444 bool Extension::LoadAppIsolation(string16* error) {
2445 Value* temp = NULL;
2446 if (!manifest_->Get(keys::kIsolation, &temp))
2447 return true;
2448
2449 if (temp->GetType() != Value::TYPE_LIST) {
2450 *error = ASCIIToUTF16(errors::kInvalidIsolation);
2451 return false;
2452 }
2453
2454 ListValue* isolation_list = static_cast<ListValue*>(temp);
2455 for (size_t i = 0; i < isolation_list->GetSize(); ++i) {
2456 std::string isolation_string;
2457 if (!isolation_list->GetString(i, &isolation_string)) {
2458 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2459 errors::kInvalidIsolationValue,
2460 base::UintToString(i));
2461 return false;
2462 }
2463
2464 // Check for isolated storage.
2465 if (isolation_string == values::kIsolatedStorage) {
2466 is_storage_isolated_ = true;
2467 } else {
2468 DLOG(WARNING) << "Did not recognize isolation type: "
2469 << isolation_string;
2470 }
2471 }
2472 return true;
2473 }
2474
2475 bool Extension::LoadThemeFeatures(string16* error) {
2476 if (!manifest_->HasKey(keys::kTheme))
2477 return true;
2478 DictionaryValue* theme_value = NULL;
2479 if (!manifest_->GetDictionary(keys::kTheme, &theme_value)) {
2480 *error = ASCIIToUTF16(errors::kInvalidTheme);
2481 return false;
2482 }
2483 if (!LoadThemeImages(theme_value, error))
2484 return false;
2485 if (!LoadThemeColors(theme_value, error))
2486 return false;
2487 if (!LoadThemeTints(theme_value, error))
2488 return false;
2489 if (!LoadThemeDisplayProperties(theme_value, error))
2490 return false;
2491
2492 return true;
2493 }
2494
2495 bool Extension::LoadThemeImages(const DictionaryValue* theme_value,
2496 string16* error) {
2497 DictionaryValue* images_value = NULL;
2498 if (theme_value->GetDictionary(keys::kThemeImages, &images_value)) {
2499 // Validate that the images are all strings
2500 for (DictionaryValue::key_iterator iter = images_value->begin_keys();
2501 iter != images_value->end_keys(); ++iter) {
2502 std::string val;
2503 if (!images_value->GetString(*iter, &val)) {
2504 *error = ASCIIToUTF16(errors::kInvalidThemeImages);
2505 return false;
2506 }
2507 }
2508 theme_images_.reset(images_value->DeepCopy());
2509 }
2510 return true;
2511 }
2512
2513 bool Extension::LoadThemeColors(const DictionaryValue* theme_value,
2514 string16* error) {
2515 DictionaryValue* colors_value = NULL;
2516 if (theme_value->GetDictionary(keys::kThemeColors, &colors_value)) {
2517 // Validate that the colors are RGB or RGBA lists
2518 for (DictionaryValue::key_iterator iter = colors_value->begin_keys();
2519 iter != colors_value->end_keys(); ++iter) {
2520 ListValue* color_list = NULL;
2521 double alpha = 0.0;
2522 int color = 0;
2523 // The color must be a list
2524 if (!colors_value->GetListWithoutPathExpansion(*iter, &color_list) ||
2525 // And either 3 items (RGB) or 4 (RGBA)
2526 ((color_list->GetSize() != 3) &&
2527 ((color_list->GetSize() != 4) ||
2528 // For RGBA, the fourth item must be a real or int alpha value.
2529 // Note that GetDouble() can get an integer value.
2530 !color_list->GetDouble(3, &alpha))) ||
2531 // For both RGB and RGBA, the first three items must be ints (R,G,B)
2532 !color_list->GetInteger(0, &color) ||
2533 !color_list->GetInteger(1, &color) ||
2534 !color_list->GetInteger(2, &color)) {
2535 *error = ASCIIToUTF16(errors::kInvalidThemeColors);
2536 return false;
2537 }
2538 }
2539 theme_colors_.reset(colors_value->DeepCopy());
2540 }
2541 return true;
2542 }
2543
2544 bool Extension::LoadThemeTints(const DictionaryValue* theme_value,
2545 string16* error) {
2546 DictionaryValue* tints_value = NULL;
2547 if (theme_value->GetDictionary(keys::kThemeTints, &tints_value)) {
2548 // Validate that the tints are all reals.
2549 for (DictionaryValue::key_iterator iter = tints_value->begin_keys();
2550 iter != tints_value->end_keys(); ++iter) {
2551 ListValue* tint_list = NULL;
2552 double v = 0.0;
2553 if (!tints_value->GetListWithoutPathExpansion(*iter, &tint_list) ||
2554 tint_list->GetSize() != 3 ||
2555 !tint_list->GetDouble(0, &v) ||
2556 !tint_list->GetDouble(1, &v) ||
2557 !tint_list->GetDouble(2, &v)) {
2558 *error = ASCIIToUTF16(errors::kInvalidThemeTints);
2559 return false;
2560 }
2561 }
2562 theme_tints_.reset(tints_value->DeepCopy());
2563 }
2564 return true;
2565 }
2566
2567 bool Extension::LoadThemeDisplayProperties(const DictionaryValue* theme_value,
2568 string16* error) {
2569 DictionaryValue* display_properties_value = NULL;
2570 if (theme_value->GetDictionary(keys::kThemeDisplayProperties,
2571 &display_properties_value)) {
2572 theme_display_properties_.reset(
2573 display_properties_value->DeepCopy());
2574 }
2575 return true;
2576 }
2577
1518 // static 2578 // static
1519 bool Extension::IsTrustedId(const std::string& id) { 2579 bool Extension::IsTrustedId(const std::string& id) {
1520 // See http://b/4946060 for more details. 2580 // See http://b/4946060 for more details.
1521 return id == std::string("nckgahadagoaajjgafhacjanaoiihapd"); 2581 return id == std::string("nckgahadagoaajjgafhacjanaoiihapd");
1522 } 2582 }
1523 2583
1524 Extension::Extension(const FilePath& path, 2584 Extension::Extension(const FilePath& path,
1525 scoped_ptr<extensions::Manifest> manifest) 2585 scoped_ptr<extensions::Manifest> manifest)
1526 : manifest_version_(0), 2586 : manifest_version_(0),
1527 incognito_split_mode_(false), 2587 incognito_split_mode_(false),
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
1690 const SkBitmap& Extension::GetDefaultIcon(bool is_app) { 2750 const SkBitmap& Extension::GetDefaultIcon(bool is_app) {
1691 if (is_app) { 2751 if (is_app) {
1692 return *ResourceBundle::GetSharedInstance().GetBitmapNamed( 2752 return *ResourceBundle::GetSharedInstance().GetBitmapNamed(
1693 IDR_APP_DEFAULT_ICON); 2753 IDR_APP_DEFAULT_ICON);
1694 } else { 2754 } else {
1695 return *ResourceBundle::GetSharedInstance().GetBitmapNamed( 2755 return *ResourceBundle::GetSharedInstance().GetBitmapNamed(
1696 IDR_EXTENSION_DEFAULT_ICON); 2756 IDR_EXTENSION_DEFAULT_ICON);
1697 } 2757 }
1698 } 2758 }
1699 2759
2760 // static
1700 GURL Extension::GetBaseURLFromExtensionId(const std::string& extension_id) { 2761 GURL Extension::GetBaseURLFromExtensionId(const std::string& extension_id) {
1701 return GURL(std::string(chrome::kExtensionScheme) + 2762 return GURL(std::string(chrome::kExtensionScheme) +
1702 chrome::kStandardSchemeSeparator + extension_id + "/"); 2763 chrome::kStandardSchemeSeparator + extension_id + "/");
1703 } 2764 }
1704 2765
1705 bool Extension::LoadManifestVersion(string16* error) {
1706 // Get the original value out of the dictionary so that we can validate it
1707 // more strictly.
1708 if (manifest_->value()->HasKey(keys::kManifestVersion)) {
1709 int manifest_version = 1;
1710 if (!manifest_->GetInteger(keys::kManifestVersion, &manifest_version) ||
1711 manifest_version < 1) {
1712 *error = ASCIIToUTF16(errors::kInvalidManifestVersion);
1713 return false;
1714 }
1715 }
1716
1717 manifest_version_ = manifest_->GetManifestVersion();
1718 if (creation_flags_ & REQUIRE_MODERN_MANIFEST_VERSION &&
1719 manifest_version_ < kModernManifestVersion &&
1720 !CommandLine::ForCurrentProcess()->HasSwitch(
1721 switches::kAllowLegacyExtensionManifests)) {
1722 *error = ASCIIToUTF16(errors::kInvalidManifestVersion);
1723 return false;
1724 }
1725
1726 return true;
1727 }
1728
1729 // static
1730 bool Extension::InitExtensionID(extensions::Manifest* manifest,
1731 const FilePath& path,
1732 const std::string& explicit_id,
1733 int creation_flags,
1734 string16* error) {
1735 if (!explicit_id.empty()) {
1736 manifest->set_extension_id(explicit_id);
1737 return true;
1738 }
1739
1740 if (manifest->HasKey(keys::kPublicKey)) {
1741 std::string public_key;
1742 std::string public_key_bytes;
1743 std::string extension_id;
1744 if (!manifest->GetString(keys::kPublicKey, &public_key) ||
1745 !ParsePEMKeyBytes(public_key, &public_key_bytes) ||
1746 !GenerateId(public_key_bytes, &extension_id)) {
1747 *error = ASCIIToUTF16(errors::kInvalidKey);
1748 return false;
1749 }
1750 manifest->set_extension_id(extension_id);
1751 return true;
1752 }
1753
1754 if (creation_flags & REQUIRE_KEY) {
1755 *error = ASCIIToUTF16(errors::kInvalidKey);
1756 return false;
1757 } else {
1758 // If there is a path, we generate the ID from it. This is useful for
1759 // development mode, because it keeps the ID stable across restarts and
1760 // reloading the extension.
1761 std::string extension_id = GenerateIdForPath(path);
1762 if (extension_id.empty()) {
1763 NOTREACHED() << "Could not create ID from path.";
1764 return false;
1765 }
1766 manifest->set_extension_id(extension_id);
1767 return true;
1768 }
1769 }
1770
1771 bool Extension::InitFromValue(int flags, string16* error) { 2766 bool Extension::InitFromValue(int flags, string16* error) {
1772 DCHECK(error); 2767 DCHECK(error);
1773 2768
1774 base::AutoLock auto_lock(runtime_data_lock_); 2769 base::AutoLock auto_lock(runtime_data_lock_);
1775 2770
1776 // Initialize permissions with an empty, default permission set. 2771 // Initialize permissions with an empty, default permission set.
1777 runtime_data_.SetActivePermissions(new ExtensionPermissionSet()); 2772 runtime_data_.SetActivePermissions(new ExtensionPermissionSet());
1778 optional_permission_set_ = new ExtensionPermissionSet(); 2773 optional_permission_set_ = new ExtensionPermissionSet();
1779 required_permission_set_ = new ExtensionPermissionSet(); 2774 required_permission_set_ = new ExtensionPermissionSet();
1780 2775
1781 creation_flags_ = flags; 2776 creation_flags_ = flags;
1782 2777
1783 if (!LoadManifestVersion(error)) 2778 // Validate minimum Chrome version. We don't need to store this, since the
2779 // extension is not valid if it is incorrect
2780 if (!CheckMinimumChromeVersion(error))
2781 return false;
2782
2783 // Loads the required fields for an extension; this must be done first.
Yoyo Zhou 2012/03/02 20:20:07 There seems to be no need to actually load these t
Devlin 2012/03/07 04:18:54 Done.
2784 if (!LoadRequiredFeatures(error))
1784 return false; 2785 return false;
1785 2786
1786 // We don't ned to validate because InitExtensionID already did that. 2787 // We don't ned to validate because InitExtensionID already did that.
1787 manifest_->GetString(keys::kPublicKey, &public_key_); 2788 manifest_->GetString(keys::kPublicKey, &public_key_);
1788 2789
1789 // Initialize the URL. 2790 // Initialize permissions with an empty, default permission set.
2791 runtime_data_.SetActivePermissions(new ExtensionPermissionSet());
2792 optional_permission_set_ = new ExtensionPermissionSet();
2793 required_permission_set_ = new ExtensionPermissionSet();
2794
1790 extension_url_ = Extension::GetBaseURLFromExtensionId(id()); 2795 extension_url_ = Extension::GetBaseURLFromExtensionId(id());
1791 2796
1792 // Initialize version.
1793 std::string version_str;
1794 if (!manifest_->GetString(keys::kVersion, &version_str)) {
1795 *error = ASCIIToUTF16(errors::kInvalidVersion);
1796 return false;
1797 }
1798 version_.reset(Version::GetVersionFromString(version_str));
1799 if (!version_.get() ||
1800 version_->components().size() > 4) {
1801 *error = ASCIIToUTF16(errors::kInvalidVersion);
1802 return false;
1803 }
1804
1805 // Initialize name.
1806 string16 localized_name;
1807 if (!manifest_->GetString(keys::kName, &localized_name)) {
1808 *error = ASCIIToUTF16(errors::kInvalidName);
1809 return false;
1810 }
1811 base::i18n::AdjustStringForLocaleDirection(&localized_name);
1812 name_ = UTF16ToUTF8(localized_name);
1813
1814 // Load App settings. LoadExtent at least has to be done before 2797 // Load App settings. LoadExtent at least has to be done before
1815 // ParsePermissions(), because the valid permissions depend on what type of 2798 // ParsePermissions(), because the valid permissions depend on what type of
1816 // package this is. 2799 // package this is.
1817 if (is_app() && 2800 if (is_app() && !LoadAppFeatures(error))
1818 (!LoadExtent(keys::kWebURLs, &extent_,errors::kInvalidWebURLs, 2801 return false;
1819 errors::kInvalidWebURL, error) || 2802
1820 !LoadLaunchURL(error) ||
1821 !LoadLaunchContainer(error))) {
1822 return false;
1823 }
1824
1825 if (is_platform_app()) {
1826 if (launch_container() != extension_misc::LAUNCH_SHELL) {
1827 *error = ASCIIToUTF16(errors::kInvalidLaunchContainerForPlatform);
1828 return false;
1829 }
1830 } else if (launch_container() == extension_misc::LAUNCH_SHELL) {
1831 *error = ASCIIToUTF16(errors::kInvalidLaunchContainerForNonPlatform);
1832 return false;
1833 }
1834
1835 // Initialize the permissions (optional).
1836 ExtensionAPIPermissionSet api_permissions; 2803 ExtensionAPIPermissionSet api_permissions;
1837 URLPatternSet host_permissions; 2804 URLPatternSet host_permissions;
1838 if (!ParsePermissions(keys::kPermissions, 2805 if (!ParsePermissions(keys::kPermissions,
1839 flags,
1840 error, 2806 error,
1841 &api_permissions, 2807 &api_permissions,
1842 &host_permissions)) { 2808 &host_permissions)) {
1843 return false; 2809 return false;
1844 } 2810 }
1845 2811
1846 // Initialize the optional permissions (optional).
1847 ExtensionAPIPermissionSet optional_api_permissions; 2812 ExtensionAPIPermissionSet optional_api_permissions;
1848 URLPatternSet optional_host_permissions; 2813 URLPatternSet optional_host_permissions;
1849 if (!ParsePermissions(keys::kOptionalPermissions, 2814 if (!ParsePermissions(keys::kOptionalPermissions,
1850 flags,
1851 error, 2815 error,
1852 &optional_api_permissions, 2816 &optional_api_permissions,
1853 &optional_host_permissions)) { 2817 &optional_host_permissions)) {
1854 return false; 2818 return false;
1855 } 2819 }
1856 2820
1857 // Initialize description (if present).
1858 if (manifest_->HasKey(keys::kDescription)) {
1859 if (!manifest_->GetString(keys::kDescription, &description_)) {
1860 *error = ASCIIToUTF16(errors::kInvalidDescription);
1861 return false;
1862 }
1863 }
1864
1865 // Initialize homepage url (if present).
1866 if (manifest_->HasKey(keys::kHomepageURL)) {
1867 std::string tmp;
1868 if (!manifest_->GetString(keys::kHomepageURL, &tmp)) {
1869 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1870 errors::kInvalidHomepageURL, "");
1871 return false;
1872 }
1873 homepage_url_ = GURL(tmp);
1874 if (!homepage_url_.is_valid() ||
1875 (!homepage_url_.SchemeIs("http") &&
1876 !homepage_url_.SchemeIs("https"))) {
1877 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1878 errors::kInvalidHomepageURL, tmp);
1879 return false;
1880 }
1881 }
1882
1883 // Initialize update url (if present).
1884 if (manifest_->HasKey(keys::kUpdateURL)) {
1885 std::string tmp;
1886 if (!manifest_->GetString(keys::kUpdateURL, &tmp)) {
1887 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1888 errors::kInvalidUpdateURL, "");
1889 return false;
1890 }
1891 update_url_ = GURL(tmp);
1892 if (!update_url_.is_valid() ||
1893 update_url_.has_ref()) {
1894 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1895 errors::kInvalidUpdateURL, tmp);
1896 return false;
1897 }
1898 }
1899
1900 // Validate minimum Chrome version (if present). We don't need to store this,
1901 // since the extension is not valid if it is incorrect.
1902 if (manifest_->HasKey(keys::kMinimumChromeVersion)) {
1903 std::string minimum_version_string;
1904 if (!manifest_->GetString(keys::kMinimumChromeVersion,
1905 &minimum_version_string)) {
1906 *error = ASCIIToUTF16(errors::kInvalidMinimumChromeVersion);
1907 return false;
1908 }
1909
1910 scoped_ptr<Version> minimum_version(
1911 Version::GetVersionFromString(minimum_version_string));
1912 if (!minimum_version.get()) {
1913 *error = ASCIIToUTF16(errors::kInvalidMinimumChromeVersion);
1914 return false;
1915 }
1916
1917 chrome::VersionInfo current_version_info;
1918 if (!current_version_info.is_valid()) {
1919 NOTREACHED();
1920 return false;
1921 }
1922
1923 scoped_ptr<Version> current_version(
1924 Version::GetVersionFromString(current_version_info.Version()));
1925 if (!current_version.get()) {
1926 DCHECK(false);
1927 return false;
1928 }
1929
1930 if (current_version->CompareTo(*minimum_version) < 0) {
1931 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1932 errors::kChromeVersionTooLow,
1933 l10n_util::GetStringUTF8(IDS_PRODUCT_NAME),
1934 minimum_version_string);
1935 return false;
1936 }
1937 }
1938
1939 // Initialize converted_from_user_script (if present)
1940 if (manifest_->HasKey(keys::kConvertedFromUserScript))
1941 manifest_->GetBoolean(keys::kConvertedFromUserScript,
1942 &converted_from_user_script_);
1943
1944 // Initialize commands (if present).
1945 if (manifest_->HasKey(keys::kCommands)) {
1946 DictionaryValue* commands = NULL;
1947 if (!manifest_->GetDictionary(keys::kCommands, &commands)) {
1948 *error = ASCIIToUTF16(errors::kInvalidCommandsKey);
1949 return false;
1950 }
1951
1952 int command_index = 0;
1953 for (DictionaryValue::key_iterator iter = commands->begin_keys();
1954 iter != commands->end_keys(); ++iter) {
1955 ++command_index;
1956
1957 DictionaryValue* command = NULL;
1958 if (!commands->GetDictionary(*iter, &command)) {
1959 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1960 errors::kInvalidKeyBindingDictionary,
1961 base::IntToString(command_index));
1962 return false;
1963 }
1964
1965 ExtensionKeybinding binding;
1966 if (!binding.Parse(command, *iter, command_index, error))
1967 return false; // |error| already set.
1968
1969 commands_.push_back(binding);
1970 }
1971 }
1972
1973 // Initialize icons (if present).
1974 if (manifest_->HasKey(keys::kIcons)) {
1975 DictionaryValue* icons_value = NULL;
1976 if (!manifest_->GetDictionary(keys::kIcons, &icons_value)) {
1977 *error = ASCIIToUTF16(errors::kInvalidIcons);
1978 return false;
1979 }
1980
1981 for (size_t i = 0; i < ExtensionIconSet::kNumIconSizes; ++i) {
1982 std::string key = base::IntToString(ExtensionIconSet::kIconSizes[i]);
1983 if (icons_value->HasKey(key)) {
1984 std::string icon_path;
1985 if (!icons_value->GetString(key, &icon_path)) {
1986 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1987 errors::kInvalidIconPath, key);
1988 return false;
1989 }
1990
1991 if (!icon_path.empty() && icon_path[0] == '/')
1992 icon_path = icon_path.substr(1);
1993
1994 if (icon_path.empty()) {
1995 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
1996 errors::kInvalidIconPath, key);
1997 return false;
1998 }
1999
2000 icons_.Add(ExtensionIconSet::kIconSizes[i], icon_path);
2001 }
2002 }
2003 }
2004
2005 // Initialize themes (if present).
2006 if (manifest_->HasKey(keys::kTheme)) {
2007 DictionaryValue* theme_value = NULL;
2008 if (!manifest_->GetDictionary(keys::kTheme, &theme_value)) {
2009 *error = ASCIIToUTF16(errors::kInvalidTheme);
2010 return false;
2011 }
2012
2013 DictionaryValue* images_value = NULL;
2014 if (theme_value->GetDictionary(keys::kThemeImages, &images_value)) {
2015 // Validate that the images are all strings
2016 for (DictionaryValue::key_iterator iter = images_value->begin_keys();
2017 iter != images_value->end_keys(); ++iter) {
2018 std::string val;
2019 if (!images_value->GetString(*iter, &val)) {
2020 *error = ASCIIToUTF16(errors::kInvalidThemeImages);
2021 return false;
2022 }
2023 }
2024 theme_images_.reset(images_value->DeepCopy());
2025 }
2026
2027 DictionaryValue* colors_value = NULL;
2028 if (theme_value->GetDictionary(keys::kThemeColors, &colors_value)) {
2029 // Validate that the colors are RGB or RGBA lists
2030 for (DictionaryValue::key_iterator iter = colors_value->begin_keys();
2031 iter != colors_value->end_keys(); ++iter) {
2032 ListValue* color_list = NULL;
2033 double alpha = 0.0;
2034 int color = 0;
2035 // The color must be a list
2036 if (!colors_value->GetListWithoutPathExpansion(*iter, &color_list) ||
2037 // And either 3 items (RGB) or 4 (RGBA)
2038 ((color_list->GetSize() != 3) &&
2039 ((color_list->GetSize() != 4) ||
2040 // For RGBA, the fourth item must be a real or int alpha value.
2041 // Note that GetDouble() can get an integer value.
2042 !color_list->GetDouble(3, &alpha))) ||
2043 // For both RGB and RGBA, the first three items must be ints (R,G,B)
2044 !color_list->GetInteger(0, &color) ||
2045 !color_list->GetInteger(1, &color) ||
2046 !color_list->GetInteger(2, &color)) {
2047 *error = ASCIIToUTF16(errors::kInvalidThemeColors);
2048 return false;
2049 }
2050 }
2051 theme_colors_.reset(colors_value->DeepCopy());
2052 }
2053
2054 DictionaryValue* tints_value = NULL;
2055 if (theme_value->GetDictionary(keys::kThemeTints, &tints_value)) {
2056 // Validate that the tints are all reals.
2057 for (DictionaryValue::key_iterator iter = tints_value->begin_keys();
2058 iter != tints_value->end_keys(); ++iter) {
2059 ListValue* tint_list = NULL;
2060 double v = 0.0;
2061 if (!tints_value->GetListWithoutPathExpansion(*iter, &tint_list) ||
2062 tint_list->GetSize() != 3 ||
2063 !tint_list->GetDouble(0, &v) ||
2064 !tint_list->GetDouble(1, &v) ||
2065 !tint_list->GetDouble(2, &v)) {
2066 *error = ASCIIToUTF16(errors::kInvalidThemeTints);
2067 return false;
2068 }
2069 }
2070 theme_tints_.reset(tints_value->DeepCopy());
2071 }
2072
2073 DictionaryValue* display_properties_value = NULL;
2074 if (theme_value->GetDictionary(keys::kThemeDisplayProperties,
2075 &display_properties_value)) {
2076 theme_display_properties_.reset(
2077 display_properties_value->DeepCopy());
2078 }
2079
2080 return true;
2081 }
2082
2083 // Initialize plugins (optional).
2084 if (manifest_->HasKey(keys::kPlugins)) {
2085 ListValue* list_value = NULL;
2086 if (!manifest_->GetList(keys::kPlugins, &list_value)) {
2087 *error = ASCIIToUTF16(errors::kInvalidPlugins);
2088 return false;
2089 }
2090
2091 for (size_t i = 0; i < list_value->GetSize(); ++i) {
2092 DictionaryValue* plugin_value = NULL;
2093 std::string path_str;
2094 bool is_public = false;
2095
2096 if (!list_value->GetDictionary(i, &plugin_value)) {
2097 *error = ASCIIToUTF16(errors::kInvalidPlugins);
2098 return false;
2099 }
2100
2101 // Get plugins[i].path.
2102 if (!plugin_value->GetString(keys::kPluginsPath, &path_str)) {
2103 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2104 errors::kInvalidPluginsPath, base::IntToString(i));
2105 return false;
2106 }
2107
2108 // Get plugins[i].content (optional).
2109 if (plugin_value->HasKey(keys::kPluginsPublic)) {
2110 if (!plugin_value->GetBoolean(keys::kPluginsPublic, &is_public)) {
2111 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2112 errors::kInvalidPluginsPublic, base::IntToString(i));
2113 return false;
2114 }
2115 }
2116
2117 // We don't allow extension plugins to run on Chrome OS. We still
2118 // parse the manifest entry so that error messages are consistently
2119 // displayed across platforms.
2120 #if !defined(OS_CHROMEOS)
2121 plugins_.push_back(PluginInfo());
2122 plugins_.back().path = path().Append(FilePath::FromUTF8Unsafe(path_str));
2123 plugins_.back().is_public = is_public;
2124 #endif
2125 }
2126 }
2127
2128 if (manifest_->HasKey(keys::kNaClModules)) {
2129 ListValue* list_value = NULL;
2130 if (!manifest_->GetList(keys::kNaClModules, &list_value)) {
2131 *error = ASCIIToUTF16(errors::kInvalidNaClModules);
2132 return false;
2133 }
2134
2135 for (size_t i = 0; i < list_value->GetSize(); ++i) {
2136 DictionaryValue* module_value = NULL;
2137 std::string path_str;
2138 std::string mime_type;
2139
2140 if (!list_value->GetDictionary(i, &module_value)) {
2141 *error = ASCIIToUTF16(errors::kInvalidNaClModules);
2142 return false;
2143 }
2144
2145 // Get nacl_modules[i].path.
2146 if (!module_value->GetString(keys::kNaClModulesPath, &path_str)) {
2147 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2148 errors::kInvalidNaClModulesPath, base::IntToString(i));
2149 return false;
2150 }
2151
2152 // Get nacl_modules[i].mime_type.
2153 if (!module_value->GetString(keys::kNaClModulesMIMEType, &mime_type)) {
2154 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2155 errors::kInvalidNaClModulesMIMEType, base::IntToString(i));
2156 return false;
2157 }
2158
2159 nacl_modules_.push_back(NaClModuleInfo());
2160 nacl_modules_.back().url = GetResourceURL(path_str);
2161 nacl_modules_.back().mime_type = mime_type;
2162 }
2163 }
2164
2165 // Initialize content scripts (optional).
2166 if (manifest_->HasKey(keys::kContentScripts)) {
2167 ListValue* list_value;
2168 if (!manifest_->GetList(keys::kContentScripts, &list_value)) {
2169 *error = ASCIIToUTF16(errors::kInvalidContentScriptsList);
2170 return false;
2171 }
2172
2173 for (size_t i = 0; i < list_value->GetSize(); ++i) {
2174 DictionaryValue* content_script = NULL;
2175 if (!list_value->GetDictionary(i, &content_script)) {
2176 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2177 errors::kInvalidContentScript, base::IntToString(i));
2178 return false;
2179 }
2180
2181 UserScript script;
2182 if (!LoadUserScriptHelper(content_script, i, flags, error, &script))
2183 return false; // Failed to parse script context definition.
2184 script.set_extension_id(id());
2185 if (converted_from_user_script_) {
2186 script.set_emulate_greasemonkey(true);
2187 script.set_match_all_frames(true); // Greasemonkey matches all frames.
2188 }
2189 content_scripts_.push_back(script);
2190 }
2191 }
2192
2193 // Initialize web accessible resources (optional).
2194 if (manifest_->HasKey(keys::kWebAccessibleResources)) {
2195 ListValue* list_value;
2196 if (!manifest_->GetList(keys::kWebAccessibleResources, &list_value)) {
2197 *error = ASCIIToUTF16(errors::kInvalidWebAccessibleResourcesList);
2198 return false;
2199 }
2200 for (size_t i = 0; i < list_value->GetSize(); ++i) {
2201 std::string relative_path;
2202 if (!list_value->GetString(i, &relative_path)) {
2203 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2204 errors::kInvalidWebAccessibleResource, base::IntToString(i));
2205 return false;
2206 }
2207 if (relative_path[0] != '/')
2208 relative_path = '/' + relative_path;
2209 web_accessible_resources_.insert(relative_path);
2210 }
2211 }
2212
2213 // Initialize page action (optional).
2214 DictionaryValue* page_action_value = NULL;
2215
2216 if (manifest_->HasKey(keys::kPageActions)) {
2217 ListValue* list_value = NULL;
2218 if (!manifest_->GetList(keys::kPageActions, &list_value)) {
2219 *error = ASCIIToUTF16(errors::kInvalidPageActionsList);
2220 return false;
2221 }
2222
2223 size_t list_value_length = list_value->GetSize();
2224
2225 if (list_value_length == 0u) {
2226 // A list with zero items is allowed, and is equivalent to not having
2227 // a page_actions key in the manifest. Don't set |page_action_value|.
2228 } else if (list_value_length == 1u) {
2229 if (!list_value->GetDictionary(0, &page_action_value)) {
2230 *error = ASCIIToUTF16(errors::kInvalidPageAction);
2231 return false;
2232 }
2233 } else { // list_value_length > 1u.
2234 *error = ASCIIToUTF16(errors::kInvalidPageActionsListSize);
2235 return false;
2236 }
2237 } else if (manifest_->HasKey(keys::kPageAction)) {
2238 if (!manifest_->GetDictionary(keys::kPageAction, &page_action_value)) {
2239 *error = ASCIIToUTF16(errors::kInvalidPageAction);
2240 return false;
2241 }
2242 }
2243
2244 // If page_action_value is not NULL, then there was a valid page action.
2245 if (page_action_value) {
2246 page_action_.reset(
2247 LoadExtensionActionHelper(page_action_value, error));
2248 if (!page_action_.get())
2249 return false; // Failed to parse page action definition.
2250 }
2251
2252 // Initialize browser action (optional).
2253 if (manifest_->HasKey(keys::kBrowserAction)) {
2254 DictionaryValue* browser_action_value = NULL;
2255 if (!manifest_->GetDictionary(keys::kBrowserAction,
2256 &browser_action_value)) {
2257 *error = ASCIIToUTF16(errors::kInvalidBrowserAction);
2258 return false;
2259 }
2260
2261 browser_action_.reset(
2262 LoadExtensionActionHelper(browser_action_value, error));
2263 if (!browser_action_.get())
2264 return false; // Failed to parse browser action definition.
2265 }
2266
2267 // Initialize file browser actions (optional).
2268 if (manifest_->HasKey(keys::kFileBrowserHandlers)) {
2269 ListValue* file_browser_handlers_value = NULL;
2270 if (!manifest_->GetList(keys::kFileBrowserHandlers,
2271 &file_browser_handlers_value)) {
2272 *error = ASCIIToUTF16(errors::kInvalidFileBrowserHandler);
2273 return false;
2274 }
2275
2276 file_browser_handlers_.reset(
2277 LoadFileBrowserHandlers(file_browser_handlers_value, error));
2278 if (!file_browser_handlers_.get())
2279 return false; // Failed to parse file browser actions definition.
2280 }
2281
2282 // App isolation. 2821 // App isolation.
2283 if (api_permissions.count(ExtensionAPIPermission::kExperimental)) { 2822 if (api_permissions.count(ExtensionAPIPermission::kExperimental) &&
2284 if (is_app() && !LoadAppIsolation(error)) 2823 !LoadAppIsolation(error))
2285 return false; 2824 return false;
2286 } 2825
2287 2826 if (!LoadSharedFeatures(api_permissions, error))
2288 // Initialize options page url (optional). 2827 return false;
2289 if (manifest_->HasKey(keys::kOptionsPage)) { 2828
2290 std::string options_str; 2829 if (!LoadExtensionFeatures(api_permissions, error))
2291 if (!manifest_->GetString(keys::kOptionsPage, &options_str)) { 2830 return false;
2292 *error = ASCIIToUTF16(errors::kInvalidOptionsPage); 2831
2293 return false; 2832 if (!LoadThemeFeatures(error))
2294 } 2833 return false;
2295
2296 if (is_hosted_app()) {
2297 // hosted apps require an absolute URL.
2298 GURL options_url(options_str);
2299 if (!options_url.is_valid() ||
2300 !(options_url.SchemeIs("http") || options_url.SchemeIs("https"))) {
2301 *error = ASCIIToUTF16(errors::kInvalidOptionsPageInHostedApp);
2302 return false;
2303 }
2304 options_url_ = options_url;
2305 } else {
2306 GURL absolute(options_str);
2307 if (absolute.is_valid()) {
2308 *error = ASCIIToUTF16(errors::kInvalidOptionsPageExpectUrlInPackage);
2309 return false;
2310 }
2311 options_url_ = GetResourceURL(options_str);
2312 if (!options_url_.is_valid()) {
2313 *error = ASCIIToUTF16(errors::kInvalidOptionsPage);
2314 return false;
2315 }
2316 }
2317 }
2318
2319 if (!LoadBackgroundScripts(error))
2320 return false;
2321
2322 if (!LoadBackgroundPage(api_permissions, error))
2323 return false;
2324
2325 if (!LoadBackgroundPersistent(api_permissions, error))
2326 return false;
2327
2328 if (manifest_->HasKey(keys::kDefaultLocale)) {
2329 if (!manifest_->GetString(keys::kDefaultLocale, &default_locale_) ||
2330 !l10n_util::IsValidLocaleSyntax(default_locale_)) {
2331 *error = ASCIIToUTF16(errors::kInvalidDefaultLocale);
2332 return false;
2333 }
2334 }
2335
2336 // Chrome URL overrides (optional)
2337 if (manifest_->HasKey(keys::kChromeURLOverrides)) {
2338 DictionaryValue* overrides = NULL;
2339 if (!manifest_->GetDictionary(keys::kChromeURLOverrides, &overrides)) {
2340 *error = ASCIIToUTF16(errors::kInvalidChromeURLOverrides);
2341 return false;
2342 }
2343
2344 // Validate that the overrides are all strings
2345 for (DictionaryValue::key_iterator iter = overrides->begin_keys();
2346 iter != overrides->end_keys(); ++iter) {
2347 std::string page = *iter;
2348 std::string val;
2349 // Restrict override pages to a list of supported URLs.
2350 if ((page != chrome::kChromeUINewTabHost &&
2351 #if defined(USE_VIRTUAL_KEYBOARD)
2352 page != chrome::kChromeUIKeyboardHost &&
2353 #endif
2354 #if defined(OS_CHROMEOS)
2355 page != chrome::kChromeUIActivationMessageHost &&
2356 #endif
2357 page != chrome::kChromeUIBookmarksHost &&
2358 page != chrome::kChromeUIHistoryHost
2359 #if defined(FILE_MANAGER_EXTENSION)
2360 &&
2361 !(location() == COMPONENT &&
2362 page == chrome::kChromeUIFileManagerHost)
2363 #endif
2364 ) ||
2365 !overrides->GetStringWithoutPathExpansion(*iter, &val)) {
2366 *error = ASCIIToUTF16(errors::kInvalidChromeURLOverrides);
2367 return false;
2368 }
2369 // Replace the entry with a fully qualified chrome-extension:// URL.
2370 chrome_url_overrides_[page] = GetResourceURL(val);
2371 }
2372
2373 // An extension may override at most one page.
2374 if (overrides->size() > 1) {
2375 *error = ASCIIToUTF16(errors::kMultipleOverrides);
2376 return false;
2377 }
2378 }
2379
2380 if (manifest_->HasKey(keys::kInputComponents)) {
2381 ListValue* list_value = NULL;
2382 if (!manifest_->GetList(keys::kInputComponents, &list_value)) {
2383 *error = ASCIIToUTF16(errors::kInvalidInputComponents);
2384 return false;
2385 }
2386
2387 for (size_t i = 0; i < list_value->GetSize(); ++i) {
2388 DictionaryValue* module_value = NULL;
2389 std::string name_str;
2390 InputComponentType type;
2391 std::string id_str;
2392 std::string description_str;
2393 std::string language_str;
2394 std::set<std::string> layouts;
2395 std::string shortcut_keycode_str;
2396 bool shortcut_alt = false;
2397 bool shortcut_ctrl = false;
2398 bool shortcut_shift = false;
2399
2400 if (!list_value->GetDictionary(i, &module_value)) {
2401 *error = ASCIIToUTF16(errors::kInvalidInputComponents);
2402 return false;
2403 }
2404
2405 // Get input_components[i].name.
2406 if (!module_value->GetString(keys::kName, &name_str)) {
2407 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2408 errors::kInvalidInputComponentName, base::IntToString(i));
2409 return false;
2410 }
2411
2412 // Get input_components[i].type.
2413 std::string type_str;
2414 if (module_value->GetString(keys::kType, &type_str)) {
2415 if (type_str == "ime") {
2416 type = INPUT_COMPONENT_TYPE_IME;
2417 } else if (type_str == "virtual_keyboard") {
2418 if (!api_permissions.count(ExtensionAPIPermission::kExperimental)) {
2419 // Virtual Keyboards require the experimental flag.
2420 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2421 errors::kInvalidInputComponentType, base::IntToString(i));
2422 return false;
2423 }
2424 type = INPUT_COMPONENT_TYPE_VIRTUAL_KEYBOARD;
2425 } else {
2426 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2427 errors::kInvalidInputComponentType, base::IntToString(i));
2428 return false;
2429 }
2430 } else {
2431 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2432 errors::kInvalidInputComponentType, base::IntToString(i));
2433 return false;
2434 }
2435
2436 // Get input_components[i].id.
2437 if (!module_value->GetString(keys::kId, &id_str)) {
2438 id_str = "";
2439 }
2440
2441 // Get input_components[i].description.
2442 if (!module_value->GetString(keys::kDescription, &description_str)) {
2443 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2444 errors::kInvalidInputComponentDescription, base::IntToString(i));
2445 return false;
2446 }
2447
2448 // Get input_components[i].language.
2449 if (!module_value->GetString(keys::kLanguage, &language_str)) {
2450 language_str = "";
2451 }
2452
2453 // Get input_components[i].layouts.
2454 ListValue* layouts_value = NULL;
2455 if (!module_value->GetList(keys::kLayouts, &layouts_value)) {
2456 *error = ASCIIToUTF16(errors::kInvalidInputComponentLayouts);
2457 return false;
2458 }
2459
2460 for (size_t j = 0; j < layouts_value->GetSize(); ++j) {
2461 std::string layout_name_str;
2462 if (!layouts_value->GetString(j, &layout_name_str)) {
2463 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2464 errors::kInvalidInputComponentLayoutName, base::IntToString(i),
2465 base::IntToString(j));
2466 return false;
2467 }
2468 layouts.insert(layout_name_str);
2469 }
2470
2471 if (module_value->HasKey(keys::kShortcutKey)) {
2472 DictionaryValue* shortcut_value = NULL;
2473 if (!module_value->GetDictionary(keys::kShortcutKey, &shortcut_value)) {
2474 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2475 errors::kInvalidInputComponentShortcutKey, base::IntToString(i));
2476 return false;
2477 }
2478
2479 // Get input_components[i].shortcut_keycode.
2480 if (!shortcut_value->GetString(keys::kKeycode, &shortcut_keycode_str)) {
2481 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2482 errors::kInvalidInputComponentShortcutKeycode,
2483 base::IntToString(i));
2484 return false;
2485 }
2486
2487 // Get input_components[i].shortcut_alt.
2488 if (!shortcut_value->GetBoolean(keys::kAltKey, &shortcut_alt)) {
2489 shortcut_alt = false;
2490 }
2491
2492 // Get input_components[i].shortcut_ctrl.
2493 if (!shortcut_value->GetBoolean(keys::kCtrlKey, &shortcut_ctrl)) {
2494 shortcut_ctrl = false;
2495 }
2496
2497 // Get input_components[i].shortcut_shift.
2498 if (!shortcut_value->GetBoolean(keys::kShiftKey, &shortcut_shift)) {
2499 shortcut_shift = false;
2500 }
2501 }
2502
2503 input_components_.push_back(InputComponentInfo());
2504 input_components_.back().name = name_str;
2505 input_components_.back().type = type;
2506 input_components_.back().id = id_str;
2507 input_components_.back().description = description_str;
2508 input_components_.back().language = language_str;
2509 input_components_.back().layouts.insert(layouts.begin(), layouts.end());
2510 input_components_.back().shortcut_keycode = shortcut_keycode_str;
2511 input_components_.back().shortcut_alt = shortcut_alt;
2512 input_components_.back().shortcut_ctrl = shortcut_ctrl;
2513 input_components_.back().shortcut_shift = shortcut_shift;
2514 }
2515 }
2516
2517 if (manifest_->HasKey(keys::kOmnibox)) {
2518 if (!manifest_->GetString(keys::kOmniboxKeyword, &omnibox_keyword_) ||
2519 omnibox_keyword_.empty()) {
2520 *error = ASCIIToUTF16(errors::kInvalidOmniboxKeyword);
2521 return false;
2522 }
2523 }
2524
2525 if (manifest_->HasKey(keys::kContentSecurityPolicy)) {
2526 std::string content_security_policy;
2527 if (!manifest_->GetString(keys::kContentSecurityPolicy,
2528 &content_security_policy)) {
2529 *error = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
2530 return false;
2531 }
2532 if (!ContentSecurityPolicyIsLegal(content_security_policy)) {
2533 *error = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
2534 return false;
2535 }
2536 if (manifest_version_ >= 2 &&
2537 !ContentSecurityPolicyIsSecure(content_security_policy)) {
2538 *error = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
2539 return false;
2540 }
2541
2542 content_security_policy_ = content_security_policy;
2543 } else if (manifest_version_ >= 2) {
2544 // Manifest version 2 introduced a default Content-Security-Policy.
2545 // TODO(abarth): Should we continue to let extensions override the
2546 // default Content-Security-Policy?
2547 content_security_policy_ = kDefaultContentSecurityPolicy;
2548 CHECK(ContentSecurityPolicyIsSecure(content_security_policy_));
2549 }
2550
2551 // Initialize devtools page url (optional).
2552 if (manifest_->HasKey(keys::kDevToolsPage)) {
2553 std::string devtools_str;
2554 if (!manifest_->GetString(keys::kDevToolsPage, &devtools_str)) {
2555 *error = ASCIIToUTF16(errors::kInvalidDevToolsPage);
2556 return false;
2557 }
2558 devtools_url_ = GetResourceURL(devtools_str);
2559 }
2560
2561 // Initialize text-to-speech voices (optional).
2562 if (manifest_->HasKey(keys::kTtsEngine)) {
2563 DictionaryValue* tts_dict = NULL;
2564 if (!manifest_->GetDictionary(keys::kTtsEngine, &tts_dict)) {
2565 *error = ASCIIToUTF16(errors::kInvalidTts);
2566 return false;
2567 }
2568
2569 if (tts_dict->HasKey(keys::kTtsVoices)) {
2570 ListValue* tts_voices = NULL;
2571 if (!tts_dict->GetList(keys::kTtsVoices, &tts_voices)) {
2572 *error = ASCIIToUTF16(errors::kInvalidTtsVoices);
2573 return false;
2574 }
2575
2576 for (size_t i = 0; i < tts_voices->GetSize(); i++) {
2577 DictionaryValue* one_tts_voice = NULL;
2578 if (!tts_voices->GetDictionary(i, &one_tts_voice)) {
2579 *error = ASCIIToUTF16(errors::kInvalidTtsVoices);
2580 return false;
2581 }
2582
2583 TtsVoice voice_data;
2584 if (one_tts_voice->HasKey(keys::kTtsVoicesVoiceName)) {
2585 if (!one_tts_voice->GetString(
2586 keys::kTtsVoicesVoiceName, &voice_data.voice_name)) {
2587 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesVoiceName);
2588 return false;
2589 }
2590 }
2591 if (one_tts_voice->HasKey(keys::kTtsVoicesLang)) {
2592 if (!one_tts_voice->GetString(
2593 keys::kTtsVoicesLang, &voice_data.lang) ||
2594 !l10n_util::IsValidLocaleSyntax(voice_data.lang)) {
2595 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesLang);
2596 return false;
2597 }
2598 }
2599 if (one_tts_voice->HasKey(keys::kTtsVoicesGender)) {
2600 if (!one_tts_voice->GetString(
2601 keys::kTtsVoicesGender, &voice_data.gender) ||
2602 (voice_data.gender != keys::kTtsGenderMale &&
2603 voice_data.gender != keys::kTtsGenderFemale)) {
2604 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesGender);
2605 return false;
2606 }
2607 }
2608 if (one_tts_voice->HasKey(keys::kTtsVoicesEventTypes)) {
2609 ListValue* event_types_list;
2610 if (!one_tts_voice->GetList(
2611 keys::kTtsVoicesEventTypes, &event_types_list)) {
2612 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
2613 return false;
2614 }
2615 for (size_t i = 0; i < event_types_list->GetSize(); i++) {
2616 std::string event_type;
2617 if (!event_types_list->GetString(i, &event_type)) {
2618 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
2619 return false;
2620 }
2621 if (event_type != keys::kTtsVoicesEventTypeEnd &&
2622 event_type != keys::kTtsVoicesEventTypeError &&
2623 event_type != keys::kTtsVoicesEventTypeMarker &&
2624 event_type != keys::kTtsVoicesEventTypeSentence &&
2625 event_type != keys::kTtsVoicesEventTypeStart &&
2626 event_type != keys::kTtsVoicesEventTypeWord) {
2627 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
2628 return false;
2629 }
2630 if (voice_data.event_types.find(event_type) !=
2631 voice_data.event_types.end()) {
2632 *error = ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
2633 return false;
2634 }
2635 voice_data.event_types.insert(event_type);
2636 }
2637 }
2638
2639 tts_voices_.push_back(voice_data);
2640 }
2641 }
2642 }
2643
2644 // Initialize web intents (optional).
2645 if (!LoadWebIntentServices(error))
2646 return false;
2647
2648 // Initialize incognito behavior. Apps default to split mode, extensions
2649 // default to spanning.
2650 incognito_split_mode_ = is_app();
2651 if (manifest_->HasKey(keys::kIncognito)) {
2652 std::string value;
2653 if (!manifest_->GetString(keys::kIncognito, &value)) {
2654 *error = ASCIIToUTF16(errors::kInvalidIncognitoBehavior);
2655 return false;
2656 }
2657 if (value == values::kIncognitoSpanning) {
2658 incognito_split_mode_ = false;
2659 } else if (value == values::kIncognitoSplit) {
2660 incognito_split_mode_ = true;
2661 } else {
2662 *error = ASCIIToUTF16(errors::kInvalidIncognitoBehavior);
2663 return false;
2664 }
2665 }
2666
2667 // Initialize offline-enabled status. Defaults to false.
2668 if (manifest_->HasKey(keys::kOfflineEnabled)) {
2669 if (!manifest_->GetBoolean(keys::kOfflineEnabled, &offline_enabled_)) {
2670 *error = ASCIIToUTF16(errors::kInvalidOfflineEnabled);
2671 return false;
2672 }
2673 }
2674
2675 // Initialize requirements (optional). Not actually persisted (they're only
2676 // used by the store), but still validated.
2677 if (manifest_->HasKey(keys::kRequirements)) {
2678 DictionaryValue* requirements_value = NULL;
2679 if (!manifest_->GetDictionary(keys::kRequirements, &requirements_value)) {
2680 *error = ASCIIToUTF16(errors::kInvalidRequirements);
2681 return false;
2682 }
2683
2684 for (DictionaryValue::key_iterator it = requirements_value->begin_keys();
2685 it != requirements_value->end_keys(); ++it) {
2686 DictionaryValue* requirement_value;
2687 if (!requirements_value->GetDictionaryWithoutPathExpansion(
2688 *it, &requirement_value)) {
2689 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2690 errors::kInvalidRequirement, *it);
2691 return false;
2692 }
2693 }
2694 }
2695 2834
2696 if (HasMultipleUISurfaces()) { 2835 if (HasMultipleUISurfaces()) {
2697 *error = ASCIIToUTF16(errors::kOneUISurfaceOnly); 2836 *error = ASCIIToUTF16(errors::kOneUISurfaceOnly);
2698 return false; 2837 return false;
2699 } 2838 }
2700 2839
2701 runtime_data_.SetActivePermissions(new ExtensionPermissionSet( 2840 runtime_data_.SetActivePermissions(new ExtensionPermissionSet(
2702 this, api_permissions, host_permissions)); 2841 this, api_permissions, host_permissions));
2703 required_permission_set_ = new ExtensionPermissionSet( 2842 required_permission_set_ = new ExtensionPermissionSet(
2704 this, api_permissions, host_permissions); 2843 this, api_permissions, host_permissions);
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
2854 GURL Extension::GetIconURL(int size, 2993 GURL Extension::GetIconURL(int size,
2855 ExtensionIconSet::MatchType match_type) const { 2994 ExtensionIconSet::MatchType match_type) const {
2856 std::string path = icons().Get(size, match_type); 2995 std::string path = icons().Get(size, match_type);
2857 if (path.empty()) 2996 if (path.empty())
2858 return GURL(); 2997 return GURL();
2859 else 2998 else
2860 return GetResourceURL(path); 2999 return GetResourceURL(path);
2861 } 3000 }
2862 3001
2863 bool Extension::ParsePermissions(const char* key, 3002 bool Extension::ParsePermissions(const char* key,
2864 int flags,
2865 string16* error, 3003 string16* error,
2866 ExtensionAPIPermissionSet* api_permissions, 3004 ExtensionAPIPermissionSet* api_permissions,
2867 URLPatternSet* host_permissions) { 3005 URLPatternSet* host_permissions) {
2868 if (manifest_->HasKey(key)) { 3006 if (manifest_->HasKey(key)) {
2869 ListValue* permissions = NULL; 3007 ListValue* permissions = NULL;
2870 if (!manifest_->GetList(key, &permissions)) { 3008 if (!manifest_->GetList(key, &permissions)) {
2871 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( 3009 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
2872 errors::kInvalidPermissions, ""); 3010 errors::kInvalidPermissions, "");
2873 return false; 3011 return false;
2874 } 3012 }
(...skipping 30 matching lines...) Expand all
2905 return false; 3043 return false;
2906 } 3044 }
2907 3045
2908 // The path component is not used for host permissions, so we force it 3046 // The path component is not used for host permissions, so we force it
2909 // to match all paths. 3047 // to match all paths.
2910 pattern.SetPath("/*"); 3048 pattern.SetPath("/*");
2911 3049
2912 if (pattern.MatchesScheme(chrome::kFileScheme) && 3050 if (pattern.MatchesScheme(chrome::kFileScheme) &&
2913 !CanExecuteScriptEverywhere()) { 3051 !CanExecuteScriptEverywhere()) {
2914 wants_file_access_ = true; 3052 wants_file_access_ = true;
2915 if (!(flags & ALLOW_FILE_ACCESS)) 3053 if (!(creation_flags_ & ALLOW_FILE_ACCESS))
2916 pattern.SetValidSchemes( 3054 pattern.SetValidSchemes(
2917 pattern.valid_schemes() & ~URLPattern::SCHEME_FILE); 3055 pattern.valid_schemes() & ~URLPattern::SCHEME_FILE);
2918 } 3056 }
2919 3057
2920 host_permissions->AddPattern(pattern); 3058 host_permissions->AddPattern(pattern);
2921 } 3059 }
2922 3060
2923 // If it's not a host permission, then it's probably an unknown API 3061 // If it's not a host permission, then it's probably an unknown API
2924 // permission. Do not throw an error so extensions can retain 3062 // permission. Do not throw an error so extensions can retain
2925 // backwards compatability (http://crbug.com/42742). 3063 // backwards compatability (http://crbug.com/42742).
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
3094 // extension with options. All other menu items like uninstall have 3232 // extension with options. All other menu items like uninstall have
3095 // no sense for component extensions. 3233 // no sense for component extensions.
3096 return location() != Extension::COMPONENT; 3234 return location() != Extension::COMPONENT;
3097 } 3235 }
3098 3236
3099 bool Extension::CanSpecifyAPIPermission( 3237 bool Extension::CanSpecifyAPIPermission(
3100 const ExtensionAPIPermission* permission, 3238 const ExtensionAPIPermission* permission,
3101 string16* error) const { 3239 string16* error) const {
3102 if (location() == Extension::COMPONENT) 3240 if (location() == Extension::COMPONENT)
3103 return true; 3241 return true;
3104
3105 bool access_denied = false; 3242 bool access_denied = false;
3106 if (permission->HasWhitelist()) { 3243 if (permission->HasWhitelist()) {
3107 if (permission->IsWhitelisted(id())) 3244 if (permission->IsWhitelisted(id()))
3108 return true; 3245 return true;
3109 else 3246 else
3110 access_denied = true; 3247 access_denied = true;
3111 } else if (permission->is_component_only()) { 3248 } else if (permission->is_component_only()) {
3112 access_denied = true; 3249 access_denied = true;
3113 } 3250 }
3114 3251
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
3272 return SYNC_TYPE_APP; 3409 return SYNC_TYPE_APP;
3273 3410
3274 default: 3411 default:
3275 return SYNC_TYPE_NONE; 3412 return SYNC_TYPE_NONE;
3276 } 3413 }
3277 } 3414 }
3278 3415
3279 bool Extension::IsSyncable() const { 3416 bool Extension::IsSyncable() const {
3280 // TODO(akalin): Figure out if we need to allow some other types. 3417 // TODO(akalin): Figure out if we need to allow some other types.
3281 3418
3282 // We want to sync any extensions that are shown in the luancher because 3419 // We want to sync any extensions that are shown in the launcher because
3283 // their positions should sync. 3420 // their positions should sync.
3284 return location() == Extension::INTERNAL || 3421 return location() == Extension::INTERNAL ||
3285 ShouldDisplayInLauncher(); 3422 ShouldDisplayInLauncher();
3286 } 3423 }
3287 3424
3288 bool Extension::ShouldDisplayInLauncher() const { 3425 bool Extension::ShouldDisplayInLauncher() const {
3289 // All apps should be displayed on the NTP except for the Cloud Print App. 3426 // All apps should be displayed on the NTP except for the Cloud Print App.
3290 return is_app() && id() != extension_misc::kCloudPrintAppId; 3427 return is_app() && id() != extension_misc::kCloudPrintAppId;
3291 } 3428 }
3292 3429
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3325 already_disabled(false), 3462 already_disabled(false),
3326 extension(extension) {} 3463 extension(extension) {}
3327 3464
3328 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( 3465 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo(
3329 const Extension* extension, 3466 const Extension* extension,
3330 const ExtensionPermissionSet* permissions, 3467 const ExtensionPermissionSet* permissions,
3331 Reason reason) 3468 Reason reason)
3332 : reason(reason), 3469 : reason(reason),
3333 extension(extension), 3470 extension(extension),
3334 permissions(permissions) {} 3471 permissions(permissions) {}
OLDNEW
« no previous file with comments | « chrome/common/extensions/extension.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698