blob: f24a29f20a744ffd70f3b1ea74f7235d4b3322bc [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/scripting_permissions_modifier.h"
#include "base/functional/callback_helpers.h"
#include "chrome/browser/extensions/permissions_updater.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_util.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/permissions_manager.h"
#include "extensions/common/extension.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/user_script.h"
namespace extensions {
ScriptingPermissionsModifier::ScriptingPermissionsModifier(
content::BrowserContext* browser_context,
const scoped_refptr<const Extension>& extension)
: browser_context_(browser_context),
extension_(extension),
extension_prefs_(ExtensionPrefs::Get(browser_context_)),
permissions_manager_(PermissionsManager::Get(browser_context_)) {
DCHECK(extension_);
}
ScriptingPermissionsModifier::~ScriptingPermissionsModifier() = default;
void ScriptingPermissionsModifier::SetWithholdHostPermissions(
bool should_withhold) {
DCHECK(permissions_manager_->CanAffectExtension(*extension_));
if (permissions_manager_->HasWithheldHostPermissions(*extension_) ==
should_withhold) {
return;
}
// Set the pref first, so that listeners for permission changes get the proper
// value if they query HasWithheldHostPermissions().
extension_prefs_->SetWithholdingPermissions(extension_->id(),
should_withhold);
if (should_withhold) {
RemoveAllGrantedHostPermissions();
} else {
GrantWithheldHostPermissions();
}
}
void ScriptingPermissionsModifier::GrantHostPermission(const GURL& url) {
CHECK(permissions_manager_->CanAffectExtension(*extension_));
// Check that we don't grant host permission to a restricted URL.
CHECK(
!extension_->permissions_data()->IsRestrictedUrl(url, /*error=*/nullptr))
<< "Cannot grant access to a restricted URL.";
URLPatternSet explicit_hosts;
explicit_hosts.AddOrigin(Extension::kValidHostPermissionSchemes, url);
URLPatternSet scriptable_hosts;
scriptable_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(), url);
GrantHostPermission(std::move(explicit_hosts), std::move(scriptable_hosts),
base::DoNothing());
}
// Adds `site` to the extension's set of runtime granted host permissions.
void ScriptingPermissionsModifier::GrantHostPermission(
const URLPattern& site,
base::OnceClosure done_callback) {
CHECK(permissions_manager_->CanAffectExtension(*extension_));
URLPatternSet new_host_permissions({site});
GrantHostPermission(new_host_permissions.Clone(),
new_host_permissions.Clone(), std::move(done_callback));
}
void ScriptingPermissionsModifier::RemoveGrantedHostPermission(
const GURL& url) {
CHECK(permissions_manager_->CanAffectExtension(*extension_));
CHECK(permissions_manager_->HasGrantedHostPermission(*extension_, url));
std::unique_ptr<const PermissionSet> runtime_permissions =
permissions_manager_->GetRuntimePermissionsFromPrefs(*extension_);
URLPatternSet explicit_hosts;
for (const auto& pattern : runtime_permissions->explicit_hosts()) {
if (pattern.MatchesSecurityOrigin(url)) {
explicit_hosts.AddPattern(pattern);
}
}
URLPatternSet scriptable_hosts;
for (const auto& pattern : runtime_permissions->scriptable_hosts()) {
if (pattern.MatchesSecurityOrigin(url)) {
scriptable_hosts.AddPattern(pattern);
}
}
WithholdHostPermissions(std::move(explicit_hosts),
std::move(scriptable_hosts), base::DoNothing());
}
void ScriptingPermissionsModifier::RemoveHostPermissions(
const URLPattern& pattern,
base::OnceClosure done_callback) {
CHECK(permissions_manager_->CanAffectExtension(*extension_));
// Revoke all sites which have some intersection with `pattern` from the
// extension's set of runtime granted host permissions.
std::unique_ptr<const PermissionSet> runtime_permissions =
permissions_manager_->GetRuntimePermissionsFromPrefs(*extension_);
URLPatternSet explicit_hosts;
for (const auto& runtime_pattern : runtime_permissions->explicit_hosts()) {
if (pattern.OverlapsWith(runtime_pattern)) {
explicit_hosts.AddPattern(runtime_pattern);
}
}
URLPatternSet scriptable_hosts;
for (const auto& runtime_pattern : runtime_permissions->scriptable_hosts()) {
if (pattern.OverlapsWith(runtime_pattern)) {
scriptable_hosts.AddPattern(runtime_pattern);
}
}
WithholdHostPermissions(std::move(explicit_hosts),
std::move(scriptable_hosts),
std::move(done_callback));
}
void ScriptingPermissionsModifier::RemoveBroadGrantedHostPermissions() {
DCHECK(permissions_manager_->CanAffectExtension(*extension_));
std::unique_ptr<const PermissionSet> runtime_permissions =
permissions_manager_->GetRuntimePermissionsFromPrefs(*extension_);
URLPatternSet explicit_hosts;
for (const auto& pattern : runtime_permissions->explicit_hosts()) {
if (pattern.MatchesEffectiveTld()) {
explicit_hosts.AddPattern(pattern);
}
}
URLPatternSet scriptable_hosts;
for (const auto& pattern : runtime_permissions->scriptable_hosts()) {
if (pattern.MatchesEffectiveTld()) {
scriptable_hosts.AddPattern(pattern);
}
}
PermissionsUpdater(browser_context_)
.RevokeRuntimePermissions(
*extension_,
PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
std::move(explicit_hosts), std::move(scriptable_hosts)),
base::DoNothing());
}
void ScriptingPermissionsModifier::RemoveAllGrantedHostPermissions() {
DCHECK(permissions_manager_->CanAffectExtension(*extension_));
std::unique_ptr<const PermissionSet> revokable_permissions =
permissions_manager_->GetRevokablePermissions(*extension_);
DCHECK(revokable_permissions);
PermissionsUpdater(browser_context_)
.RevokeRuntimePermissions(*extension_, *revokable_permissions,
base::DoNothing());
}
void ScriptingPermissionsModifier::GrantHostPermission(
URLPatternSet explicit_hosts,
URLPatternSet scriptable_hosts,
base::OnceClosure done_callback) {
PermissionsUpdater(browser_context_)
.GrantRuntimePermissions(
*extension_,
PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
std::move(explicit_hosts), std::move(scriptable_hosts)),
std::move(done_callback));
}
void ScriptingPermissionsModifier::GrantWithheldHostPermissions() {
const PermissionSet& withheld =
extension_->permissions_data()->withheld_permissions();
PermissionSet permissions(APIPermissionSet(), ManifestPermissionSet(),
withheld.explicit_hosts().Clone(),
withheld.scriptable_hosts().Clone());
PermissionsUpdater(browser_context_)
.GrantRuntimePermissions(*extension_, permissions, base::DoNothing());
}
void ScriptingPermissionsModifier::WithholdHostPermissions(
URLPatternSet explicit_hosts,
URLPatternSet scriptable_hosts,
base::OnceClosure done_callback) {
std::unique_ptr<const PermissionSet> permissions_to_remove =
PermissionSet::CreateIntersection(
PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
std::move(explicit_hosts), std::move(scriptable_hosts)),
*permissions_manager_->GetRevokablePermissions(*extension_),
URLPatternSet::IntersectionBehavior::kDetailed);
if (permissions_to_remove->IsEmpty()) {
std::move(done_callback).Run();
return;
}
PermissionsUpdater(browser_context_)
.RevokeRuntimePermissions(*extension_, *permissions_to_remove,
std::move(done_callback));
}
} // namespace extensions