#include "extensions/browser/permissions/site_permissions_helper.h"
#include "components/sessions/content/session_tab_helper.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/blocked_action_type.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/permissions/active_tab_permission_granter.h"
#include "extensions/browser/permissions/scripting_permissions_modifier.h"
#include "extensions/browser/permissions_manager.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/extension.h"
#include "extensions/common/permissions/permissions_data.h"
#include "url/gurl.h"
static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));
namespace extensions {
namespace {
constexpr const char kPrefShowAccessRequestsInToolbar[] =
"show_access_requests_in_toolbar";
constexpr int kRefreshRequiredActionsMask =
BLOCKED_ACTION_WEB_REQUEST | BLOCKED_ACTION_SCRIPT_AT_START;
}
SitePermissionsHelper::SitePermissionsHelper(
content::BrowserContext* browser_context)
: browser_context_(browser_context) {}
SitePermissionsHelper::~SitePermissionsHelper() = default;
SitePermissionsHelper::SiteInteraction
SitePermissionsHelper::GetSiteInteraction(
const Extension& extension,
content::WebContents* web_contents) const {
if (!web_contents) {
return SiteInteraction::kNone;
}
const int tab_id = sessions::SessionTabHelper::IdForTab(web_contents).id();
const GURL& url = web_contents->GetLastCommittedURL();
PermissionsData::PageAccess page_access =
extension.permissions_data()->GetPageAccess(url, tab_id,
nullptr);
PermissionsData::PageAccess script_access =
extension.permissions_data()->GetContentScriptAccess(url, tab_id,
nullptr);
if (page_access == PermissionsData::PageAccess::kAllowed ||
script_access == PermissionsData::PageAccess::kAllowed) {
return SiteInteraction::kGranted;
}
if (page_access == PermissionsData::PageAccess::kWithheld ||
script_access == PermissionsData::PageAccess::kWithheld ||
HasBeenBlocked(extension, web_contents)) {
return SiteInteraction::kWithheld;
}
if (PermissionsManager::Get(browser_context_)
->HasActiveTabAndCanAccess(extension, url)) {
return SiteInteraction::kActiveTab;
}
return SiteInteraction::kNone;
}
void SitePermissionsHelper::UpdateSiteAccess(
const Extension& extension,
content::WebContents* web_contents,
PermissionsManager::UserSiteAccess new_access) {
std::vector<const Extension*> extensions = {&extension};
UpdateSiteAccess(extensions, web_contents, new_access);
}
void SitePermissionsHelper::UpdateSiteAccess(
const std::vector<const Extension*>& extensions,
content::WebContents* web_contents,
PermissionsManager::UserSiteAccess new_access) {
auto current_url = web_contents->GetLastCommittedURL();
auto* permissions_manager = PermissionsManager::Get(browser_context_);
bool reload_required = false;
for (auto const* extension : extensions) {
auto current_access =
permissions_manager->GetUserSiteAccess(*extension, current_url);
if (new_access == current_access) {
break;
}
CHECK(permissions_manager->CanAffectExtension(*extension));
CHECK(permissions_manager->CanUserSelectSiteAccess(*extension, current_url,
new_access));
if (current_access == PermissionsManager::UserSiteAccess::kOnAllSites) {
permissions_manager->AddExtensionToPreviousBroadSiteAccessSet(
extension->id());
} else {
permissions_manager->RemoveExtensionFromPreviousBroadSiteAccessSet(
extension->id());
}
ScriptingPermissionsModifier modifier(browser_context_, extension);
switch (new_access) {
case PermissionsManager::UserSiteAccess::kOnClick:
if (permissions_manager->HasBroadGrantedHostPermissions(*extension)) {
modifier.RemoveBroadGrantedHostPermissions();
}
modifier.SetWithholdHostPermissions(true);
if (permissions_manager->HasGrantedHostPermission(*extension,
current_url)) {
modifier.RemoveGrantedHostPermission(current_url);
}
break;
case PermissionsManager::UserSiteAccess::kOnSite:
if (permissions_manager->HasBroadGrantedHostPermissions(*extension)) {
modifier.RemoveBroadGrantedHostPermissions();
}
modifier.SetWithholdHostPermissions(true);
if (!permissions_manager->HasGrantedHostPermission(*extension,
current_url)) {
modifier.GrantHostPermission(current_url);
}
break;
case PermissionsManager::UserSiteAccess::kOnAllSites:
modifier.SetWithholdHostPermissions(false);
break;
}
bool revoking_current_site_permissions =
new_access == PermissionsManager::UserSiteAccess::kOnClick;
if (revoking_current_site_permissions) {
ActiveTabPermissionGranter::FromWebContents(web_contents)
->ClearActiveExtensionAndNotify(extension->id());
reload_required = true;
break;
}
ExtensionsBrowserClient::Get()->RunBlockActionsIfNeeded(
extension, web_contents, this, &reload_required);
}
if (reload_required) {
ExtensionsBrowserClient::Get()->ShowReloadBubbleForAllExtensions(
extensions, web_contents);
}
}
bool SitePermissionsHelper::PageNeedsRefreshToRun(int blocked_actions) {
return blocked_actions & kRefreshRequiredActionsMask;
}
bool SitePermissionsHelper::HasBeenBlocked(
const Extension& extension,
content::WebContents* web_contents) const {
return ExtensionsBrowserClient::Get()->HasBeenBlocked(extension,
web_contents);
}
bool SitePermissionsHelper::ShowAccessRequestsInToolbar(
const std::string& extension_id) {
bool show_access_requests = true;
ExtensionPrefs::Get(browser_context_)
->ReadPrefAsBoolean(extension_id, kPrefShowAccessRequestsInToolbar,
&show_access_requests);
return show_access_requests;
}
void SitePermissionsHelper::SetShowAccessRequestsInToolbar(
const std::string& extension_id,
bool show_access_requests_in_toolbar) {
ExtensionPrefs::Get(browser_context_)
->UpdateExtensionPref(extension_id, kPrefShowAccessRequestsInToolbar,
base::Value(show_access_requests_in_toolbar));
PermissionsManager::Get(browser_context_)
->NotifyShowAccessRequestsInToolbarChanged(
extension_id, show_access_requests_in_toolbar);
}
}