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

Unified Diff: extensions/common/permissions/permissions_data.cc

Issue 348313003: Create withheld permissions (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Test fix Created 6 years, 6 months 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 side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698