| Index: extensions/common/permissions/permissions_data.cc
|
| diff --git a/extensions/common/permissions/permissions_data.cc b/extensions/common/permissions/permissions_data.cc
|
| index 4025d23c0ff0096e075b60521ae95bb0b0e5675c..fb9cecb1cbca59ccb2fa73487ad004ce8018f44d 100644
|
| --- a/extensions/common/permissions/permissions_data.cc
|
| +++ b/extensions/common/permissions/permissions_data.cc
|
| @@ -8,6 +8,7 @@
|
| #include <utility>
|
|
|
| #include "base/command_line.h"
|
| +#include "base/lazy_instance.h"
|
| #include "base/macros.h"
|
| #include "content/public/common/url_constants.h"
|
| #include "extensions/common/constants.h"
|
| @@ -30,6 +31,17 @@ namespace {
|
|
|
| PermissionsData::PolicyDelegate* g_policy_delegate = nullptr;
|
|
|
| +struct DefaultRuntimePolicy {
|
| + URLPatternSet blocked_hosts;
|
| + URLPatternSet allowed_hosts;
|
| +};
|
| +
|
| +// URLs an extension can't interact with. An extension can override these
|
| +// settings by declaring its own list of blocked and allowed hosts using
|
| +// policy_blocked_hosts and policy_allowed_hosts.
|
| +base::LazyInstance<DefaultRuntimePolicy>::Leaky default_runtime_policy =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| class AutoLockOnValidThread {
|
| public:
|
| AutoLockOnValidThread(base::Lock& lock, base::ThreadChecker* thread_checker)
|
| @@ -127,6 +139,45 @@ bool PermissionsData::IsRestrictedUrl(const GURL& document_url,
|
| return false;
|
| }
|
|
|
| +bool PermissionsData::UsesDefaultPolicyHostRestrictions() const {
|
| + DCHECK(!thread_checker_ || thread_checker_->CalledOnValidThread());
|
| + return uses_default_policy_host_restrictions;
|
| +}
|
| +
|
| +const URLPatternSet& PermissionsData::default_policy_blocked_hosts() {
|
| + return default_runtime_policy.Get().blocked_hosts;
|
| +}
|
| +
|
| +const URLPatternSet& PermissionsData::default_policy_allowed_hosts() {
|
| + return default_runtime_policy.Get().allowed_hosts;
|
| +}
|
| +
|
| +const URLPatternSet PermissionsData::policy_blocked_hosts() const {
|
| + base::AutoLock auto_lock(runtime_lock_);
|
| + return PolicyBlockedHostsUnsafe();
|
| +}
|
| +
|
| +const URLPatternSet& PermissionsData::PolicyBlockedHostsUnsafe() const {
|
| + DCHECK(!thread_checker_ || thread_checker_->CalledOnValidThread());
|
| + if (uses_default_policy_host_restrictions)
|
| + return default_policy_blocked_hosts();
|
| + runtime_lock_.AssertAcquired();
|
| + return policy_blocked_hosts_unsafe_;
|
| +}
|
| +
|
| +const URLPatternSet PermissionsData::policy_allowed_hosts() const {
|
| + base::AutoLock auto_lock(runtime_lock_);
|
| + return PolicyAllowedHostsUnsafe();
|
| +}
|
| +
|
| +const URLPatternSet& PermissionsData::PolicyAllowedHostsUnsafe() const {
|
| + DCHECK(!thread_checker_ || thread_checker_->CalledOnValidThread());
|
| + if (uses_default_policy_host_restrictions)
|
| + return default_policy_allowed_hosts();
|
| + runtime_lock_.AssertAcquired();
|
| + return policy_allowed_hosts_unsafe_;
|
| +}
|
| +
|
| void PermissionsData::BindToCurrentThread() const {
|
| DCHECK(!thread_checker_);
|
| thread_checker_.reset(new base::ThreadChecker());
|
| @@ -140,6 +191,28 @@ void PermissionsData::SetPermissions(
|
| withheld_permissions_unsafe_ = std::move(withheld);
|
| }
|
|
|
| +void PermissionsData::SetPolicyHostRestrictions(
|
| + const URLPatternSet& runtime_blocked_hosts,
|
| + const URLPatternSet& runtime_allowed_hosts) const {
|
| + AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get());
|
| + policy_blocked_hosts_unsafe_ = runtime_blocked_hosts;
|
| + policy_allowed_hosts_unsafe_ = runtime_allowed_hosts;
|
| + uses_default_policy_host_restrictions = false;
|
| +}
|
| +
|
| +void PermissionsData::SetUsesDefaultHostRestrictions() const {
|
| + AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get());
|
| + uses_default_policy_host_restrictions = true;
|
| +}
|
| +
|
| +// static
|
| +void PermissionsData::SetDefaultPolicyHostRestrictions(
|
| + const URLPatternSet& default_runtime_blocked_hosts,
|
| + const URLPatternSet& default_runtime_allowed_hosts) {
|
| + default_runtime_policy.Get().blocked_hosts = default_runtime_blocked_hosts;
|
| + default_runtime_policy.Get().allowed_hosts = default_runtime_allowed_hosts;
|
| +}
|
| +
|
| void PermissionsData::SetActivePermissions(
|
| std::unique_ptr<const PermissionSet> active) const {
|
| AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get());
|
| @@ -208,7 +281,8 @@ URLPatternSet PermissionsData::GetEffectiveHostPermissions() const {
|
|
|
| bool PermissionsData::HasHostPermission(const GURL& url) const {
|
| base::AutoLock auto_lock(runtime_lock_);
|
| - return active_permissions_unsafe_->HasExplicitAccessToOrigin(url);
|
| + return active_permissions_unsafe_->HasExplicitAccessToOrigin(url) &&
|
| + !IsRuntimeBlockedHost(url);
|
| }
|
|
|
| bool PermissionsData::HasEffectiveAccessToAllHosts() const {
|
| @@ -327,6 +401,12 @@ bool PermissionsData::HasTabSpecificPermissionToExecuteScript(
|
| return false;
|
| }
|
|
|
| +bool PermissionsData::IsRuntimeBlockedHost(const GURL& url) const {
|
| + runtime_lock_.AssertAcquired();
|
| + return PolicyBlockedHostsUnsafe().MatchesURL(url) &&
|
| + !PolicyAllowedHostsUnsafe().MatchesURL(url);
|
| +}
|
| +
|
| PermissionsData::AccessType PermissionsData::CanRunOnPage(
|
| const Extension* extension,
|
| const GURL& document_url,
|
| @@ -335,9 +415,14 @@ PermissionsData::AccessType PermissionsData::CanRunOnPage(
|
| const URLPatternSet& withheld_url_patterns,
|
| std::string* error) const {
|
| runtime_lock_.AssertAcquired();
|
| - if (g_policy_delegate &&
|
| - !g_policy_delegate->CanExecuteScriptOnPage(extension, document_url,
|
| - tab_id, error)) {
|
| + if (g_policy_delegate && !g_policy_delegate->CanExecuteScriptOnPage(
|
| + extension, document_url, tab_id, error))
|
| + return ACCESS_DENIED;
|
| +
|
| + if (extension->location() != Manifest::COMPONENT &&
|
| + extension->permissions_data()->IsRuntimeBlockedHost(document_url)) {
|
| + if (error)
|
| + *error = extension_misc::kPolicyBlockedScripting;
|
| return ACCESS_DENIED;
|
| }
|
|
|
|
|