blob: 832bbbe58854bb83bde6ebeb1ef5ea3165d0f265 [file] [log] [blame]
// Copyright 2013 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/storage/durable_storage_permission_context.h"
#include <algorithm>
#include "base/check_op.h"
#include "base/containers/contains.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/engagement/important_sites_util.h"
#include "chrome/browser/profiles/profile.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/browser/website_settings_registry.h"
#include "components/content_settings/core/common/content_settings_utils.h"
#include "components/permissions/permission_decision.h"
#include "components/permissions/permission_request_data.h"
#include "components/permissions/permission_request_id.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/origin_util.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/schemeful_site.h"
#include "net/cookies/cookie_setting_override.h"
#include "net/cookies/site_for_cookies.h"
#include "services/network/public/mojom/permissions_policy/permissions_policy_feature.mojom-shared.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "url/gurl.h"
#include "url/origin.h"
using bookmarks::BookmarkModel;
using PermissionStatus = blink::mojom::PermissionStatus;
DurableStoragePermissionContext::DurableStoragePermissionContext(
content::BrowserContext* browser_context)
: permissions::ContentSettingPermissionContextBase(
browser_context,
ContentSettingsType::DURABLE_STORAGE,
network::mojom::PermissionsPolicyFeature::kNotFound) {}
void DurableStoragePermissionContext::DecidePermission(
std::unique_ptr<permissions::PermissionRequestData> request_data,
permissions::BrowserPermissionCallback callback) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK_NE(PermissionStatus::GRANTED,
GetPermissionStatus(
*request_data->resolver, nullptr /* render_frame_host */,
request_data->requesting_origin, request_data->embedding_origin)
.status);
DCHECK_NE(PermissionStatus::DENIED,
GetPermissionStatus(
*request_data->resolver, nullptr /* render_frame_host */,
request_data->requesting_origin, request_data->embedding_origin)
.status);
// Durable is only allowed to be granted to the top-level origin. Embedding
// origin is the last committed navigation origin to the web contents.
if (request_data->requesting_origin != request_data->embedding_origin) {
NotifyPermissionSet(*request_data, std::move(callback),
/*persist=*/false, PermissionDecision::kNone,
/*is_final_decision=*/true);
return;
}
scoped_refptr<content_settings::CookieSettings> cookie_settings =
CookieSettingsFactory::GetForProfile(
Profile::FromBrowserContext(browser_context()));
content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
request_data->id.global_render_frame_host_id());
CHECK(rfh);
// Don't grant durable for session-only storage, since it won't be persisted
// anyway. Don't grant durable if we can't write cookies.
if (cookie_settings->IsCookieSessionOnly(request_data->requesting_origin) ||
!cookie_settings->IsFullCookieAccessAllowed(
request_data->requesting_origin,
net::SiteForCookies::FromUrl(request_data->requesting_origin),
url::Origin::Create(request_data->requesting_origin),
net::CookieSettingOverrides(),
rfh->GetStorageKey().ToCookiePartitionKey())) {
NotifyPermissionSet(*request_data, std::move(callback),
/*persist=*/false, PermissionDecision::kNone,
/*is_final_decision=*/true);
return;
}
std::string registerable_domain =
net::registry_controlled_domains::GetDomainAndRegistry(
request_data->requesting_origin,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
if (registerable_domain.empty() &&
request_data->requesting_origin.HostIsIPAddress()) {
registerable_domain = request_data->requesting_origin.host();
}
std::set<std::string> installed_registerable_domains =
site_engagement::ImportantSitesUtil::GetInstalledRegisterableDomains(
Profile::FromBrowserContext(browser_context()));
if (base::Contains(installed_registerable_domains, registerable_domain)) {
NotifyPermissionSet(*request_data, std::move(callback),
/*persist=*/true, PermissionDecision::kAllow,
/*is_final_decision=*/true);
return;
}
const size_t kMaxImportantResults = 10;
std::vector<site_engagement::ImportantSitesUtil::ImportantDomainInfo>
important_sites =
site_engagement::ImportantSitesUtil::GetImportantRegisterableDomains(
Profile::FromBrowserContext(browser_context()),
kMaxImportantResults);
for (const auto& important_site : important_sites) {
if (important_site.registerable_domain == registerable_domain) {
NotifyPermissionSet(*request_data, std::move(callback),
/*persist=*/true, PermissionDecision::kAllow,
/*is_final_decision=*/true);
return;
}
}
NotifyPermissionSet(*request_data, std::move(callback),
/*persist=*/false, PermissionDecision::kNone,
/*is_final_decision=*/true);
}
void DurableStoragePermissionContext::UpdateContentSetting(
const permissions::PermissionRequestData& request_data,
ContentSetting content_setting,
bool is_one_time) {
DCHECK(!is_one_time);
DCHECK_EQ(request_data.requesting_origin,
request_data.requesting_origin.DeprecatedGetOriginAsURL());
DCHECK_EQ(request_data.embedding_origin,
request_data.embedding_origin.DeprecatedGetOriginAsURL());
DCHECK(content_setting == CONTENT_SETTING_ALLOW ||
content_setting == CONTENT_SETTING_BLOCK);
HostContentSettingsMapFactory::GetForProfile(browser_context())
->SetContentSettingDefaultScope(request_data.requesting_origin, GURL(),
ContentSettingsType::DURABLE_STORAGE,
content_setting);
}