Index: chrome/common/extensions/extension.cc |
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc |
index 8d80814940e0bca108c9f3c8a3aa2fbfaabe0b54..0ad83a1fa6e2fb0ac4617feb046f8f71ce968b6e 100644 |
--- a/chrome/common/extensions/extension.cc |
+++ b/chrome/common/extensions/extension.cc |
@@ -1129,11 +1129,6 @@ bool Extension::LoadLaunchContainer(const DictionaryValue* manifest, |
bool Extension::LoadAppIsolation(const DictionaryValue* manifest, |
std::string* error) { |
- // Only parse app isolation features if this switch is present. |
- if (!CommandLine::ForCurrentProcess()->HasSwitch( |
- switches::kEnableExperimentalExtensionApis)) |
- return true; |
- |
Value* temp = NULL; |
if (!manifest->Get(keys::kIsolation, &temp)) |
return true; |
@@ -1496,6 +1491,30 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, |
base::i18n::AdjustStringForLocaleDirection(&localized_name); |
name_ = UTF16ToUTF8(localized_name); |
+ // Initialize the permissions (optional). |
+ ExtensionAPIPermissionSet api_permissions; |
+ URLPatternSet host_permissions; |
+ if (!ParsePermissions(&source, |
+ keys::kPermissions, |
+ flags, |
+ error, |
+ &api_permissions, |
+ &host_permissions)) { |
+ return false; |
+ } |
+ |
+ // Initialize the optional permissions (optional). |
+ ExtensionAPIPermissionSet optional_api_permissions; |
+ URLPatternSet optional_host_permissions; |
+ if (!ParsePermissions(&source, |
+ keys::kOptionalPermissions, |
+ flags, |
+ error, |
+ &optional_api_permissions, |
+ &optional_host_permissions)) { |
+ return false; |
+ } |
+ |
// Initialize description (if present). |
if (source.HasKey(keys::kDescription)) { |
if (!source.GetString(keys::kDescription, |
@@ -1783,11 +1802,10 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, |
} |
} |
- // Initialize toolstrips. This is deprecated for public use. |
- // NOTE(erikkay) Although deprecated, we intend to preserve this parsing |
- // code indefinitely. Please contact me or Joi for details as to why. |
- if (CommandLine::ForCurrentProcess()->HasSwitch( |
- switches::kEnableExperimentalExtensionApis) && |
+ // Initialize toolstrips. |
+ // TODO(aa): Remove this and all the related tests, docs, etc. |
+ // See: crbug.com/100488. |
+ if (api_permissions.count(ExtensionAPIPermission::kExperimental) && |
source.HasKey(keys::kToolstrips)) { |
ListValue* list_value = NULL; |
if (!source.GetList(keys::kToolstrips, &list_value)) { |
@@ -1923,9 +1941,12 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, |
parse_strictness, error) || |
!EnsureNotHybridApp(manifest_value_.get(), error) || |
!LoadLaunchURL(manifest_value_.get(), error) || |
- !LoadLaunchContainer(manifest_value_.get(), error) || |
- !LoadAppIsolation(manifest_value_.get(), error)) { |
+ !LoadLaunchContainer(manifest_value_.get(), error)) |
return false; |
+ |
+ if (api_permissions.count(ExtensionAPIPermission::kExperimental)) { |
+ if (!LoadAppIsolation(manifest_value_.get(), error)) |
+ return false; |
} |
// Initialize options page url (optional). |
@@ -1960,30 +1981,6 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, |
} |
} |
- // Initialize the permissions (optional). |
- ExtensionAPIPermissionSet api_permissions; |
- URLPatternSet host_permissions; |
- if (!ParsePermissions(&source, |
- keys::kPermissions, |
- flags, |
- error, |
- &api_permissions, |
- &host_permissions)) { |
- return false; |
- } |
- |
- // Initialize the optional permissions (optional). |
- ExtensionAPIPermissionSet optional_api_permissions; |
- URLPatternSet optional_host_permissions; |
- if (!ParsePermissions(&source, |
- keys::kOptionalPermissions, |
- flags, |
- error, |
- &optional_api_permissions, |
- &optional_host_permissions)) { |
- return false; |
- } |
- |
// Initialize background url (optional). |
if (source.HasKey(keys::kBackground)) { |
std::string background_str; |
@@ -2070,8 +2067,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, |
} |
} |
- if (CommandLine::ForCurrentProcess()->HasSwitch( |
- switches::kEnableExperimentalExtensionApis) && |
+ if (api_permissions.count(ExtensionAPIPermission::kExperimental) && |
source.HasKey(keys::kInputComponents)) { |
ListValue* list_value = NULL; |
if (!source.GetList(keys::kInputComponents, &list_value)) { |
@@ -2598,41 +2594,16 @@ bool Extension::ParsePermissions(const DictionaryValue* source, |
ExtensionAPIPermission* permission = |
ExtensionPermissionsInfo::GetInstance()->GetByName(permission_str); |
- // Only COMPONENT extensions can use private APIs. |
- // TODO(asargent) - We want a more general purpose mechanism for this, |
- // and better error messages. (http://crbug.com/54013) |
- if (!IsComponentOnlyPermission(permission) |
-#ifndef NDEBUG |
- && !CommandLine::ForCurrentProcess()->HasSwitch( |
- switches::kExposePrivateExtensionApi) |
-#endif |
- ) { |
- continue; |
- } |
- |
- if (web_extent().is_empty() || location() == Extension::COMPONENT) { |
- // Check if it's a module permission. If so, enable that permission. |
- if (permission != NULL) { |
- // Only allow the experimental API permission if the command line |
- // flag is present, or if the extension is a component of Chrome. |
- if (IsDisallowedExperimentalPermission(permission->id()) && |
- location() != Extension::COMPONENT) { |
- *error = errors::kExperimentalFlagRequired; |
- return false; |
- } |
- api_permissions->insert(permission->id()); |
- continue; |
- } |
- } else { |
- // Hosted apps only get access to a subset of the valid permissions. |
- if (permission != NULL && permission->is_hosted_app()) { |
- if (IsDisallowedExperimentalPermission(permission->id())) { |
- *error = errors::kExperimentalFlagRequired; |
- return false; |
- } |
+ if (permission != NULL) { |
+ if (CanSpecifyAPIPermission(permission, error)) |
api_permissions->insert(permission->id()); |
- continue; |
- } |
+ |
+ // Sometimes when you can't specify an API permission we ignore it |
+ // silently. This seems like a bug. Specifically, crbug.com/100489. |
+ if (!error->empty()) |
+ return false; |
+ |
+ continue; |
} |
// Check if it's a host pattern permission. |
@@ -2760,17 +2731,6 @@ scoped_refptr<const ExtensionPermissionSet> |
return runtime_data_.GetActivePermissions(); |
} |
-bool Extension::IsComponentOnlyPermission( |
- const ExtensionAPIPermission* api) const { |
- if (location() == Extension::COMPONENT) |
- return true; |
- |
- if (api == NULL) |
- return true; |
- |
- return !api->is_component_only(); |
-} |
- |
bool Extension::HasMultipleUISurfaces() const { |
int num_surfaces = 0; |
@@ -2842,11 +2802,73 @@ bool Extension::ImplicitlyDelaysNetworkStartup() const { |
HasAPIPermission(ExtensionAPIPermission::kWebRequest); |
} |
-bool Extension::IsDisallowedExperimentalPermission( |
- ExtensionAPIPermission::ID permission) const { |
- return permission == ExtensionAPIPermission::kExperimental && |
- !CommandLine::ForCurrentProcess()->HasSwitch( |
- switches::kEnableExperimentalExtensionApis); |
+bool Extension::CanSpecifyAPIPermission( |
+ const ExtensionAPIPermission* permission, |
+ std::string* error) const { |
+ if (permission->is_component_only()) { |
+ if (!CanSpecifyComponentOnlyPermission()) |
+ return false; |
+ } |
+ |
+ if (permission->id() == ExtensionAPIPermission::kExperimental) { |
+ if (!CanSpecifyExperimentalPermission()) { |
+ *error = errors::kExperimentalFlagRequired; |
+ return false; |
+ } |
+ } |
+ |
+ if (is_hosted_app()) { |
+ if (!CanSpecifyPermissionForHostedApp(permission)) |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
+bool Extension::CanSpecifyComponentOnlyPermission() const { |
+ // Only COMPONENT extensions can use private APIs. |
+ // TODO(asargent) - We want a more general purpose mechanism for this, |
+ // and better error messages. (http://crbug.com/54013) |
+ if (location_ == Extension::COMPONENT) |
+ return true; |
+ |
+#ifndef NDEBUG |
+ if (CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kExposePrivateExtensionApi)) { |
+ return true; |
+ } |
+#endif |
+ |
+ return false; |
+} |
+ |
+bool Extension::CanSpecifyExperimentalPermission() const { |
+ if (location_ == Extension::COMPONENT) |
+ return true; |
+ |
+ if (CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kEnableExperimentalExtensionApis)) { |
+ return true; |
+ } |
+ |
+ // We rely on the webstore to check access to experimental. This way we can |
+ // whitelist extensions to have access to experimental in just the store, and |
+ // not have to push a new version of the client. |
+ if (from_webstore()) |
+ return true; |
+ |
+ return false; |
+} |
+ |
+bool Extension::CanSpecifyPermissionForHostedApp( |
+ const ExtensionAPIPermission* permission) const { |
+ if (location_ == Extension::COMPONENT) |
+ return true; |
+ |
+ if (permission->is_hosted_app()) |
+ return true; |
+ |
+ return false; |
} |
bool Extension::CanExecuteScriptEverywhere() const { |