0
Files
src/content/browser/browser_context.cc
Peter Birk Pakkenberg 73e07b672d Integrate origin trials with BrowserContext
Adding a new OriginTrialControllerDelegate interface which is
implemented by the OriginTrials component.
Adding factories for the component for chrome and weblayer based on
HostContentSettingsMap as the storage provider.

Adding browsertests for Chrome to test the functionality.

To support the browser tests, this CL introduces a generator for
test origin trial tokens, which allows us to use the embedded
test server on a random port, and still get valid tokens.

This CL is part of the persistent origin trials implementation.
Full implementation plan here:
https://docs.google.com/document/d/1v4cwALXi33VgYrdqFCldDT0N0BuwiXzESt7NIJIiOTs/edit?usp=sharing

Bug: 1257579
Test: browser_tests
Change-Id: I13f67174a24c6605d76db8ca5b6abd0cc2727431
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3664138
Reviewed-by: Christian Dullweber <dullweber@chromium.org>
Reviewed-by: Colin Blundell <blundell@chromium.org>
Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org>
Reviewed-by: Jason Chase <chasej@chromium.org>
Commit-Queue: Peter Pakkenberg <pbirk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1049578}
2022-09-21 11:20:30 +00:00

419 lines
14 KiB
C++

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/public/browser/browser_context.h"
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <limits>
#include <memory>
#include <unordered_set>
#include <utility>
#include <vector>
#include "base/base64.h"
#include "base/bind.h"
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/notreached.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/typed_macros.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/services/storage/privileged/mojom/indexed_db_control.mojom.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/browser_context_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/media/browser_feature_provider.h"
#include "content/browser/push_messaging/push_messaging_router.h"
#include "content/browser/site_info.h"
#include "content/browser/storage_partition_impl_map.h"
#include "content/common/child_process_host_impl.h"
#include "content/public/browser/blob_handle.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition_config.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "media/base/media_switches.h"
#include "media/capabilities/in_memory_video_decode_stats_db_impl.h"
#include "media/capabilities/video_decode_stats_db_impl.h"
#include "media/mojo/services/video_decode_perf_history.h"
#include "media/mojo/services/webrtc_video_perf_history.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/database/database_tracker.h"
#include "storage/browser/file_system/external_mount_points.h"
#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom.h"
#include "third_party/perfetto/include/perfetto/tracing/traced_proto.h"
#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
namespace content {
namespace {
using perfetto::protos::pbzero::ChromeBrowserContext;
using perfetto::protos::pbzero::ChromeTrackEvent;
base::WeakPtr<storage::BlobStorageContext> BlobStorageContextGetterForBrowser(
scoped_refptr<ChromeBlobStorageContext> blob_context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return blob_context->context()->AsWeakPtr();
}
} // namespace
BrowserContext::BrowserContext() {
impl_ = base::WrapUnique(new BrowserContextImpl(this));
TRACE_EVENT("shutdown", "BrowserContext::BrowserContext",
ChromeTrackEvent::kChromeBrowserContext, *this);
TRACE_EVENT_BEGIN("shutdown", "Browser.BrowserContext",
perfetto::Track::FromPointer(this),
ChromeTrackEvent::kChromeBrowserContext, *this);
}
BrowserContext::~BrowserContext() {
TRACE_EVENT("shutdown", "BrowserContext::~BrowserContext",
ChromeTrackEvent::kChromeBrowserContext, *this);
// End for ASYNC event "Browser.BrowserContext".
TRACE_EVENT_END("shutdown", perfetto::Track::FromPointer(this),
ChromeTrackEvent::kChromeBrowserContext, *this);
impl_.reset();
}
DownloadManager* BrowserContext::GetDownloadManager() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return impl()->GetDownloadManager();
}
storage::ExternalMountPoints* BrowserContext::GetMountPoints() {
return impl()->GetMountPoints();
}
BrowsingDataRemover* BrowserContext::GetBrowsingDataRemover() {
return impl()->GetBrowsingDataRemover();
}
PermissionController* BrowserContext::GetPermissionController() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return impl()->GetPermissionController();
}
StoragePartition* BrowserContext::GetStoragePartition(
SiteInstance* site_instance,
bool can_create) {
if (site_instance)
DCHECK_EQ(this, site_instance->GetBrowserContext());
auto partition_config = site_instance
? site_instance->GetStoragePartitionConfig()
: StoragePartitionConfig::CreateDefault(this);
return GetStoragePartition(partition_config, can_create);
}
StoragePartition* BrowserContext::GetStoragePartition(
const StoragePartitionConfig& storage_partition_config,
bool can_create) {
if (IsOffTheRecord()) {
// An off the record profile MUST only use in memory storage partitions.
CHECK(storage_partition_config.in_memory());
}
return impl()->GetOrCreateStoragePartitionMap()->Get(storage_partition_config,
can_create);
}
StoragePartition* BrowserContext::GetStoragePartitionForUrl(
const GURL& url,
bool can_create) {
auto storage_partition_config = SiteInfo::GetStoragePartitionConfigForUrl(
this, url, /*is_site_url=*/false);
return GetStoragePartition(storage_partition_config, can_create);
}
void BrowserContext::ForEachStoragePartition(
StoragePartitionCallback callback) {
StoragePartitionImplMap* partition_map = impl()->storage_partition_map();
if (!partition_map)
return;
partition_map->ForEach(std::move(callback));
}
void BrowserContext::DisposeStoragePartition(
StoragePartition* storage_partition) {
StoragePartitionImplMap* partition_map = impl()->storage_partition_map();
if (!partition_map)
return;
partition_map->DisposeInMemory(storage_partition);
}
size_t BrowserContext::GetStoragePartitionCount() {
StoragePartitionImplMap* partition_map = impl()->storage_partition_map();
return partition_map ? partition_map->size() : 0;
}
void BrowserContext::AsyncObliterateStoragePartition(
const std::string& partition_domain,
base::OnceClosure on_gc_required,
base::OnceClosure done_callback) {
impl()->GetOrCreateStoragePartitionMap()->AsyncObliterate(
partition_domain, std::move(on_gc_required), std::move(done_callback));
}
void BrowserContext::GarbageCollectStoragePartitions(
std::unordered_set<base::FilePath> active_paths,
base::OnceClosure done) {
impl()->GetOrCreateStoragePartitionMap()->GarbageCollect(
std::move(active_paths), std::move(done));
}
StoragePartition* BrowserContext::GetDefaultStoragePartition() {
return GetStoragePartition(StoragePartitionConfig::CreateDefault(this));
}
void BrowserContext::CreateMemoryBackedBlob(base::span<const uint8_t> data,
const std::string& content_type,
BlobCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
ChromeBlobStorageContext* blob_context =
ChromeBlobStorageContext::GetFor(this);
GetIOThreadTaskRunner({})->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&ChromeBlobStorageContext::CreateMemoryBackedBlob,
base::WrapRefCounted(blob_context), data, content_type),
std::move(callback));
}
BrowserContext::BlobContextGetter BrowserContext::GetBlobStorageContext() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
scoped_refptr<ChromeBlobStorageContext> chrome_blob_context =
ChromeBlobStorageContext::GetFor(this);
return base::BindRepeating(&BlobStorageContextGetterForBrowser,
chrome_blob_context);
}
mojo::PendingRemote<blink::mojom::Blob> BrowserContext::GetBlobRemote(
const std::string& uuid) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return ChromeBlobStorageContext::GetBlobRemote(this, uuid);
}
void BrowserContext::DeliverPushMessage(
const GURL& origin,
int64_t service_worker_registration_id,
const std::string& message_id,
absl::optional<std::string> payload,
base::OnceCallback<void(blink::mojom::PushEventStatus)> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PushMessagingRouter::DeliverMessage(
this, origin, service_worker_registration_id, message_id,
std::move(payload), std::move(callback));
}
void BrowserContext::FirePushSubscriptionChangeEvent(
const GURL& origin,
int64_t service_worker_registration_id,
blink::mojom::PushSubscriptionPtr new_subscription,
blink::mojom::PushSubscriptionPtr old_subscription,
base::OnceCallback<void(blink::mojom::PushEventStatus)> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PushMessagingRouter::FireSubscriptionChangeEvent(
this, origin, service_worker_registration_id, std::move(new_subscription),
std::move(old_subscription), std::move(callback));
}
void BrowserContext::NotifyWillBeDestroyed() {
impl()->NotifyWillBeDestroyed();
}
void BrowserContext::EnsureResourceContextInitialized() {
// This will be enough to tickle initialization of BrowserContext if
// necessary, which initializes ResourceContext. The reason we don't call
// ResourceContext::InitializeResourceContext() directly here is that
// ResourceContext initialization may call back into BrowserContext
// and when that call returns it'll end rewriting its Impl. It will
// end up rewriting the same value but this still causes a race condition.
//
// See http://crbug.com/115678.
GetDefaultStoragePartition();
}
void BrowserContext::SaveSessionState() {
StoragePartition* storage_partition = GetDefaultStoragePartition();
storage::DatabaseTracker* database_tracker =
storage_partition->GetDatabaseTracker();
database_tracker->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&storage::DatabaseTracker::SetForceKeepSessionState,
base::WrapRefCounted(database_tracker)));
storage_partition->GetCookieManagerForBrowserProcess()
->SetForceKeepSessionState();
DOMStorageContextWrapper* dom_storage_context_proxy =
static_cast<DOMStorageContextWrapper*>(
storage_partition->GetDOMStorageContext());
dom_storage_context_proxy->SetForceKeepSessionState();
auto& indexed_db_control = storage_partition->GetIndexedDBControl();
indexed_db_control.SetForceKeepSessionState();
}
void BrowserContext::SetDownloadManagerForTesting(
std::unique_ptr<DownloadManager> download_manager) {
impl()->SetDownloadManagerForTesting(std::move(download_manager)); // IN-TEST
}
void BrowserContext::SetPermissionControllerForTesting(
std::unique_ptr<PermissionController> permission_controller) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(permission_controller);
impl()->SetPermissionControllerForTesting( // IN-TEST
std::move(permission_controller));
}
SharedCorsOriginAccessList* BrowserContext::GetSharedCorsOriginAccessList() {
return impl()->shared_cors_origin_access_list();
}
void BrowserContext::ShutdownStoragePartitions() {
impl()->ShutdownStoragePartitions();
}
bool BrowserContext::ShutdownStarted() {
return impl()->ShutdownStarted();
}
const std::string& BrowserContext::UniqueId() {
return impl()->UniqueId();
}
media::VideoDecodePerfHistory* BrowserContext::GetVideoDecodePerfHistory() {
return impl()->GetVideoDecodePerfHistory();
}
media::WebrtcVideoPerfHistory* BrowserContext::GetWebrtcVideoPerfHistory() {
return impl()->GetWebrtcVideoPerfHistory();
}
media::learning::LearningSession* BrowserContext::GetLearningSession() {
return impl()->GetLearningSession();
}
download::InProgressDownloadManager*
BrowserContext::RetriveInProgressDownloadManager() {
return nullptr;
}
// static
std::string BrowserContext::CreateRandomMediaDeviceIDSalt() {
return base::UnguessableToken::Create().ToString();
}
void BrowserContext::WriteIntoTrace(
perfetto::TracedProto<ChromeBrowserContext> proto) const {
perfetto::WriteIntoTracedProto(std::move(proto), impl());
}
//////////////////////////////////////////////////////////////////////////////
// The //content embedder can override the methods below to change or extend
// how the //content layer interacts with a BrowserContext. The code below
// provides default implementations where appropriate.
//
// TODO(https://crbug.com/1179776): Migrate method definitions from this
// section into a separate BrowserContextDelegate class and a separate
// browser_context_delegate.cc source file.
std::string BrowserContext::GetMediaDeviceIDSalt() {
return UniqueId();
}
FileSystemAccessPermissionContext*
BrowserContext::GetFileSystemAccessPermissionContext() {
return nullptr;
}
ContentIndexProvider* BrowserContext::GetContentIndexProvider() {
return nullptr;
}
bool BrowserContext::CanUseDiskWhenOffTheRecord() {
return false;
}
variations::VariationsClient* BrowserContext::GetVariationsClient() {
return nullptr;
}
std::unique_ptr<media::VideoDecodePerfHistory>
BrowserContext::CreateVideoDecodePerfHistory() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const char kUseInMemoryDBParamName[] = "db_in_memory";
const bool kUseInMemoryDBDefault = false;
bool use_in_memory_db = base::GetFieldTrialParamByFeatureAsBool(
media::kMediaCapabilitiesWithParameters, kUseInMemoryDBParamName,
kUseInMemoryDBDefault);
std::unique_ptr<media::VideoDecodeStatsDB> stats_db;
if (use_in_memory_db) {
stats_db = std::make_unique<media::InMemoryVideoDecodeStatsDBImpl>(nullptr);
} else {
auto* db_provider =
GetDefaultStoragePartition()->GetProtoDatabaseProvider();
stats_db = media::VideoDecodeStatsDBImpl::Create(
GetPath().Append(FILE_PATH_LITERAL("VideoDecodeStats")), db_provider);
}
return std::make_unique<media::VideoDecodePerfHistory>(
std::move(stats_db), BrowserFeatureProvider::GetFactoryCB());
}
FederatedIdentityApiPermissionContextDelegate*
BrowserContext::GetFederatedIdentityApiPermissionContext() {
return nullptr;
}
FederatedIdentityActiveSessionPermissionContextDelegate*
BrowserContext::GetFederatedIdentityActiveSessionPermissionContext() {
return nullptr;
}
FederatedIdentitySharingPermissionContextDelegate*
BrowserContext::GetFederatedIdentitySharingPermissionContext() {
return nullptr;
}
KAnonymityServiceDelegate* BrowserContext::GetKAnonymityServiceDelegate() {
return nullptr;
}
OriginTrialsControllerDelegate*
BrowserContext::GetOriginTrialsControllerDelegate() {
return nullptr;
}
} // namespace content