| Index: chrome/browser/extensions/permissions_updater.cc
|
| diff --git a/chrome/browser/extensions/permissions_updater.cc b/chrome/browser/extensions/permissions_updater.cc
|
| index 9d4a7b6f9dcabf2084940fc0ab69304650d20910..d95f812f68813406144a27be1f73a34871335c27 100644
|
| --- a/chrome/browser/extensions/permissions_updater.cc
|
| +++ b/chrome/browser/extensions/permissions_updater.cc
|
| @@ -9,6 +9,7 @@
|
| #include "base/values.h"
|
| #include "chrome/browser/chrome_notification_types.h"
|
| #include "chrome/browser/extensions/api/permissions/permissions_api_helpers.h"
|
| +#include "chrome/browser/extensions/extension_util.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| #include "chrome/common/extensions/api/permissions.h"
|
| #include "content/public/browser/notification_observer.h"
|
| @@ -19,9 +20,12 @@
|
| #include "extensions/browser/extension_prefs.h"
|
| #include "extensions/common/extension.h"
|
| #include "extensions/common/extension_messages.h"
|
| +#include "extensions/common/feature_switch.h"
|
| #include "extensions/common/manifest_handlers/permissions_parser.h"
|
| #include "extensions/common/permissions/permission_set.h"
|
| #include "extensions/common/permissions/permissions_data.h"
|
| +#include "extensions/common/url_pattern.h"
|
| +#include "extensions/common/url_pattern_set.h"
|
|
|
| using content::RenderProcessHost;
|
| using extensions::permissions_api_helpers::PackPermissionSet;
|
| @@ -30,6 +34,61 @@ namespace extensions {
|
|
|
| namespace permissions = api::permissions;
|
|
|
| +namespace {
|
| +
|
| +// Returns a PermissionSet that has the active permissions of the extension,
|
| +// bounded to its current manifest.
|
| +scoped_refptr<const PermissionSet> GetBoundedActivePermissions(
|
| + const Extension* extension, ExtensionPrefs* extension_prefs) {
|
| + // If the extension has used the optional permissions API, it will have a
|
| + // custom set of active permissions defined in the extension prefs. Here,
|
| + // we update the extension's active permissions based on the prefs.
|
| + scoped_refptr<const PermissionSet> active_permissions =
|
| + extension_prefs->GetActivePermissions(extension->id());
|
| + if (!active_permissions)
|
| + return extension->permissions_data()->active_permissions();
|
| +
|
| + scoped_refptr<const PermissionSet> required_permissions =
|
| + PermissionsParser::GetRequiredPermissions(extension);
|
| +
|
| + // We restrict the active permissions to be within the bounds defined in the
|
| + // extension's manifest.
|
| + // a) active permissions must be a subset of optional + default permissions
|
| + // b) active permissions must contains all default permissions
|
| + scoped_refptr<PermissionSet> total_permissions = PermissionSet::CreateUnion(
|
| + required_permissions,
|
| + PermissionsParser::GetOptionalPermissions(extension));
|
| +
|
| + // Make sure the active permissions contain no more than optional + default.
|
| + scoped_refptr<PermissionSet> adjusted_active =
|
| + PermissionSet::CreateIntersection(total_permissions, active_permissions);
|
| +
|
| + // Make sure the active permissions contain the default permissions.
|
| + adjusted_active =
|
| + PermissionSet::CreateUnion(required_permissions, adjusted_active);
|
| +
|
| + return adjusted_active;
|
| +}
|
| +
|
| +// Divvy up the |url patterns| between those we grant and those we do not. If
|
| +// |withhold_permissions| is false (because the requisite feature is not
|
| +// enabled), no permissions are withheld.
|
| +void SegregateUrlPermissions(const URLPatternSet& url_patterns,
|
| + bool withhold_permissions,
|
| + URLPatternSet* granted,
|
| + URLPatternSet* withheld) {
|
| + for (URLPatternSet::const_iterator iter = url_patterns.begin();
|
| + iter != url_patterns.end();
|
| + ++iter) {
|
| + if (withhold_permissions && iter->ImpliesAllHosts())
|
| + withheld->AddPattern(*iter);
|
| + else
|
| + granted->AddPattern(*iter);
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| PermissionsUpdater::PermissionsUpdater(content::BrowserContext* browser_context)
|
| : browser_context_(browser_context) {
|
| }
|
| @@ -45,7 +104,7 @@ void PermissionsUpdater::AddPermissions(
|
| scoped_refptr<PermissionSet> added(
|
| PermissionSet::CreateDifference(total.get(), existing.get()));
|
|
|
| - SetActivePermissions(extension, total.get());
|
| + SetPermissions(extension, total, NULL);
|
|
|
| // Update the granted permissions so we don't auto-disable the extension.
|
| GrantActivePermissions(extension);
|
| @@ -65,7 +124,7 @@ void PermissionsUpdater::RemovePermissions(
|
| // We update the active permissions, and not the granted permissions, because
|
| // the extension, not the user, removed the permissions. This allows the
|
| // extension to add them again without prompting the user.
|
| - SetActivePermissions(extension, total.get());
|
| + SetPermissions(extension, total, NULL);
|
|
|
| NotifyPermissionsUpdated(REMOVED, extension, removed.get());
|
| }
|
| @@ -84,42 +143,122 @@ void PermissionsUpdater::GrantActivePermissions(const Extension* extension) {
|
| extension->permissions_data()->active_permissions().get());
|
| }
|
|
|
| -void PermissionsUpdater::InitializeActivePermissions(
|
| - const Extension* extension) {
|
| - // If the extension has used the optional permissions API, it will have a
|
| - // custom set of active permissions defined in the extension prefs. Here,
|
| - // we update the extension's active permissions based on the prefs.
|
| - scoped_refptr<PermissionSet> active_permissions =
|
| - ExtensionPrefs::Get(browser_context_)->GetActivePermissions(
|
| - extension->id());
|
| - if (!active_permissions)
|
| - return;
|
| -
|
| - // We restrict the active permissions to be within the bounds defined in the
|
| - // extension's manifest.
|
| - // a) active permissions must be a subset of optional + default permissions
|
| - // b) active permissions must contains all default permissions
|
| - scoped_refptr<PermissionSet> total_permissions = PermissionSet::CreateUnion(
|
| - PermissionsParser::GetRequiredPermissions(extension),
|
| - PermissionsParser::GetOptionalPermissions(extension));
|
| -
|
| - // Make sure the active permissions contain no more than optional + default.
|
| - scoped_refptr<PermissionSet> adjusted_active =
|
| - PermissionSet::CreateIntersection(total_permissions, active_permissions);
|
| +void PermissionsUpdater::InitializePermissions(const Extension* extension) {
|
| + scoped_refptr<const PermissionSet> bounded_active =
|
| + GetBoundedActivePermissions(extension,
|
| + ExtensionPrefs::Get(browser_context_));
|
| +
|
| + // We withhold permissions iff the switch to do so is enabled, the extension
|
| + // shows up in chrome:extensions (so the user can grant withheld permissions),
|
| + // the extension is not part of chrome or corporate policy, and also not on
|
| + // the scripting whitelist. Additionally, we don't withhold if the extension
|
| + // has the preference to allow scripting on all urls.
|
| + bool should_withhold_permissions =
|
| + FeatureSwitch::scripts_require_action()->IsEnabled() &&
|
| + extension->ShouldDisplayInExtensionSettings() &&
|
| + !Manifest::IsPolicyLocation(extension->location()) &&
|
| + !Manifest::IsComponentLocation(extension->location()) &&
|
| + !PermissionsData::CanExecuteScriptEverywhere(extension) &&
|
| + !util::AllowedScriptingOnAllUrls(extension->id(), browser_context_);
|
| +
|
| + URLPatternSet granted_explicit_hosts;
|
| + URLPatternSet withheld_explicit_hosts;
|
| + SegregateUrlPermissions(bounded_active->explicit_hosts(),
|
| + should_withhold_permissions,
|
| + &granted_explicit_hosts,
|
| + &withheld_explicit_hosts);
|
| +
|
| + URLPatternSet granted_scriptable_hosts;
|
| + URLPatternSet withheld_scriptable_hosts;
|
| + SegregateUrlPermissions(bounded_active->scriptable_hosts(),
|
| + should_withhold_permissions,
|
| + &granted_scriptable_hosts,
|
| + &withheld_scriptable_hosts);
|
| +
|
| + bounded_active = new PermissionSet(bounded_active->apis(),
|
| + bounded_active->manifest_permissions(),
|
| + granted_explicit_hosts,
|
| + granted_scriptable_hosts);
|
| +
|
| + scoped_refptr<const PermissionSet> withheld =
|
| + new PermissionSet(APIPermissionSet(),
|
| + ManifestPermissionSet(),
|
| + withheld_explicit_hosts,
|
| + withheld_scriptable_hosts);
|
| + SetPermissions(extension, bounded_active, withheld);
|
| +}
|
|
|
| - // Make sure the active permissions contain the default permissions.
|
| - adjusted_active = PermissionSet::CreateUnion(
|
| - PermissionsParser::GetRequiredPermissions(extension),
|
| - adjusted_active);
|
| +void PermissionsUpdater::WithholdImpliedAllHosts(const Extension* extension) {
|
| + scoped_refptr<const PermissionSet> active =
|
| + extension->permissions_data()->active_permissions();
|
| + scoped_refptr<const PermissionSet> withheld =
|
| + extension->permissions_data()->withheld_permissions();
|
| +
|
| + URLPatternSet withheld_scriptable = withheld->scriptable_hosts();
|
| + URLPatternSet active_scriptable;
|
| + SegregateUrlPermissions(active->scriptable_hosts(),
|
| + true, // withhold permissions
|
| + &active_scriptable,
|
| + &withheld_scriptable);
|
| +
|
| + URLPatternSet withheld_explicit = withheld->explicit_hosts();
|
| + URLPatternSet active_explicit;
|
| + SegregateUrlPermissions(active->explicit_hosts(),
|
| + true, // withhold permissions
|
| + &active_explicit,
|
| + &withheld_explicit);
|
| +
|
| + SetPermissions(extension,
|
| + new PermissionSet(active->apis(),
|
| + active->manifest_permissions(),
|
| + active_explicit,
|
| + active_scriptable),
|
| + new PermissionSet(withheld->apis(),
|
| + withheld->manifest_permissions(),
|
| + withheld_explicit,
|
| + withheld_scriptable));
|
| + // TODO(rdevlin.cronin) We should notify the observers/renderer.
|
| +}
|
|
|
| - SetActivePermissions(extension, adjusted_active);
|
| +void PermissionsUpdater::GrantWithheldImpliedAllHosts(
|
| + const Extension* extension) {
|
| + scoped_refptr<const PermissionSet> active =
|
| + extension->permissions_data()->active_permissions();
|
| + scoped_refptr<const PermissionSet> withheld =
|
| + extension->permissions_data()->withheld_permissions();
|
| +
|
| + // Move the all-hosts permission from withheld to active.
|
| + // We can cheat a bit here since we know that the only host permission we
|
| + // withhold is allhosts (or something similar enough to it), so we can just
|
| + // grant all withheld host permissions.
|
| + URLPatternSet explicit_hosts;
|
| + URLPatternSet::CreateUnion(
|
| + active->explicit_hosts(), withheld->explicit_hosts(), &explicit_hosts);
|
| + URLPatternSet scriptable_hosts;
|
| + URLPatternSet::CreateUnion(active->scriptable_hosts(),
|
| + withheld->scriptable_hosts(),
|
| + &scriptable_hosts);
|
| +
|
| + // Since we only withhold host permissions (so far), we know that withheld
|
| + // permissions will be empty.
|
| + SetPermissions(extension,
|
| + new PermissionSet(active->apis(),
|
| + active->manifest_permissions(),
|
| + explicit_hosts,
|
| + scriptable_hosts),
|
| + new PermissionSet());
|
| + // TODO(rdevlin.cronin) We should notify the observers/renderer.
|
| }
|
|
|
| -void PermissionsUpdater::SetActivePermissions(
|
| - const Extension* extension, const PermissionSet* permissions) {
|
| +void PermissionsUpdater::SetPermissions(
|
| + const Extension* extension,
|
| + const scoped_refptr<const PermissionSet>& active,
|
| + scoped_refptr<const PermissionSet> withheld) {
|
| + withheld = withheld.get() ? withheld
|
| + : extension->permissions_data()->withheld_permissions();
|
| + extension->permissions_data()->SetPermissions(active, withheld);
|
| ExtensionPrefs::Get(browser_context_)->SetActivePermissions(
|
| - extension->id(), permissions);
|
| - extension->permissions_data()->SetActivePermissions(permissions);
|
| + extension->id(), active.get());
|
| }
|
|
|
| void PermissionsUpdater::DispatchEvent(
|
| @@ -168,12 +307,11 @@ void PermissionsUpdater::NotifyPermissionsUpdated(
|
| content::Details<UpdatedExtensionPermissionsInfo>(&info));
|
|
|
| ExtensionMsg_UpdatePermissions_Params params;
|
| - params.reason_id = static_cast<int>(reason);
|
| params.extension_id = extension->id();
|
| - params.apis = changed->apis();
|
| - params.manifest_permissions = changed->manifest_permissions();
|
| - params.explicit_hosts = changed->explicit_hosts();
|
| - params.scriptable_hosts = changed->scriptable_hosts();
|
| + params.active_permissions = ExtensionMsg_PermissionSetStruct(
|
| + extension->permissions_data()->active_permissions());
|
| + params.withheld_permissions = ExtensionMsg_PermissionSetStruct(
|
| + extension->permissions_data()->withheld_permissions());
|
|
|
| // Send the new permissions to the renderers.
|
| for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
|
|
|