blob: 21e72bb8a6994cf7b6051b525133f8fa5d9f28bd [file] [log] [blame]
// 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/check_op.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/functional/bind.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/trace_event/typed_macros.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/download/public/common/in_progress_download_manager.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/browsing_data/browsing_data_remover_impl.h"
#include "content/browser/child_process_host_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/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::ForEachLoadedStoragePartition(
StoragePartitionCallback callback) {
StoragePartitionImplMap* partition_map = impl()->storage_partition_map();
if (!partition_map)
return;
partition_map->ForEach(std::move(callback));
}
size_t BrowserContext::GetLoadedStoragePartitionCount() {
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();
}
std::unique_ptr<download::InProgressDownloadManager>
BrowserContext::RetrieveInProgressDownloadManager() {
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;
}
FederatedIdentityAutoReauthnPermissionContextDelegate*
BrowserContext::GetFederatedIdentityAutoReauthnPermissionContext() {
return nullptr;
}
FederatedIdentityPermissionContextDelegate*
BrowserContext::GetFederatedIdentityPermissionContext() {
return nullptr;
}
KAnonymityServiceDelegate* BrowserContext::GetKAnonymityServiceDelegate() {
return nullptr;
}
OriginTrialsControllerDelegate*
BrowserContext::GetOriginTrialsControllerDelegate() {
return nullptr;
}
} // namespace content