Index: extensions/common/permissions/permissions_data.cc |
diff --git a/extensions/common/permissions/permissions_data.cc b/extensions/common/permissions/permissions_data.cc |
index 1b160cab003c68e23a2895efa2b72a5bd5e01b12..724e1c276a6b91aca7438a26198fc5eb6650d064 100644 |
--- a/extensions/common/permissions/permissions_data.cc |
+++ b/extensions/common/permissions/permissions_data.cc |
@@ -9,6 +9,7 @@ |
#include "extensions/common/constants.h" |
#include "extensions/common/error_utils.h" |
#include "extensions/common/extensions_client.h" |
+#include "extensions/common/feature_switch.h" |
#include "extensions/common/manifest.h" |
#include "extensions/common/manifest_constants.h" |
#include "extensions/common/manifest_handlers/permissions_parser.h" |
@@ -31,18 +32,29 @@ bool ShouldSkipPermissionWarnings(const std::string& extension_id) { |
return extension_id == std::string("nckgahadagoaajjgafhacjanaoiihapd"); |
} |
+// 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 |
PermissionsData::PermissionsData(const Extension* extension) |
: extension_id_(extension->id()), manifest_type_(extension->GetType()) { |
- base::AutoLock auto_lock(runtime_lock_); |
- scoped_refptr<const PermissionSet> required_permissions = |
- PermissionsParser::GetRequiredPermissions(extension); |
- active_permissions_unsafe_ = |
- new PermissionSet(required_permissions->apis(), |
- required_permissions->manifest_permissions(), |
- required_permissions->explicit_hosts(), |
- required_permissions->scriptable_hosts()); |
+ InitializePermissions(PermissionsParser::GetRequiredPermissions(extension), |
+ extension); |
} |
PermissionsData::~PermissionsData() { |
@@ -113,10 +125,54 @@ bool PermissionsData::IsRestrictedUrl(const GURL& document_url, |
return false; |
} |
-void PermissionsData::SetActivePermissions( |
- const PermissionSet* permissions) const { |
+void PermissionsData::InitializePermissions(const PermissionSet* permissions, |
not at google - send to devlin
2014/06/27 23:24:34
you don't actually use |permissions| anywhere.
Devlin
2014/06/30 17:06:10
Whoops! Done.
|
+ const Extension* extension) const { |
base::AutoLock auto_lock(runtime_lock_); |
- active_permissions_unsafe_ = permissions; |
+ scoped_refptr<const PermissionSet> required_permissions = |
+ PermissionsParser::GetRequiredPermissions(extension); |
+ |
+ // 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. |
+ bool withhold_permissions = |
+ FeatureSwitch::scripts_require_action()->IsEnabled() && |
+ extension->ShouldDisplayInExtensionSettings() && |
+ !Manifest::IsPolicyLocation(extension->location()) && |
+ !Manifest::IsComponentLocation(extension->location()) && |
+ !CanExecuteScriptEverywhere(extension); |
+ |
+ URLPatternSet granted_explicit_hosts; |
+ URLPatternSet withheld_explicit_hosts; |
+ SegregateUrlPermissions(required_permissions->explicit_hosts(), |
+ withhold_permissions, |
+ &granted_explicit_hosts, |
+ &withheld_explicit_hosts); |
+ |
+ URLPatternSet granted_scriptable_hosts; |
+ URLPatternSet withheld_scriptable_hosts; |
+ SegregateUrlPermissions(required_permissions->scriptable_hosts(), |
+ withhold_permissions, |
+ &granted_scriptable_hosts, |
+ &withheld_scriptable_hosts); |
+ |
+ active_permissions_unsafe_ = |
+ new PermissionSet(required_permissions->apis(), |
+ required_permissions->manifest_permissions(), |
+ granted_explicit_hosts, |
+ granted_scriptable_hosts); |
+ |
+ withheld_permissions_unsafe_ = new PermissionSet(APIPermissionSet(), |
+ ManifestPermissionSet(), |
+ withheld_explicit_hosts, |
+ withheld_scriptable_hosts); |
+} |
+ |
+void PermissionsData::SetPermissions(const PermissionSet* active, |
+ const PermissionSet* withheld) const { |
+ base::AutoLock auto_lock(runtime_lock_); |
+ active_permissions_unsafe_ = active; |
+ withheld_permissions_unsafe_ = withheld; |
} |
void PermissionsData::UpdateTabSpecificPermissions( |
@@ -204,18 +260,103 @@ PermissionsData::GetPermissionMessageDetailsStrings() const { |
active_permissions(), manifest_type_); |
} |
+bool PermissionsData::HasWithheldAllHosts() const { |
+ // Since we currently only withhold all_hosts, it's sufficient to check |
+ // that either set is not empty. |
+ return !withheld_permissions()->explicit_hosts().is_empty() || |
+ !withheld_permissions()->scriptable_hosts().is_empty(); |
+} |
+ |
+void PermissionsData::WithholdAllHosts() const { |
+ base::AutoLock auto_lock(runtime_lock_); |
+ |
+ URLPatternSet withheld_scriptable = |
+ withheld_permissions_unsafe_->scriptable_hosts(); |
+ URLPatternSet active_scriptable; |
+ SegregateUrlPermissions(active_permissions_unsafe_->scriptable_hosts(), |
+ true, // withhold permissions |
+ &active_scriptable, |
+ &withheld_scriptable); |
+ |
+ URLPatternSet withheld_explicit = |
+ withheld_permissions_unsafe_->explicit_hosts(); |
+ URLPatternSet active_explicit; |
+ SegregateUrlPermissions(active_permissions_unsafe_->explicit_hosts(), |
+ true, // withhold permissions |
+ &active_explicit, |
+ &withheld_explicit); |
+ |
+ active_permissions_unsafe_ = |
+ new PermissionSet(active_permissions_unsafe_->apis(), |
+ active_permissions_unsafe_->manifest_permissions(), |
+ active_explicit, |
+ active_scriptable); |
+ withheld_permissions_unsafe_ = |
+ new PermissionSet(withheld_permissions_unsafe_->apis(), |
+ withheld_permissions_unsafe_->manifest_permissions(), |
+ withheld_explicit, |
+ withheld_scriptable); |
+} |
+ |
+void PermissionsData::GrantWithheldAllHosts() const { |
+ base::AutoLock auto_lock(runtime_lock_); |
+ |
+ // 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_permissions_unsafe_->explicit_hosts(), |
+ withheld_permissions_unsafe_->explicit_hosts(), |
+ &explicit_hosts); |
+ URLPatternSet scriptable_hosts; |
+ URLPatternSet::CreateUnion(active_permissions_unsafe_->scriptable_hosts(), |
+ withheld_permissions_unsafe_->scriptable_hosts(), |
+ &scriptable_hosts); |
+ scoped_refptr<const PermissionSet> new_active_permissions = |
+ new PermissionSet(active_permissions_unsafe_->apis(), |
+ active_permissions_unsafe_->manifest_permissions(), |
+ explicit_hosts, |
+ scriptable_hosts); |
+ |
+ active_permissions_unsafe_ = new_active_permissions; |
+ // Since we only withhold host permissions (so far), we know that withheld |
+ // permissions will be empty. |
+ withheld_permissions_unsafe_ = new PermissionSet(); |
+} |
+ |
bool PermissionsData::CanAccessPage(const Extension* extension, |
const GURL& document_url, |
const GURL& top_frame_url, |
int tab_id, |
int process_id, |
std::string* error) const { |
+ AccessType result = CanRunOnPage(extension, |
+ document_url, |
+ top_frame_url, |
+ tab_id, |
+ process_id, |
+ active_permissions()->explicit_hosts(), |
+ withheld_permissions()->explicit_hosts(), |
+ error); |
+ // TODO(rdevlin.cronin) Update callers so that they only need ALLOW_ACCESS. |
+ return result == ALLOW_ACCESS || result == REQUEST_ACCESS; |
+} |
+ |
+PermissionsData::AccessType PermissionsData::CanAccessPageWithUserConsent( |
+ const Extension* extension, |
+ const GURL& document_url, |
+ const GURL& top_frame_url, |
+ int tab_id, |
+ int process_id, |
+ std::string* error) const { |
return CanRunOnPage(extension, |
document_url, |
top_frame_url, |
tab_id, |
process_id, |
active_permissions()->explicit_hosts(), |
+ withheld_permissions()->explicit_hosts(), |
error); |
} |
@@ -225,12 +366,33 @@ bool PermissionsData::CanRunContentScriptOnPage(const Extension* extension, |
int tab_id, |
int process_id, |
std::string* error) const { |
+ AccessType result = CanRunOnPage(extension, |
+ document_url, |
+ top_frame_url, |
+ tab_id, |
+ process_id, |
+ active_permissions()->scriptable_hosts(), |
+ withheld_permissions()->scriptable_hosts(), |
+ error); |
+ // TODO(rdevlin.cronin) Update callers so that they only need ALLOW_ACCESS. |
+ return result == ALLOW_ACCESS || result == REQUEST_ACCESS; |
+} |
+ |
+PermissionsData::AccessType |
+PermissionsData::CanRunContentScriptOnPageWithUserConsent( |
+ const Extension* extension, |
+ const GURL& document_url, |
+ const GURL& top_frame_url, |
+ int tab_id, |
+ int process_id, |
+ std::string* error) const { |
return CanRunOnPage(extension, |
document_url, |
top_frame_url, |
tab_id, |
process_id, |
active_permissions()->scriptable_hosts(), |
+ withheld_permissions()->scriptable_hosts(), |
error); |
} |
@@ -259,37 +421,6 @@ bool PermissionsData::CanCaptureVisiblePage(int tab_id, |
return false; |
} |
-// static |
-bool PermissionsData::RequiresActionForScriptExecution( |
- const Extension* extension) const { |
- return RequiresActionForScriptExecution(extension, -1, GURL()); |
-} |
- |
-// static |
-bool PermissionsData::RequiresActionForScriptExecution( |
- const Extension* extension, |
- int tab_id, |
- const GURL& url) const { |
- // For now, the user should be notified when an extension with all hosts |
- // permission tries to execute a script on a page. Exceptions for policy- |
- // enabled and component extensions, and extensions which are whitelisted to |
- // execute scripts everywhere. |
- if (!extension->ShouldDisplayInExtensionSettings() || |
- Manifest::IsPolicyLocation(extension->location()) || |
- Manifest::IsComponentLocation(extension->location()) || |
- CanExecuteScriptEverywhere(extension) || |
- !active_permissions()->ShouldWarnAllHosts()) { |
- return false; |
- } |
- |
- // If the extension has explicit permission to run on the given tab, then |
- // we don't need to alert the user. |
- if (HasTabSpecificPermissionToExecuteScript(tab_id, url)) |
- return false; |
- |
- return true; |
-} |
- |
scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions( |
int tab_id) const { |
base::AutoLock auto_lock(runtime_lock_); |
@@ -313,33 +444,38 @@ bool PermissionsData::HasTabSpecificPermissionToExecuteScript( |
return false; |
} |
-bool PermissionsData::CanRunOnPage(const Extension* extension, |
- const GURL& document_url, |
- const GURL& top_frame_url, |
- int tab_id, |
- int process_id, |
- const URLPatternSet& permitted_url_patterns, |
- std::string* error) const { |
+PermissionsData::AccessType PermissionsData::CanRunOnPage( |
+ const Extension* extension, |
+ const GURL& document_url, |
+ const GURL& top_frame_url, |
+ int tab_id, |
+ int process_id, |
+ const URLPatternSet& permitted_url_patterns, |
+ const URLPatternSet& withheld_url_patterns, |
+ std::string* error) const { |
if (g_policy_delegate && |
!g_policy_delegate->CanExecuteScriptOnPage( |
extension, document_url, top_frame_url, tab_id, process_id, error)) { |
- return false; |
+ return DENY_ACCESS; |
} |
if (IsRestrictedUrl(document_url, top_frame_url, extension, error)) |
- return false; |
+ return DENY_ACCESS; |
if (HasTabSpecificPermissionToExecuteScript(tab_id, top_frame_url)) |
- return true; |
+ return ALLOW_ACCESS; |
+ |
+ if (permitted_url_patterns.MatchesURL(document_url)) |
+ return ALLOW_ACCESS; |
- bool can_access = permitted_url_patterns.MatchesURL(document_url); |
+ if (withheld_url_patterns.MatchesURL(document_url)) |
+ return REQUEST_ACCESS; |
- if (!can_access && error) { |
+ if (error) { |
*error = ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage, |
document_url.spec()); |
} |
- |
- return can_access; |
+ return DENY_ACCESS; |
} |
} // namespace extensions |