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

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

Issue 8654001: Reland restrict extension features based on the extension type. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 15 matching lines...) Expand all
26 #include "chrome/common/chrome_switches.h" 26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/chrome_version_info.h" 27 #include "chrome/common/chrome_version_info.h"
28 #include "chrome/common/extensions/extension_action.h" 28 #include "chrome/common/extensions/extension_action.h"
29 #include "chrome/common/extensions/extension_constants.h" 29 #include "chrome/common/extensions/extension_constants.h"
30 #include "chrome/common/extensions/extension_error_utils.h" 30 #include "chrome/common/extensions/extension_error_utils.h"
31 #include "chrome/common/extensions/extension_l10n_util.h" 31 #include "chrome/common/extensions/extension_l10n_util.h"
32 #include "chrome/common/extensions/extension_resource.h" 32 #include "chrome/common/extensions/extension_resource.h"
33 #include "chrome/common/extensions/extension_sidebar_defaults.h" 33 #include "chrome/common/extensions/extension_sidebar_defaults.h"
34 #include "chrome/common/extensions/extension_sidebar_utils.h" 34 #include "chrome/common/extensions/extension_sidebar_utils.h"
35 #include "chrome/common/extensions/file_browser_handler.h" 35 #include "chrome/common/extensions/file_browser_handler.h"
36 #include "chrome/common/extensions/manifest.h"
36 #include "chrome/common/extensions/user_script.h" 37 #include "chrome/common/extensions/user_script.h"
37 #include "chrome/common/url_constants.h" 38 #include "chrome/common/url_constants.h"
38 #include "googleurl/src/url_util.h" 39 #include "googleurl/src/url_util.h"
39 #include "grit/chromium_strings.h" 40 #include "grit/chromium_strings.h"
40 #include "grit/generated_resources.h" 41 #include "grit/generated_resources.h"
41 #include "grit/theme_resources.h" 42 #include "grit/theme_resources.h"
42 #include "net/base/registry_controlled_domain.h" 43 #include "net/base/registry_controlled_domain.h"
43 #include "third_party/skia/include/core/SkBitmap.h" 44 #include "third_party/skia/include/core/SkBitmap.h"
44 #include "ui/base/l10n/l10n_util.h" 45 #include "ui/base/l10n/l10n_util.h"
45 #include "ui/base/resource/resource_bundle.h" 46 #include "ui/base/resource/resource_bundle.h"
(...skipping 27 matching lines...) Expand all
73 static void ConvertHexadecimalToIDAlphabet(std::string* id) { 74 static void ConvertHexadecimalToIDAlphabet(std::string* id) {
74 for (size_t i = 0; i < id->size(); ++i) { 75 for (size_t i = 0; i < id->size(); ++i) {
75 int val; 76 int val;
76 if (base::HexStringToInt(id->begin() + i, id->begin() + i + 1, &val)) 77 if (base::HexStringToInt(id->begin() + i, id->begin() + i + 1, &val))
77 (*id)[i] = val + 'a'; 78 (*id)[i] = val + 'a';
78 else 79 else
79 (*id)[i] = 'a'; 80 (*id)[i] = 'a';
80 } 81 }
81 } 82 }
82 83
83 // These keys are allowed by all crx files (apps, extensions, themes, etc).
84 static const char* kBaseCrxKeys[] = {
85 keys::kCurrentLocale,
86 keys::kDefaultLocale,
87 keys::kDescription,
88 keys::kIcons,
89 keys::kName,
90 keys::kPublicKey,
91 keys::kSignature,
92 keys::kVersion,
93 keys::kUpdateURL
94 };
95
96 bool IsBaseCrxKey(const std::string& key) {
97 for (size_t i = 0; i < arraysize(kBaseCrxKeys); ++i) {
98 if (key == kBaseCrxKeys[i])
99 return true;
100 }
101
102 return false;
103 }
104
105 // A singleton object containing global data needed by the extension objects. 84 // A singleton object containing global data needed by the extension objects.
106 class ExtensionConfig { 85 class ExtensionConfig {
107 public: 86 public:
108 static ExtensionConfig* GetInstance() { 87 static ExtensionConfig* GetInstance() {
109 return Singleton<ExtensionConfig>::get(); 88 return Singleton<ExtensionConfig>::get();
110 } 89 }
111 90
112 Extension::ScriptingWhitelist* whitelist() { return &scripting_whitelist_; } 91 Extension::ScriptingWhitelist* whitelist() { return &scripting_whitelist_; }
113 92
114 private: 93 private:
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 219
241 // static 220 // static
242 scoped_refptr<Extension> Extension::Create(const FilePath& path, 221 scoped_refptr<Extension> Extension::Create(const FilePath& path,
243 Location location, 222 Location location,
244 const DictionaryValue& value, 223 const DictionaryValue& value,
245 int flags, 224 int flags,
246 std::string* error) { 225 std::string* error) {
247 DCHECK(error); 226 DCHECK(error);
248 scoped_refptr<Extension> extension = new Extension(path, location); 227 scoped_refptr<Extension> extension = new Extension(path, location);
249 228
250 if (!extension->InitFromValue(value, flags, error)) 229 if (!extension->InitFromValue(new extensions::Manifest(value.DeepCopy()),
230 flags, error))
251 return NULL; 231 return NULL;
252 return extension; 232 return extension;
253 } 233 }
254 234
255 scoped_refptr<Extension> Extension::CreateWithId(const FilePath& path, 235 scoped_refptr<Extension> Extension::CreateWithId(const FilePath& path,
256 Location location, 236 Location location,
257 const DictionaryValue& value, 237 const DictionaryValue& value,
258 int flags, 238 int flags,
259 const std::string& explicit_id, 239 const std::string& explicit_id,
260 std::string* error) { 240 std::string* error) {
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 GURL url = extension_sidebar_utils::ResolveRelativePath( 865 GURL url = extension_sidebar_utils::ResolveRelativePath(
886 default_page, this, error); 866 default_page, this, error);
887 if (!url.is_valid()) 867 if (!url.is_valid())
888 return NULL; 868 return NULL;
889 result->set_default_page(url); 869 result->set_default_page(url);
890 } 870 }
891 871
892 return result.release(); 872 return result.release();
893 } 873 }
894 874
895 bool Extension::ContainsNonThemeKeys(const DictionaryValue& source) const { 875 bool Extension::LoadExtent(const extensions::Manifest* manifest,
896 for (DictionaryValue::key_iterator key = source.begin_keys();
897 key != source.end_keys(); ++key) {
898 if (!IsBaseCrxKey(*key) && *key != keys::kTheme)
899 return true;
900 }
901 return false;
902 }
903
904 bool Extension::LoadIsApp(const DictionaryValue* manifest,
905 std::string* error) {
906 if (manifest->HasKey(keys::kApp))
907 is_app_ = true;
908
909 if (CommandLine::ForCurrentProcess()->HasSwitch(
910 switches::kEnablePlatformApps)) {
911 if (manifest->HasKey(keys::kPlatformApp))
912 is_platform_app_ = true;
913 }
914
915 return true;
916 }
917
918 bool Extension::LoadExtent(const DictionaryValue* manifest,
919 const char* key, 876 const char* key,
920 URLPatternSet* extent, 877 URLPatternSet* extent,
921 const char* list_error, 878 const char* list_error,
922 const char* value_error, 879 const char* value_error,
923 URLPattern::ParseOption parse_strictness, 880 URLPattern::ParseOption parse_strictness,
924 std::string* error) { 881 std::string* error) {
925 Value* temp = NULL; 882 Value* temp = NULL;
926 if (!manifest->Get(key, &temp)) 883 if (!manifest->Get(key, &temp))
927 return true; 884 return true;
928 885
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 return false; 942 return false;
986 } 943 }
987 pattern.SetPath(pattern.path() + '*'); 944 pattern.SetPath(pattern.path() + '*');
988 945
989 extent->AddPattern(pattern); 946 extent->AddPattern(pattern);
990 } 947 }
991 948
992 return true; 949 return true;
993 } 950 }
994 951
995 bool Extension::LoadLaunchURL(const DictionaryValue* manifest, 952 bool Extension::LoadLaunchURL(const extensions::Manifest* manifest,
996 std::string* error) { 953 std::string* error) {
997 Value* temp = NULL; 954 Value* temp = NULL;
998 955
999 // launch URL can be either local (to chrome-extension:// root) or an absolute 956 // launch URL can be either local (to chrome-extension:// root) or an absolute
1000 // web URL. 957 // web URL.
1001 if (manifest->Get(keys::kLaunchLocalPath, &temp)) { 958 if (manifest->Get(keys::kLaunchLocalPath, &temp)) {
1002 if (manifest->Get(keys::kLaunchWebURL, NULL)) { 959 if (manifest->Get(keys::kLaunchWebURL, NULL)) {
1003 *error = errors::kLaunchPathAndURLAreExclusive; 960 *error = errors::kLaunchPathAndURLAreExclusive;
1004 return false; 961 return false;
1005 } 962 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1083 GURL::Replacements replacements; 1040 GURL::Replacements replacements;
1084 replacements.SetPathStr(path); 1041 replacements.SetPathStr(path);
1085 GURL cloud_print_enable_connector_url = 1042 GURL cloud_print_enable_connector_url =
1086 cloud_print_service_url.ReplaceComponents(replacements); 1043 cloud_print_service_url.ReplaceComponents(replacements);
1087 OverrideLaunchUrl(cloud_print_enable_connector_url); 1044 OverrideLaunchUrl(cloud_print_enable_connector_url);
1088 } 1045 }
1089 } 1046 }
1090 return true; 1047 return true;
1091 } 1048 }
1092 1049
1093 bool Extension::LoadLaunchContainer(const DictionaryValue* manifest, 1050 bool Extension::LoadLaunchContainer(const extensions::Manifest* manifest,
1094 std::string* error) { 1051 std::string* error) {
1095 Value* temp = NULL; 1052 Value* temp = NULL;
1096 if (!manifest->Get(keys::kLaunchContainer, &temp)) 1053 if (!manifest->Get(keys::kLaunchContainer, &temp))
1097 return true; 1054 return true;
1098 1055
1099 std::string launch_container_string; 1056 std::string launch_container_string;
1100 if (!temp->GetAsString(&launch_container_string)) { 1057 if (!temp->GetAsString(&launch_container_string)) {
1101 *error = errors::kInvalidLaunchContainer; 1058 *error = errors::kInvalidLaunchContainer;
1102 return false; 1059 return false;
1103 } 1060 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1136 if (!temp->GetAsInteger(&launch_height_) || launch_height_ < 0) { 1093 if (!temp->GetAsInteger(&launch_height_) || launch_height_ < 0) {
1137 launch_height_ = 0; 1094 launch_height_ = 0;
1138 *error = errors::kInvalidLaunchHeight; 1095 *error = errors::kInvalidLaunchHeight;
1139 return false; 1096 return false;
1140 } 1097 }
1141 } 1098 }
1142 1099
1143 return true; 1100 return true;
1144 } 1101 }
1145 1102
1146 bool Extension::LoadAppIsolation(const DictionaryValue* manifest, 1103 bool Extension::LoadAppIsolation(const extensions::Manifest* manifest,
1147 std::string* error) { 1104 std::string* error) {
1148 Value* temp = NULL; 1105 Value* temp = NULL;
1149 if (!manifest->Get(keys::kIsolation, &temp)) 1106 if (!manifest->Get(keys::kIsolation, &temp))
1150 return true; 1107 return true;
1151 1108
1152 if (temp->GetType() != Value::TYPE_LIST) { 1109 if (temp->GetType() != Value::TYPE_LIST) {
1153 *error = errors::kInvalidIsolation; 1110 *error = errors::kInvalidIsolation;
1154 return false; 1111 return false;
1155 } 1112 }
1156 1113
(...skipping 11 matching lines...) Expand all
1168 if (isolation_string == values::kIsolatedStorage) { 1125 if (isolation_string == values::kIsolatedStorage) {
1169 is_storage_isolated_ = true; 1126 is_storage_isolated_ = true;
1170 } else { 1127 } else {
1171 DLOG(WARNING) << "Did not recognize isolation type: " 1128 DLOG(WARNING) << "Did not recognize isolation type: "
1172 << isolation_string; 1129 << isolation_string;
1173 } 1130 }
1174 } 1131 }
1175 return true; 1132 return true;
1176 } 1133 }
1177 1134
1178 bool Extension::LoadWebIntentServices(const base::DictionaryValue& manifest, 1135 bool Extension::LoadWebIntentServices(const extensions::Manifest* manifest,
1179 std::string* error) { 1136 std::string* error) {
1180 DCHECK(error); 1137 DCHECK(error);
1181 1138
1182 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableWebIntents)) 1139 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableWebIntents))
1183 return true; 1140 return true;
1184 1141
1185 if (!manifest.HasKey(keys::kIntents)) 1142 if (!manifest->HasKey(keys::kIntents))
1186 return true; 1143 return true;
1187 1144
1188 DictionaryValue* all_services = NULL; 1145 DictionaryValue* all_services = NULL;
1189 if (!manifest.GetDictionary(keys::kIntents, &all_services)) { 1146 if (!manifest->GetDictionary(keys::kIntents, &all_services)) {
1190 *error = errors::kInvalidIntents; 1147 *error = errors::kInvalidIntents;
1191 return false; 1148 return false;
1192 } 1149 }
1193 1150
1194 std::string value; 1151 std::string value;
1195 for (DictionaryValue::key_iterator iter(all_services->begin_keys()); 1152 for (DictionaryValue::key_iterator iter(all_services->begin_keys());
1196 iter != all_services->end_keys(); ++iter) { 1153 iter != all_services->end_keys(); ++iter) {
1197 webkit_glue::WebIntentServiceData service; 1154 webkit_glue::WebIntentServiceData service;
1198 1155
1199 DictionaryValue* one_service = NULL; 1156 DictionaryValue* one_service = NULL;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1238 service.disposition = 1195 service.disposition =
1239 webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW; 1196 webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW;
1240 } 1197 }
1241 } 1198 }
1242 1199
1243 intents_services_.push_back(service); 1200 intents_services_.push_back(service);
1244 } 1201 }
1245 return true; 1202 return true;
1246 } 1203 }
1247 1204
1248
1249 bool Extension::EnsureNotHybridApp(const DictionaryValue* manifest,
1250 std::string* error) {
1251 if (web_extent().is_empty())
1252 return true;
1253
1254 for (DictionaryValue::key_iterator key = manifest->begin_keys();
1255 key != manifest->end_keys(); ++key) {
1256 if (!IsBaseCrxKey(*key) &&
1257 *key != keys::kApp &&
1258 *key != keys::kPermissions &&
1259 *key != keys::kOptionalPermissions &&
1260 *key != keys::kOptionsPage &&
1261 *key != keys::kBackground &&
1262 *key != keys::kOfflineEnabled &&
1263 *key != keys::kMinimumChromeVersion &&
1264 *key != keys::kRequirements) {
1265 *error = ExtensionErrorUtils::FormatErrorMessage(
1266 errors::kHostedAppsCannotIncludeExtensionFeatures, *key);
1267 return false;
1268 }
1269 }
1270
1271 return true;
1272 }
1273
1274 // static 1205 // static
1275 bool Extension::IsTrustedId(const std::string& id) { 1206 bool Extension::IsTrustedId(const std::string& id) {
1276 // See http://b/4946060 for more details. 1207 // See http://b/4946060 for more details.
1277 return id == std::string("nckgahadagoaajjgafhacjanaoiihapd"); 1208 return id == std::string("nckgahadagoaajjgafhacjanaoiihapd");
1278 } 1209 }
1279 1210
1280 Extension::Extension(const FilePath& path, Location location) 1211 Extension::Extension(const FilePath& path, Location location)
1281 : manifest_version_(0), 1212 : manifest_version_(0),
1282 incognito_split_mode_(false), 1213 incognito_split_mode_(false),
1283 offline_enabled_(false), 1214 offline_enabled_(false),
1284 location_(location), 1215 location_(location),
1285 converted_from_user_script_(false), 1216 converted_from_user_script_(false),
1286 is_theme_(false),
1287 is_app_(false),
1288 is_platform_app_(false),
1289 is_storage_isolated_(false), 1217 is_storage_isolated_(false),
1290 launch_container_(extension_misc::LAUNCH_TAB), 1218 launch_container_(extension_misc::LAUNCH_TAB),
1291 launch_width_(0), 1219 launch_width_(0),
1292 launch_height_(0), 1220 launch_height_(0),
1293 wants_file_access_(false), 1221 wants_file_access_(false),
1294 creation_flags_(0) { 1222 creation_flags_(0) {
1295 DCHECK(path.empty() || path.IsAbsolute()); 1223 DCHECK(path.empty() || path.IsAbsolute());
1296 path_ = MaybeNormalizePath(path); 1224 path_ = MaybeNormalizePath(path);
1297 } 1225 }
1298 1226
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1437 return *ResourceBundle::GetSharedInstance().GetBitmapNamed( 1365 return *ResourceBundle::GetSharedInstance().GetBitmapNamed(
1438 IDR_EXTENSION_DEFAULT_ICON); 1366 IDR_EXTENSION_DEFAULT_ICON);
1439 } 1367 }
1440 } 1368 }
1441 1369
1442 GURL Extension::GetBaseURLFromExtensionId(const std::string& extension_id) { 1370 GURL Extension::GetBaseURLFromExtensionId(const std::string& extension_id) {
1443 return GURL(std::string(chrome::kExtensionScheme) + 1371 return GURL(std::string(chrome::kExtensionScheme) +
1444 chrome::kStandardSchemeSeparator + extension_id + "/"); 1372 chrome::kStandardSchemeSeparator + extension_id + "/");
1445 } 1373 }
1446 1374
1447 bool Extension::InitFromValue(const DictionaryValue& source, int flags, 1375 bool Extension::InitFromValue(extensions::Manifest* manifest, int flags,
1448 std::string* error) { 1376 std::string* error) {
1449 DCHECK(error); 1377 DCHECK(error);
1450 base::AutoLock auto_lock(runtime_data_lock_); 1378 base::AutoLock auto_lock(runtime_data_lock_);
1379
1380 if (!manifest->ValidateManifest(error))
1381 return false;
1382
1451 // When strict error checks are enabled, make URL pattern parsing strict. 1383 // When strict error checks are enabled, make URL pattern parsing strict.
1452 URLPattern::ParseOption parse_strictness = 1384 URLPattern::ParseOption parse_strictness =
1453 (flags & STRICT_ERROR_CHECKS ? URLPattern::ERROR_ON_PORTS 1385 (flags & STRICT_ERROR_CHECKS ? URLPattern::ERROR_ON_PORTS
1454 : URLPattern::IGNORE_PORTS); 1386 : URLPattern::IGNORE_PORTS);
1455 1387
1456 // Initialize permissions with an empty, default permission set. 1388 // Initialize permissions with an empty, default permission set.
1457 runtime_data_.SetActivePermissions(new ExtensionPermissionSet()); 1389 runtime_data_.SetActivePermissions(new ExtensionPermissionSet());
1458 optional_permission_set_ = new ExtensionPermissionSet(); 1390 optional_permission_set_ = new ExtensionPermissionSet();
1459 required_permission_set_ = new ExtensionPermissionSet(); 1391 required_permission_set_ = new ExtensionPermissionSet();
1460 1392
1461 if (source.HasKey(keys::kManifestVersion)) { 1393 if (manifest->HasKey(keys::kManifestVersion)) {
1462 int manifest_version = 0; 1394 int manifest_version = 0;
1463 if (!source.GetInteger(keys::kManifestVersion, &manifest_version) || 1395 if (!manifest->GetInteger(keys::kManifestVersion, &manifest_version) ||
1464 manifest_version < 1) { 1396 manifest_version < 1) {
1465 *error = errors::kInvalidManifestVersion; 1397 *error = errors::kInvalidManifestVersion;
1466 return false; 1398 return false;
1467 } 1399 }
1468 manifest_version_ = manifest_version; 1400 manifest_version_ = manifest_version;
1469 } else { 1401 } else {
1470 // Version 1 was the original version, which lacked a version indicator. 1402 // Version 1 was the original version, which lacked a version indicator.
1471 manifest_version_ = 1; 1403 manifest_version_ = 1;
1472 } 1404 }
1473 1405
1474 if (source.HasKey(keys::kPublicKey)) { 1406 if (manifest->HasKey(keys::kPublicKey)) {
1475 std::string public_key_bytes; 1407 std::string public_key_bytes;
1476 if (!source.GetString(keys::kPublicKey, 1408 if (!manifest->GetString(keys::kPublicKey,
1477 &public_key_) || 1409 &public_key_) ||
1478 !ParsePEMKeyBytes(public_key_, 1410 !ParsePEMKeyBytes(public_key_,
1479 &public_key_bytes) || 1411 &public_key_bytes) ||
1480 !GenerateId(public_key_bytes, &id_)) { 1412 !GenerateId(public_key_bytes, &id_)) {
1481 *error = errors::kInvalidKey; 1413 *error = errors::kInvalidKey;
1482 return false; 1414 return false;
1483 } 1415 }
1484 } else if (flags & REQUIRE_KEY) { 1416 } else if (flags & REQUIRE_KEY) {
1485 *error = errors::kInvalidKey; 1417 *error = errors::kInvalidKey;
1486 return false; 1418 return false;
1487 } else { 1419 } else {
1488 // If there is a path, we generate the ID from it. This is useful for 1420 // If there is a path, we generate the ID from it. This is useful for
1489 // development mode, because it keeps the ID stable across restarts and 1421 // development mode, because it keeps the ID stable across restarts and
1490 // reloading the extension. 1422 // reloading the extension.
1491 id_ = Extension::GenerateIdForPath(path()); 1423 id_ = Extension::GenerateIdForPath(path());
1492 if (id_.empty()) { 1424 if (id_.empty()) {
1493 NOTREACHED() << "Could not create ID from path."; 1425 NOTREACHED() << "Could not create ID from path.";
1494 return false; 1426 return false;
1495 } 1427 }
1496 } 1428 }
1497 1429
1498 creation_flags_ = flags; 1430 creation_flags_ = flags;
1499 1431
1500 // Make a copy of the manifest so we can store it in prefs. 1432 manifest_.reset(manifest);
1501 manifest_value_.reset(source.DeepCopy());
1502 1433
1503 // Initialize the URL. 1434 // Initialize the URL.
1504 extension_url_ = Extension::GetBaseURLFromExtensionId(id()); 1435 extension_url_ = Extension::GetBaseURLFromExtensionId(id());
1505 1436
1506 // Initialize version. 1437 // Initialize version.
1507 std::string version_str; 1438 std::string version_str;
1508 if (!source.GetString(keys::kVersion, &version_str)) { 1439 if (!manifest->GetString(keys::kVersion, &version_str)) {
1509 *error = errors::kInvalidVersion; 1440 *error = errors::kInvalidVersion;
1510 return false; 1441 return false;
1511 } 1442 }
1512 version_.reset(Version::GetVersionFromString(version_str)); 1443 version_.reset(Version::GetVersionFromString(version_str));
1513 if (!version_.get() || 1444 if (!version_.get() ||
1514 version_->components().size() > 4) { 1445 version_->components().size() > 4) {
1515 *error = errors::kInvalidVersion; 1446 *error = errors::kInvalidVersion;
1516 return false; 1447 return false;
1517 } 1448 }
1518 1449
1519 // Initialize name. 1450 // Initialize name.
1520 string16 localized_name; 1451 string16 localized_name;
1521 if (!source.GetString(keys::kName, &localized_name)) { 1452 if (!manifest->GetString(keys::kName, &localized_name)) {
1522 *error = errors::kInvalidName; 1453 *error = errors::kInvalidName;
1523 return false; 1454 return false;
1524 } 1455 }
1525 base::i18n::AdjustStringForLocaleDirection(&localized_name); 1456 base::i18n::AdjustStringForLocaleDirection(&localized_name);
1526 name_ = UTF16ToUTF8(localized_name); 1457 name_ = UTF16ToUTF8(localized_name);
1527 1458
1528 // Load App settings. LoadExtent at least has to be done before 1459 // Load App settings. LoadExtent at least has to be done before
1529 // ParsePermissions(), because the valid permissions depend on what type of 1460 // ParsePermissions(), because the valid permissions depend on what type of
1530 // package this is. 1461 // package this is.
1531 if (!LoadIsApp(manifest_value_.get(), error) || 1462 if (is_app() &&
1532 !LoadExtent(manifest_value_.get(), keys::kWebURLs, 1463 (!LoadExtent(manifest_.get(), keys::kWebURLs,
1533 &extent_, 1464 &extent_,
1534 errors::kInvalidWebURLs, errors::kInvalidWebURL, 1465 errors::kInvalidWebURLs, errors::kInvalidWebURL,
1535 parse_strictness, error) || 1466 parse_strictness, error) ||
1536 !EnsureNotHybridApp(manifest_value_.get(), error) || 1467 !LoadLaunchURL(manifest_.get(), error) ||
1537 !LoadLaunchURL(manifest_value_.get(), error) || 1468 !LoadLaunchContainer(manifest_.get(), error))) {
1538 !LoadLaunchContainer(manifest_value_.get(), error)) {
1539 return false; 1469 return false;
1540 } 1470 }
1541 1471
1542 if (is_platform_app_) { 1472 if (is_platform_app()) {
1543 if (launch_container() != extension_misc::LAUNCH_PANEL) { 1473 if (launch_container() != extension_misc::LAUNCH_PANEL) {
1544 *error = errors::kInvalidLaunchContainerForPlatform; 1474 *error = errors::kInvalidLaunchContainerForPlatform;
1545 return false; 1475 return false;
1546 } 1476 }
1547 } 1477 }
1548 1478
1549 // Initialize the permissions (optional). 1479 // Initialize the permissions (optional).
1550 ExtensionAPIPermissionSet api_permissions; 1480 ExtensionAPIPermissionSet api_permissions;
1551 URLPatternSet host_permissions; 1481 URLPatternSet host_permissions;
1552 if (!ParsePermissions(&source, 1482 if (!ParsePermissions(manifest_.get(),
1553 keys::kPermissions, 1483 keys::kPermissions,
1554 flags, 1484 flags,
1555 error, 1485 error,
1556 &api_permissions, 1486 &api_permissions,
1557 &host_permissions)) { 1487 &host_permissions)) {
1558 return false; 1488 return false;
1559 } 1489 }
1560 1490
1561 // Initialize the optional permissions (optional). 1491 // Initialize the optional permissions (optional).
1562 ExtensionAPIPermissionSet optional_api_permissions; 1492 ExtensionAPIPermissionSet optional_api_permissions;
1563 URLPatternSet optional_host_permissions; 1493 URLPatternSet optional_host_permissions;
1564 if (!ParsePermissions(&source, 1494 if (!ParsePermissions(manifest_.get(),
1565 keys::kOptionalPermissions, 1495 keys::kOptionalPermissions,
1566 flags, 1496 flags,
1567 error, 1497 error,
1568 &optional_api_permissions, 1498 &optional_api_permissions,
1569 &optional_host_permissions)) { 1499 &optional_host_permissions)) {
1570 return false; 1500 return false;
1571 } 1501 }
1572 1502
1573 // Initialize description (if present). 1503 // Initialize description (if present).
1574 if (source.HasKey(keys::kDescription)) { 1504 if (manifest->HasKey(keys::kDescription)) {
1575 if (!source.GetString(keys::kDescription, 1505 if (!manifest->GetString(keys::kDescription,
1576 &description_)) { 1506 &description_)) {
1577 *error = errors::kInvalidDescription; 1507 *error = errors::kInvalidDescription;
1578 return false; 1508 return false;
1579 } 1509 }
1580 } 1510 }
1581 1511
1582 // Initialize homepage url (if present). 1512 // Initialize homepage url (if present).
1583 if (source.HasKey(keys::kHomepageURL)) { 1513 if (manifest->HasKey(keys::kHomepageURL)) {
1584 std::string tmp; 1514 std::string tmp;
1585 if (!source.GetString(keys::kHomepageURL, &tmp)) { 1515 if (!manifest->GetString(keys::kHomepageURL, &tmp)) {
1586 *error = ExtensionErrorUtils::FormatErrorMessage( 1516 *error = ExtensionErrorUtils::FormatErrorMessage(
1587 errors::kInvalidHomepageURL, ""); 1517 errors::kInvalidHomepageURL, "");
1588 return false; 1518 return false;
1589 } 1519 }
1590 homepage_url_ = GURL(tmp); 1520 homepage_url_ = GURL(tmp);
1591 if (!homepage_url_.is_valid() || 1521 if (!homepage_url_.is_valid() ||
1592 (!homepage_url_.SchemeIs("http") && 1522 (!homepage_url_.SchemeIs("http") &&
1593 !homepage_url_.SchemeIs("https"))) { 1523 !homepage_url_.SchemeIs("https"))) {
1594 *error = ExtensionErrorUtils::FormatErrorMessage( 1524 *error = ExtensionErrorUtils::FormatErrorMessage(
1595 errors::kInvalidHomepageURL, tmp); 1525 errors::kInvalidHomepageURL, tmp);
1596 return false; 1526 return false;
1597 } 1527 }
1598 } 1528 }
1599 1529
1600 // Initialize update url (if present). 1530 // Initialize update url (if present).
1601 if (source.HasKey(keys::kUpdateURL)) { 1531 if (manifest->HasKey(keys::kUpdateURL)) {
1602 std::string tmp; 1532 std::string tmp;
1603 if (!source.GetString(keys::kUpdateURL, &tmp)) { 1533 if (!manifest->GetString(keys::kUpdateURL, &tmp)) {
1604 *error = ExtensionErrorUtils::FormatErrorMessage( 1534 *error = ExtensionErrorUtils::FormatErrorMessage(
1605 errors::kInvalidUpdateURL, ""); 1535 errors::kInvalidUpdateURL, "");
1606 return false; 1536 return false;
1607 } 1537 }
1608 update_url_ = GURL(tmp); 1538 update_url_ = GURL(tmp);
1609 if (!update_url_.is_valid() || 1539 if (!update_url_.is_valid() ||
1610 update_url_.has_ref()) { 1540 update_url_.has_ref()) {
1611 *error = ExtensionErrorUtils::FormatErrorMessage( 1541 *error = ExtensionErrorUtils::FormatErrorMessage(
1612 errors::kInvalidUpdateURL, tmp); 1542 errors::kInvalidUpdateURL, tmp);
1613 return false; 1543 return false;
1614 } 1544 }
1615 } 1545 }
1616 1546
1617 // Validate minimum Chrome version (if present). We don't need to store this, 1547 // Validate minimum Chrome version (if present). We don't need to store this,
1618 // since the extension is not valid if it is incorrect. 1548 // since the extension is not valid if it is incorrect.
1619 if (source.HasKey(keys::kMinimumChromeVersion)) { 1549 if (manifest->HasKey(keys::kMinimumChromeVersion)) {
1620 std::string minimum_version_string; 1550 std::string minimum_version_string;
1621 if (!source.GetString(keys::kMinimumChromeVersion, 1551 if (!manifest->GetString(keys::kMinimumChromeVersion,
1622 &minimum_version_string)) { 1552 &minimum_version_string)) {
1623 *error = errors::kInvalidMinimumChromeVersion; 1553 *error = errors::kInvalidMinimumChromeVersion;
1624 return false; 1554 return false;
1625 } 1555 }
1626 1556
1627 scoped_ptr<Version> minimum_version( 1557 scoped_ptr<Version> minimum_version(
1628 Version::GetVersionFromString(minimum_version_string)); 1558 Version::GetVersionFromString(minimum_version_string));
1629 if (!minimum_version.get()) { 1559 if (!minimum_version.get()) {
1630 *error = errors::kInvalidMinimumChromeVersion; 1560 *error = errors::kInvalidMinimumChromeVersion;
1631 return false; 1561 return false;
(...skipping 15 matching lines...) Expand all
1647 if (current_version->CompareTo(*minimum_version) < 0) { 1577 if (current_version->CompareTo(*minimum_version) < 0) {
1648 *error = ExtensionErrorUtils::FormatErrorMessage( 1578 *error = ExtensionErrorUtils::FormatErrorMessage(
1649 errors::kChromeVersionTooLow, 1579 errors::kChromeVersionTooLow,
1650 l10n_util::GetStringUTF8(IDS_PRODUCT_NAME), 1580 l10n_util::GetStringUTF8(IDS_PRODUCT_NAME),
1651 minimum_version_string); 1581 minimum_version_string);
1652 return false; 1582 return false;
1653 } 1583 }
1654 } 1584 }
1655 1585
1656 // Initialize converted_from_user_script (if present) 1586 // Initialize converted_from_user_script (if present)
1657 source.GetBoolean(keys::kConvertedFromUserScript, 1587 if (manifest->HasKey(keys::kConvertedFromUserScript))
1658 &converted_from_user_script_); 1588 manifest->GetBoolean(keys::kConvertedFromUserScript,
1589 &converted_from_user_script_);
1659 1590
1660 // Initialize icons (if present). 1591 // Initialize icons (if present).
1661 if (source.HasKey(keys::kIcons)) { 1592 if (manifest->HasKey(keys::kIcons)) {
1662 DictionaryValue* icons_value = NULL; 1593 DictionaryValue* icons_value = NULL;
1663 if (!source.GetDictionary(keys::kIcons, &icons_value)) { 1594 if (!manifest->GetDictionary(keys::kIcons, &icons_value)) {
1664 *error = errors::kInvalidIcons; 1595 *error = errors::kInvalidIcons;
1665 return false; 1596 return false;
1666 } 1597 }
1667 1598
1668 for (size_t i = 0; i < arraysize(kIconSizes); ++i) { 1599 for (size_t i = 0; i < arraysize(kIconSizes); ++i) {
1669 std::string key = base::IntToString(kIconSizes[i]); 1600 std::string key = base::IntToString(kIconSizes[i]);
1670 if (icons_value->HasKey(key)) { 1601 if (icons_value->HasKey(key)) {
1671 std::string icon_path; 1602 std::string icon_path;
1672 if (!icons_value->GetString(key, &icon_path)) { 1603 if (!icons_value->GetString(key, &icon_path)) {
1673 *error = ExtensionErrorUtils::FormatErrorMessage( 1604 *error = ExtensionErrorUtils::FormatErrorMessage(
1674 errors::kInvalidIconPath, key); 1605 errors::kInvalidIconPath, key);
1675 return false; 1606 return false;
1676 } 1607 }
1677 1608
1678 if (!icon_path.empty() && icon_path[0] == '/') 1609 if (!icon_path.empty() && icon_path[0] == '/')
1679 icon_path = icon_path.substr(1); 1610 icon_path = icon_path.substr(1);
1680 1611
1681 if (icon_path.empty()) { 1612 if (icon_path.empty()) {
1682 *error = ExtensionErrorUtils::FormatErrorMessage( 1613 *error = ExtensionErrorUtils::FormatErrorMessage(
1683 errors::kInvalidIconPath, key); 1614 errors::kInvalidIconPath, key);
1684 return false; 1615 return false;
1685 } 1616 }
1686 1617
1687 icons_.Add(kIconSizes[i], icon_path); 1618 icons_.Add(kIconSizes[i], icon_path);
1688 } 1619 }
1689 } 1620 }
1690 } 1621 }
1691 1622
1692 // Initialize themes (if present). 1623 // Initialize themes (if present).
1693 is_theme_ = false; 1624 if (manifest->HasKey(keys::kTheme)) {
1694 if (source.HasKey(keys::kTheme)) { 1625 DictionaryValue* theme_value = NULL;
1695 // Themes cannot contain extension keys. 1626 if (!manifest->GetDictionary(keys::kTheme, &theme_value)) {
1696 if (ContainsNonThemeKeys(source)) { 1627 *error = errors::kInvalidTheme;
1697 *error = errors::kThemesCannotContainExtensions;
1698 return false; 1628 return false;
1699 } 1629 }
1700 1630
1701 DictionaryValue* theme_value = NULL;
1702 if (!source.GetDictionary(keys::kTheme, &theme_value)) {
1703 *error = errors::kInvalidTheme;
1704 return false;
1705 }
1706 is_theme_ = true;
1707
1708 DictionaryValue* images_value = NULL; 1631 DictionaryValue* images_value = NULL;
1709 if (theme_value->GetDictionary(keys::kThemeImages, &images_value)) { 1632 if (theme_value->GetDictionary(keys::kThemeImages, &images_value)) {
1710 // Validate that the images are all strings 1633 // Validate that the images are all strings
1711 for (DictionaryValue::key_iterator iter = images_value->begin_keys(); 1634 for (DictionaryValue::key_iterator iter = images_value->begin_keys();
1712 iter != images_value->end_keys(); ++iter) { 1635 iter != images_value->end_keys(); ++iter) {
1713 std::string val; 1636 std::string val;
1714 if (!images_value->GetString(*iter, &val)) { 1637 if (!images_value->GetString(*iter, &val)) {
1715 *error = errors::kInvalidThemeImages; 1638 *error = errors::kInvalidThemeImages;
1716 return false; 1639 return false;
1717 } 1640 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1769 if (theme_value->GetDictionary(keys::kThemeDisplayProperties, 1692 if (theme_value->GetDictionary(keys::kThemeDisplayProperties,
1770 &display_properties_value)) { 1693 &display_properties_value)) {
1771 theme_display_properties_.reset( 1694 theme_display_properties_.reset(
1772 display_properties_value->DeepCopy()); 1695 display_properties_value->DeepCopy());
1773 } 1696 }
1774 1697
1775 return true; 1698 return true;
1776 } 1699 }
1777 1700
1778 // Initialize plugins (optional). 1701 // Initialize plugins (optional).
1779 if (source.HasKey(keys::kPlugins)) { 1702 if (manifest->HasKey(keys::kPlugins)) {
1780 ListValue* list_value = NULL; 1703 ListValue* list_value = NULL;
1781 if (!source.GetList(keys::kPlugins, &list_value)) { 1704 if (!manifest->GetList(keys::kPlugins, &list_value)) {
1782 *error = errors::kInvalidPlugins; 1705 *error = errors::kInvalidPlugins;
1783 return false; 1706 return false;
1784 } 1707 }
1785 1708
1786 for (size_t i = 0; i < list_value->GetSize(); ++i) { 1709 for (size_t i = 0; i < list_value->GetSize(); ++i) {
1787 DictionaryValue* plugin_value = NULL; 1710 DictionaryValue* plugin_value = NULL;
1788 std::string path_str; 1711 std::string path_str;
1789 bool is_public = false; 1712 bool is_public = false;
1790 1713
1791 if (!list_value->GetDictionary(i, &plugin_value)) { 1714 if (!list_value->GetDictionary(i, &plugin_value)) {
(...skipping 21 matching lines...) Expand all
1813 // parse the manifest entry so that error messages are consistently 1736 // parse the manifest entry so that error messages are consistently
1814 // displayed across platforms. 1737 // displayed across platforms.
1815 #if !defined(OS_CHROMEOS) 1738 #if !defined(OS_CHROMEOS)
1816 plugins_.push_back(PluginInfo()); 1739 plugins_.push_back(PluginInfo());
1817 plugins_.back().path = path().Append(FilePath::FromUTF8Unsafe(path_str)); 1740 plugins_.back().path = path().Append(FilePath::FromUTF8Unsafe(path_str));
1818 plugins_.back().is_public = is_public; 1741 plugins_.back().is_public = is_public;
1819 #endif 1742 #endif
1820 } 1743 }
1821 } 1744 }
1822 1745
1823 if (source.HasKey(keys::kNaClModules)) { 1746 if (manifest->HasKey(keys::kNaClModules)) {
1824 ListValue* list_value = NULL; 1747 ListValue* list_value = NULL;
1825 if (!source.GetList(keys::kNaClModules, &list_value)) { 1748 if (!manifest->GetList(keys::kNaClModules, &list_value)) {
1826 *error = errors::kInvalidNaClModules; 1749 *error = errors::kInvalidNaClModules;
1827 return false; 1750 return false;
1828 } 1751 }
1829 1752
1830 for (size_t i = 0; i < list_value->GetSize(); ++i) { 1753 for (size_t i = 0; i < list_value->GetSize(); ++i) {
1831 DictionaryValue* module_value = NULL; 1754 DictionaryValue* module_value = NULL;
1832 std::string path_str; 1755 std::string path_str;
1833 std::string mime_type; 1756 std::string mime_type;
1834 1757
1835 if (!list_value->GetDictionary(i, &module_value)) { 1758 if (!list_value->GetDictionary(i, &module_value)) {
(...skipping 15 matching lines...) Expand all
1851 return false; 1774 return false;
1852 } 1775 }
1853 1776
1854 nacl_modules_.push_back(NaClModuleInfo()); 1777 nacl_modules_.push_back(NaClModuleInfo());
1855 nacl_modules_.back().url = GetResourceURL(path_str); 1778 nacl_modules_.back().url = GetResourceURL(path_str);
1856 nacl_modules_.back().mime_type = mime_type; 1779 nacl_modules_.back().mime_type = mime_type;
1857 } 1780 }
1858 } 1781 }
1859 1782
1860 // Initialize content scripts (optional). 1783 // Initialize content scripts (optional).
1861 if (source.HasKey(keys::kContentScripts)) { 1784 if (manifest->HasKey(keys::kContentScripts)) {
1862 ListValue* list_value; 1785 ListValue* list_value;
1863 if (!source.GetList(keys::kContentScripts, &list_value)) { 1786 if (!manifest->GetList(keys::kContentScripts, &list_value)) {
1864 *error = errors::kInvalidContentScriptsList; 1787 *error = errors::kInvalidContentScriptsList;
1865 return false; 1788 return false;
1866 } 1789 }
1867 1790
1868 for (size_t i = 0; i < list_value->GetSize(); ++i) { 1791 for (size_t i = 0; i < list_value->GetSize(); ++i) {
1869 DictionaryValue* content_script = NULL; 1792 DictionaryValue* content_script = NULL;
1870 if (!list_value->GetDictionary(i, &content_script)) { 1793 if (!list_value->GetDictionary(i, &content_script)) {
1871 *error = ExtensionErrorUtils::FormatErrorMessage( 1794 *error = ExtensionErrorUtils::FormatErrorMessage(
1872 errors::kInvalidContentScript, base::IntToString(i)); 1795 errors::kInvalidContentScript, base::IntToString(i));
1873 return false; 1796 return false;
1874 } 1797 }
1875 1798
1876 UserScript script; 1799 UserScript script;
1877 if (!LoadUserScriptHelper(content_script, i, flags, error, &script)) 1800 if (!LoadUserScriptHelper(content_script, i, flags, error, &script))
1878 return false; // Failed to parse script context definition. 1801 return false; // Failed to parse script context definition.
1879 script.set_extension_id(id()); 1802 script.set_extension_id(id());
1880 if (converted_from_user_script_) { 1803 if (converted_from_user_script_) {
1881 script.set_emulate_greasemonkey(true); 1804 script.set_emulate_greasemonkey(true);
1882 script.set_match_all_frames(true); // Greasemonkey matches all frames. 1805 script.set_match_all_frames(true); // Greasemonkey matches all frames.
1883 } 1806 }
1884 content_scripts_.push_back(script); 1807 content_scripts_.push_back(script);
1885 } 1808 }
1886 } 1809 }
1887 1810
1888 // Initialize page action (optional). 1811 // Initialize page action (optional).
1889 DictionaryValue* page_action_value = NULL; 1812 DictionaryValue* page_action_value = NULL;
1890 1813
1891 if (source.HasKey(keys::kPageActions)) { 1814 if (manifest->HasKey(keys::kPageActions)) {
1892 ListValue* list_value = NULL; 1815 ListValue* list_value = NULL;
1893 if (!source.GetList(keys::kPageActions, &list_value)) { 1816 if (!manifest->GetList(keys::kPageActions, &list_value)) {
1894 *error = errors::kInvalidPageActionsList; 1817 *error = errors::kInvalidPageActionsList;
1895 return false; 1818 return false;
1896 } 1819 }
1897 1820
1898 size_t list_value_length = list_value->GetSize(); 1821 size_t list_value_length = list_value->GetSize();
1899 1822
1900 if (list_value_length == 0u) { 1823 if (list_value_length == 0u) {
1901 // A list with zero items is allowed, and is equivalent to not having 1824 // A list with zero items is allowed, and is equivalent to not having
1902 // a page_actions key in the manifest. Don't set |page_action_value|. 1825 // a page_actions key in the manifest. Don't set |page_action_value|.
1903 } else if (list_value_length == 1u) { 1826 } else if (list_value_length == 1u) {
1904 if (!list_value->GetDictionary(0, &page_action_value)) { 1827 if (!list_value->GetDictionary(0, &page_action_value)) {
1905 *error = errors::kInvalidPageAction; 1828 *error = errors::kInvalidPageAction;
1906 return false; 1829 return false;
1907 } 1830 }
1908 } else { // list_value_length > 1u. 1831 } else { // list_value_length > 1u.
1909 *error = errors::kInvalidPageActionsListSize; 1832 *error = errors::kInvalidPageActionsListSize;
1910 return false; 1833 return false;
1911 } 1834 }
1912 } else if (source.HasKey(keys::kPageAction)) { 1835 } else if (manifest->HasKey(keys::kPageAction)) {
1913 if (!source.GetDictionary(keys::kPageAction, &page_action_value)) { 1836 if (!manifest->GetDictionary(keys::kPageAction, &page_action_value)) {
1914 *error = errors::kInvalidPageAction; 1837 *error = errors::kInvalidPageAction;
1915 return false; 1838 return false;
1916 } 1839 }
1917 } 1840 }
1918 1841
1919 // If page_action_value is not NULL, then there was a valid page action. 1842 // If page_action_value is not NULL, then there was a valid page action.
1920 if (page_action_value) { 1843 if (page_action_value) {
1921 page_action_.reset( 1844 page_action_.reset(
1922 LoadExtensionActionHelper(page_action_value, error)); 1845 LoadExtensionActionHelper(page_action_value, error));
1923 if (!page_action_.get()) 1846 if (!page_action_.get())
1924 return false; // Failed to parse page action definition. 1847 return false; // Failed to parse page action definition.
1925 } 1848 }
1926 1849
1927 // Initialize browser action (optional). 1850 // Initialize browser action (optional).
1928 if (source.HasKey(keys::kBrowserAction)) { 1851 if (manifest->HasKey(keys::kBrowserAction)) {
1929 DictionaryValue* browser_action_value = NULL; 1852 DictionaryValue* browser_action_value = NULL;
1930 if (!source.GetDictionary(keys::kBrowserAction, &browser_action_value)) { 1853 if (!manifest->GetDictionary(keys::kBrowserAction, &browser_action_value)) {
1931 *error = errors::kInvalidBrowserAction; 1854 *error = errors::kInvalidBrowserAction;
1932 return false; 1855 return false;
1933 } 1856 }
1934 1857
1935 browser_action_.reset( 1858 browser_action_.reset(
1936 LoadExtensionActionHelper(browser_action_value, error)); 1859 LoadExtensionActionHelper(browser_action_value, error));
1937 if (!browser_action_.get()) 1860 if (!browser_action_.get())
1938 return false; // Failed to parse browser action definition. 1861 return false; // Failed to parse browser action definition.
1939 } 1862 }
1940 1863
1941 // Initialize file browser actions (optional). 1864 // Initialize file browser actions (optional).
1942 if (source.HasKey(keys::kFileBrowserHandlers)) { 1865 if (manifest->HasKey(keys::kFileBrowserHandlers)) {
1943 ListValue* file_browser_handlers_value = NULL; 1866 ListValue* file_browser_handlers_value = NULL;
1944 if (!source.GetList(keys::kFileBrowserHandlers, 1867 if (!manifest->GetList(keys::kFileBrowserHandlers,
1945 &file_browser_handlers_value)) { 1868 &file_browser_handlers_value)) {
1946 *error = errors::kInvalidFileBrowserHandler; 1869 *error = errors::kInvalidFileBrowserHandler;
1947 return false; 1870 return false;
1948 } 1871 }
1949 1872
1950 file_browser_handlers_.reset( 1873 file_browser_handlers_.reset(
1951 LoadFileBrowserHandlers(file_browser_handlers_value, error)); 1874 LoadFileBrowserHandlers(file_browser_handlers_value, error));
1952 if (!file_browser_handlers_.get()) 1875 if (!file_browser_handlers_.get())
1953 return false; // Failed to parse file browser actions definition. 1876 return false; // Failed to parse file browser actions definition.
1954 } 1877 }
1955 1878
1956 // App isolation. 1879 // App isolation.
1957 if (api_permissions.count(ExtensionAPIPermission::kExperimental)) { 1880 if (api_permissions.count(ExtensionAPIPermission::kExperimental)) {
1958 if (!LoadAppIsolation(manifest_value_.get(), error)) 1881 if (is_app() && !LoadAppIsolation(manifest_.get(), error))
1959 return false; 1882 return false;
1960 } 1883 }
1961 1884
1962 // Initialize options page url (optional). 1885 // Initialize options page url (optional).
1963 // Function LoadIsApp() set is_app_ above. 1886 if (manifest->HasKey(keys::kOptionsPage)) {
1964 if (source.HasKey(keys::kOptionsPage)) {
1965 std::string options_str; 1887 std::string options_str;
1966 if (!source.GetString(keys::kOptionsPage, &options_str)) { 1888 if (!manifest->GetString(keys::kOptionsPage, &options_str)) {
1967 *error = errors::kInvalidOptionsPage; 1889 *error = errors::kInvalidOptionsPage;
1968 return false; 1890 return false;
1969 } 1891 }
1970 1892
1971 if (is_hosted_app()) { 1893 if (is_hosted_app()) {
1972 // hosted apps require an absolute URL. 1894 // hosted apps require an absolute URL.
1973 GURL options_url(options_str); 1895 GURL options_url(options_str);
1974 if (!options_url.is_valid() || 1896 if (!options_url.is_valid() ||
1975 !(options_url.SchemeIs("http") || options_url.SchemeIs("https"))) { 1897 !(options_url.SchemeIs("http") || options_url.SchemeIs("https"))) {
1976 *error = errors::kInvalidOptionsPageInHostedApp; 1898 *error = errors::kInvalidOptionsPageInHostedApp;
1977 return false; 1899 return false;
1978 } 1900 }
1979 options_url_ = options_url; 1901 options_url_ = options_url;
1980 } else { 1902 } else {
1981 GURL absolute(options_str); 1903 GURL absolute(options_str);
1982 if (absolute.is_valid()) { 1904 if (absolute.is_valid()) {
1983 *error = errors::kInvalidOptionsPageExpectUrlInPackage; 1905 *error = errors::kInvalidOptionsPageExpectUrlInPackage;
1984 return false; 1906 return false;
1985 } 1907 }
1986 options_url_ = GetResourceURL(options_str); 1908 options_url_ = GetResourceURL(options_str);
1987 if (!options_url_.is_valid()) { 1909 if (!options_url_.is_valid()) {
1988 *error = errors::kInvalidOptionsPage; 1910 *error = errors::kInvalidOptionsPage;
1989 return false; 1911 return false;
1990 } 1912 }
1991 } 1913 }
1992 } 1914 }
1993 1915
1994 // Initialize background url (optional). 1916 // Initialize background url (optional).
1995 if (source.HasKey(keys::kBackground)) { 1917 if (manifest->HasKey(keys::kBackground)) {
1996 std::string background_str; 1918 std::string background_str;
1997 if (!source.GetString(keys::kBackground, &background_str)) { 1919 if (!manifest->GetString(keys::kBackground, &background_str)) {
1998 *error = errors::kInvalidBackground; 1920 *error = errors::kInvalidBackground;
1999 return false; 1921 return false;
2000 } 1922 }
2001 1923
2002 if (is_hosted_app()) { 1924 if (is_hosted_app()) {
2003 // Make sure "background" permission is set. 1925 // Make sure "background" permission is set.
2004 if (!api_permissions.count(ExtensionAPIPermission::kBackground)) { 1926 if (!api_permissions.count(ExtensionAPIPermission::kBackground)) {
2005 *error = errors::kBackgroundPermissionNeeded; 1927 *error = errors::kBackgroundPermissionNeeded;
2006 return false; 1928 return false;
2007 } 1929 }
(...skipping 10 matching lines...) Expand all
2018 bg_page.SchemeIs("http")))) { 1940 bg_page.SchemeIs("http")))) {
2019 *error = errors::kInvalidBackgroundInHostedApp; 1941 *error = errors::kInvalidBackgroundInHostedApp;
2020 return false; 1942 return false;
2021 } 1943 }
2022 background_url_ = bg_page; 1944 background_url_ = bg_page;
2023 } else { 1945 } else {
2024 background_url_ = GetResourceURL(background_str); 1946 background_url_ = GetResourceURL(background_str);
2025 } 1947 }
2026 } 1948 }
2027 1949
2028 if (source.HasKey(keys::kDefaultLocale)) { 1950 if (manifest->HasKey(keys::kDefaultLocale)) {
2029 if (!source.GetString(keys::kDefaultLocale, &default_locale_) || 1951 if (!manifest->GetString(keys::kDefaultLocale, &default_locale_) ||
2030 !l10n_util::IsValidLocaleSyntax(default_locale_)) { 1952 !l10n_util::IsValidLocaleSyntax(default_locale_)) {
2031 *error = errors::kInvalidDefaultLocale; 1953 *error = errors::kInvalidDefaultLocale;
2032 return false; 1954 return false;
2033 } 1955 }
2034 } 1956 }
2035 1957
2036 // Chrome URL overrides (optional) 1958 // Chrome URL overrides (optional)
2037 if (source.HasKey(keys::kChromeURLOverrides)) { 1959 if (manifest->HasKey(keys::kChromeURLOverrides)) {
2038 DictionaryValue* overrides = NULL; 1960 DictionaryValue* overrides = NULL;
2039 if (!source.GetDictionary(keys::kChromeURLOverrides, &overrides)) { 1961 if (!manifest->GetDictionary(keys::kChromeURLOverrides, &overrides)) {
2040 *error = errors::kInvalidChromeURLOverrides; 1962 *error = errors::kInvalidChromeURLOverrides;
2041 return false; 1963 return false;
2042 } 1964 }
2043 1965
2044 // Validate that the overrides are all strings 1966 // Validate that the overrides are all strings
2045 for (DictionaryValue::key_iterator iter = overrides->begin_keys(); 1967 for (DictionaryValue::key_iterator iter = overrides->begin_keys();
2046 iter != overrides->end_keys(); ++iter) { 1968 iter != overrides->end_keys(); ++iter) {
2047 std::string page = *iter; 1969 std::string page = *iter;
2048 std::string val; 1970 std::string val;
2049 // Restrict override pages to a list of supported URLs. 1971 // Restrict override pages to a list of supported URLs.
(...skipping 21 matching lines...) Expand all
2071 } 1993 }
2072 1994
2073 // An extension may override at most one page. 1995 // An extension may override at most one page.
2074 if (overrides->size() > 1) { 1996 if (overrides->size() > 1) {
2075 *error = errors::kMultipleOverrides; 1997 *error = errors::kMultipleOverrides;
2076 return false; 1998 return false;
2077 } 1999 }
2078 } 2000 }
2079 2001
2080 if (api_permissions.count(ExtensionAPIPermission::kExperimental) && 2002 if (api_permissions.count(ExtensionAPIPermission::kExperimental) &&
2081 source.HasKey(keys::kInputComponents)) { 2003 manifest->HasKey(keys::kInputComponents)) {
2082 ListValue* list_value = NULL; 2004 ListValue* list_value = NULL;
2083 if (!source.GetList(keys::kInputComponents, &list_value)) { 2005 if (!manifest->GetList(keys::kInputComponents, &list_value)) {
2084 *error = errors::kInvalidInputComponents; 2006 *error = errors::kInvalidInputComponents;
2085 return false; 2007 return false;
2086 } 2008 }
2087 2009
2088 for (size_t i = 0; i < list_value->GetSize(); ++i) { 2010 for (size_t i = 0; i < list_value->GetSize(); ++i) {
2089 DictionaryValue* module_value = NULL; 2011 DictionaryValue* module_value = NULL;
2090 std::string name_str; 2012 std::string name_str;
2091 InputComponentType type; 2013 InputComponentType type;
2092 std::string id_str; 2014 std::string id_str;
2093 std::string description_str; 2015 std::string description_str;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
2202 input_components_.back().description = description_str; 2124 input_components_.back().description = description_str;
2203 input_components_.back().language = language_str; 2125 input_components_.back().language = language_str;
2204 input_components_.back().layouts.insert(layouts.begin(), layouts.end()); 2126 input_components_.back().layouts.insert(layouts.begin(), layouts.end());
2205 input_components_.back().shortcut_keycode = shortcut_keycode_str; 2127 input_components_.back().shortcut_keycode = shortcut_keycode_str;
2206 input_components_.back().shortcut_alt = shortcut_alt; 2128 input_components_.back().shortcut_alt = shortcut_alt;
2207 input_components_.back().shortcut_ctrl = shortcut_ctrl; 2129 input_components_.back().shortcut_ctrl = shortcut_ctrl;
2208 input_components_.back().shortcut_shift = shortcut_shift; 2130 input_components_.back().shortcut_shift = shortcut_shift;
2209 } 2131 }
2210 } 2132 }
2211 2133
2212 if (source.HasKey(keys::kOmnibox)) { 2134 if (manifest->HasKey(keys::kOmnibox)) {
2213 if (!source.GetString(keys::kOmniboxKeyword, &omnibox_keyword_) || 2135 if (!manifest->GetString(keys::kOmniboxKeyword, &omnibox_keyword_) ||
2214 omnibox_keyword_.empty()) { 2136 omnibox_keyword_.empty()) {
2215 *error = errors::kInvalidOmniboxKeyword; 2137 *error = errors::kInvalidOmniboxKeyword;
2216 return false; 2138 return false;
2217 } 2139 }
2218 } 2140 }
2219 2141
2220 if (source.HasKey(keys::kContentSecurityPolicy)) { 2142 if (manifest->HasKey(keys::kContentSecurityPolicy)) {
2221 std::string content_security_policy; 2143 std::string content_security_policy;
2222 if (!source.GetString(keys::kContentSecurityPolicy, 2144 if (!manifest->GetString(keys::kContentSecurityPolicy,
2223 &content_security_policy)) { 2145 &content_security_policy)) {
2224 *error = errors::kInvalidContentSecurityPolicy; 2146 *error = errors::kInvalidContentSecurityPolicy;
2225 return false; 2147 return false;
2226 } 2148 }
2227 // We block these characters to prevent HTTP header injection when 2149 // We block these characters to prevent HTTP header injection when
2228 // representing the content security policy as an HTTP header. 2150 // representing the content security policy as an HTTP header.
2229 const char kBadCSPCharacters[] = {'\r', '\n', '\0'}; 2151 const char kBadCSPCharacters[] = {'\r', '\n', '\0'};
2230 if (content_security_policy.find_first_of(kBadCSPCharacters, 0, 2152 if (content_security_policy.find_first_of(kBadCSPCharacters, 0,
2231 arraysize(kBadCSPCharacters)) != 2153 arraysize(kBadCSPCharacters)) !=
2232 std::string::npos) { 2154 std::string::npos) {
2233 *error = errors::kInvalidContentSecurityPolicy; 2155 *error = errors::kInvalidContentSecurityPolicy;
2234 return false; 2156 return false;
2235 } 2157 }
2236 content_security_policy_ = content_security_policy; 2158 content_security_policy_ = content_security_policy;
2237 } else if (manifest_version_ >= 2) { 2159 } else if (manifest_version_ >= 2) {
2238 // Manifest version 2 introduced a default Content-Security-Policy. 2160 // Manifest version 2 introduced a default Content-Security-Policy.
2239 // TODO(abarth): Should we continue to let extensions override the 2161 // TODO(abarth): Should we continue to let extensions override the
2240 // default Content-Security-Policy? 2162 // default Content-Security-Policy?
2241 content_security_policy_ = kDefaultContentSecurityPolicy; 2163 content_security_policy_ = kDefaultContentSecurityPolicy;
2242 } 2164 }
2243 2165
2244 // Initialize devtools page url (optional). 2166 // Initialize devtools page url (optional).
2245 if (source.HasKey(keys::kDevToolsPage)) { 2167 if (manifest->HasKey(keys::kDevToolsPage)) {
2246 std::string devtools_str; 2168 std::string devtools_str;
2247 if (!source.GetString(keys::kDevToolsPage, &devtools_str)) { 2169 if (!manifest->GetString(keys::kDevToolsPage, &devtools_str)) {
2248 *error = errors::kInvalidDevToolsPage; 2170 *error = errors::kInvalidDevToolsPage;
2249 return false; 2171 return false;
2250 } 2172 }
2251 if (!api_permissions.count(ExtensionAPIPermission::kExperimental)) { 2173 if (!api_permissions.count(ExtensionAPIPermission::kExperimental)) {
2252 *error = errors::kDevToolsExperimental; 2174 *error = errors::kDevToolsExperimental;
2253 return false; 2175 return false;
2254 } 2176 }
2255 devtools_url_ = GetResourceURL(devtools_str); 2177 devtools_url_ = GetResourceURL(devtools_str);
2256 } 2178 }
2257 2179
2258 // Initialize sidebar action (optional). 2180 // Initialize sidebar action (optional).
2259 if (source.HasKey(keys::kSidebar)) { 2181 if (manifest->HasKey(keys::kSidebar)) {
2260 DictionaryValue* sidebar_value = NULL; 2182 DictionaryValue* sidebar_value = NULL;
2261 if (!source.GetDictionary(keys::kSidebar, &sidebar_value)) { 2183 if (!manifest->GetDictionary(keys::kSidebar, &sidebar_value)) {
2262 *error = errors::kInvalidSidebar; 2184 *error = errors::kInvalidSidebar;
2263 return false; 2185 return false;
2264 } 2186 }
2265 if (!api_permissions.count(ExtensionAPIPermission::kExperimental)) { 2187 if (!api_permissions.count(ExtensionAPIPermission::kExperimental)) {
2266 *error = errors::kSidebarExperimental; 2188 *error = errors::kSidebarExperimental;
2267 return false; 2189 return false;
2268 } 2190 }
2269 sidebar_defaults_.reset(LoadExtensionSidebarDefaults(sidebar_value, error)); 2191 sidebar_defaults_.reset(LoadExtensionSidebarDefaults(sidebar_value, error));
2270 if (!sidebar_defaults_.get()) 2192 if (!sidebar_defaults_.get())
2271 return false; // Failed to parse sidebar definition. 2193 return false; // Failed to parse sidebar definition.
2272 } 2194 }
2273 2195
2274 // Initialize text-to-speech voices (optional). 2196 // Initialize text-to-speech voices (optional).
2275 if (source.HasKey(keys::kTtsEngine)) { 2197 if (manifest->HasKey(keys::kTtsEngine)) {
2276 DictionaryValue* tts_dict = NULL; 2198 DictionaryValue* tts_dict = NULL;
2277 if (!source.GetDictionary(keys::kTtsEngine, &tts_dict)) { 2199 if (!manifest->GetDictionary(keys::kTtsEngine, &tts_dict)) {
2278 *error = errors::kInvalidTts; 2200 *error = errors::kInvalidTts;
2279 return false; 2201 return false;
2280 } 2202 }
2281 2203
2282 if (tts_dict->HasKey(keys::kTtsVoices)) { 2204 if (tts_dict->HasKey(keys::kTtsVoices)) {
2283 ListValue* tts_voices = NULL; 2205 ListValue* tts_voices = NULL;
2284 if (!tts_dict->GetList(keys::kTtsVoices, &tts_voices)) { 2206 if (!tts_dict->GetList(keys::kTtsVoices, &tts_voices)) {
2285 *error = errors::kInvalidTtsVoices; 2207 *error = errors::kInvalidTtsVoices;
2286 return false; 2208 return false;
2287 } 2209 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2348 voice_data.event_types.insert(event_type); 2270 voice_data.event_types.insert(event_type);
2349 } 2271 }
2350 } 2272 }
2351 2273
2352 tts_voices_.push_back(voice_data); 2274 tts_voices_.push_back(voice_data);
2353 } 2275 }
2354 } 2276 }
2355 } 2277 }
2356 2278
2357 // Initialize web intents (optional). 2279 // Initialize web intents (optional).
2358 if (!LoadWebIntentServices(source, error)) 2280 if (!LoadWebIntentServices(manifest, error))
2359 return false; 2281 return false;
2360 2282
2361 // Initialize incognito behavior. Apps default to split mode, extensions 2283 // Initialize incognito behavior. Apps default to split mode, extensions
2362 // default to spanning. 2284 // default to spanning.
2363 incognito_split_mode_ = is_app(); 2285 incognito_split_mode_ = is_app();
2364 if (source.HasKey(keys::kIncognito)) { 2286 if (manifest->HasKey(keys::kIncognito)) {
2365 std::string value; 2287 std::string value;
2366 if (!source.GetString(keys::kIncognito, &value)) { 2288 if (!manifest->GetString(keys::kIncognito, &value)) {
2367 *error = errors::kInvalidIncognitoBehavior; 2289 *error = errors::kInvalidIncognitoBehavior;
2368 return false; 2290 return false;
2369 } 2291 }
2370 if (value == values::kIncognitoSpanning) { 2292 if (value == values::kIncognitoSpanning) {
2371 incognito_split_mode_ = false; 2293 incognito_split_mode_ = false;
2372 } else if (value == values::kIncognitoSplit) { 2294 } else if (value == values::kIncognitoSplit) {
2373 incognito_split_mode_ = true; 2295 incognito_split_mode_ = true;
2374 } else { 2296 } else {
2375 *error = errors::kInvalidIncognitoBehavior; 2297 *error = errors::kInvalidIncognitoBehavior;
2376 return false; 2298 return false;
2377 } 2299 }
2378 } 2300 }
2379 2301
2380 // Initialize offline-enabled status. Defaults to false. 2302 // Initialize offline-enabled status. Defaults to false.
2381 if (source.HasKey(keys::kOfflineEnabled)) { 2303 if (manifest->HasKey(keys::kOfflineEnabled)) {
2382 if (!source.GetBoolean(keys::kOfflineEnabled, &offline_enabled_)) { 2304 if (!manifest->GetBoolean(keys::kOfflineEnabled, &offline_enabled_)) {
2383 *error = errors::kInvalidOfflineEnabled; 2305 *error = errors::kInvalidOfflineEnabled;
2384 return false; 2306 return false;
2385 } 2307 }
2386 } 2308 }
2387 2309
2388 // Initialize requirements (optional). Not actually persisted (they're only 2310 // Initialize requirements (optional). Not actually persisted (they're only
2389 // used by the store), but still validated. 2311 // used by the store), but still validated.
2390 if (source.HasKey(keys::kRequirements)) { 2312 if (manifest->HasKey(keys::kRequirements)) {
2391 DictionaryValue* requirements_value = NULL; 2313 DictionaryValue* requirements_value = NULL;
2392 if (!source.GetDictionary(keys::kRequirements, &requirements_value)) { 2314 if (!manifest->GetDictionary(keys::kRequirements, &requirements_value)) {
2393 *error = errors::kInvalidRequirements; 2315 *error = errors::kInvalidRequirements;
2394 return false; 2316 return false;
2395 } 2317 }
2396 2318
2397 for (DictionaryValue::key_iterator it = requirements_value->begin_keys(); 2319 for (DictionaryValue::key_iterator it = requirements_value->begin_keys();
2398 it != requirements_value->end_keys(); ++it) { 2320 it != requirements_value->end_keys(); ++it) {
2399 DictionaryValue* requirement_value; 2321 DictionaryValue* requirement_value;
2400 if (!requirements_value->GetDictionaryWithoutPathExpansion( 2322 if (!requirements_value->GetDictionaryWithoutPathExpansion(
2401 *it, &requirement_value)) { 2323 *it, &requirement_value)) {
2402 *error = ExtensionErrorUtils::FormatErrorMessage( 2324 *error = ExtensionErrorUtils::FormatErrorMessage(
2403 errors::kInvalidRequirement, *it); 2325 errors::kInvalidRequirement, *it);
2404 return false; 2326 return false;
2405 } 2327 }
2406 } 2328 }
2407 } 2329 }
2408 2330
2409 if (HasMultipleUISurfaces()) { 2331 if (HasMultipleUISurfaces()) {
2410 *error = errors::kOneUISurfaceOnly; 2332 *error = errors::kOneUISurfaceOnly;
2411 return false; 2333 return false;
2412 } 2334 }
2413 2335
2414 runtime_data_.SetActivePermissions(new ExtensionPermissionSet( 2336 runtime_data_.SetActivePermissions(new ExtensionPermissionSet(
2415 this, api_permissions, host_permissions)); 2337 this, api_permissions, host_permissions));
2416 required_permission_set_ = new ExtensionPermissionSet( 2338 required_permission_set_ = new ExtensionPermissionSet(
2417 this, api_permissions, host_permissions); 2339 this, api_permissions, host_permissions);
2418 optional_permission_set_ = new ExtensionPermissionSet( 2340 optional_permission_set_ = new ExtensionPermissionSet(
2419 optional_api_permissions, optional_host_permissions, URLPatternSet()); 2341 optional_api_permissions, optional_host_permissions, URLPatternSet());
2420 2342
2421 // Although |source| is passed in as a const, it's still possible to modify
2422 // it. This is dangerous since the utility process re-uses |source| after
2423 // it calls InitFromValue, passing it up to the browser process which calls
2424 // InitFromValue again. As a result, we need to make sure that nobody
2425 // accidentally modifies it.
2426 DCHECK(source.Equals(manifest_value_.get()));
2427
2428 return true; 2343 return true;
2429 } 2344 }
2430 2345
2431 GURL Extension::GetHomepageURL() const { 2346 GURL Extension::GetHomepageURL() const {
2432 if (homepage_url_.is_valid()) 2347 if (homepage_url_.is_valid())
2433 return homepage_url_; 2348 return homepage_url_;
2434 2349
2435 if (!UpdatesFromGallery()) 2350 if (!UpdatesFromGallery())
2436 return GURL(); 2351 return GURL();
2437 2352
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
2573 2488
2574 GURL Extension::GetIconURL(int size, 2489 GURL Extension::GetIconURL(int size,
2575 ExtensionIconSet::MatchType match_type) const { 2490 ExtensionIconSet::MatchType match_type) const {
2576 std::string path = icons().Get(size, match_type); 2491 std::string path = icons().Get(size, match_type);
2577 if (path.empty()) 2492 if (path.empty())
2578 return GURL(); 2493 return GURL();
2579 else 2494 else
2580 return GetResourceURL(path); 2495 return GetResourceURL(path);
2581 } 2496 }
2582 2497
2583 bool Extension::ParsePermissions(const DictionaryValue* source, 2498 bool Extension::ParsePermissions(const extensions::Manifest* source,
2584 const char* key, 2499 const char* key,
2585 int flags, 2500 int flags,
2586 std::string* error, 2501 std::string* error,
2587 ExtensionAPIPermissionSet* api_permissions, 2502 ExtensionAPIPermissionSet* api_permissions,
2588 URLPatternSet* host_permissions) { 2503 URLPatternSet* host_permissions) {
2589 if (source->HasKey(key)) { 2504 if (source->HasKey(key)) {
2590 // When strict error checks are enabled, make URL pattern parsing strict. 2505 // When strict error checks are enabled, make URL pattern parsing strict.
2591 URLPattern::ParseOption parse_strictness = 2506 URLPattern::ParseOption parse_strictness =
2592 (flags & STRICT_ERROR_CHECKS ? URLPattern::ERROR_ON_PORTS 2507 (flags & STRICT_ERROR_CHECKS ? URLPattern::ERROR_ON_PORTS
2593 : URLPattern::IGNORE_PORTS); 2508 : URLPattern::IGNORE_PORTS);
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after
3052 already_disabled(false), 2967 already_disabled(false),
3053 extension(extension) {} 2968 extension(extension) {}
3054 2969
3055 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( 2970 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo(
3056 const Extension* extension, 2971 const Extension* extension,
3057 const ExtensionPermissionSet* permissions, 2972 const ExtensionPermissionSet* permissions,
3058 Reason reason) 2973 Reason reason)
3059 : reason(reason), 2974 : reason(reason),
3060 extension(extension), 2975 extension(extension),
3061 permissions(permissions) {} 2976 permissions(permissions) {}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698