0
Files
src/content/browser/browser_context.cc
Aaron Colwell 4fcbe41517 Introduce ChildProcessSecurityPolicyImpl::Handle.
This change introduces a Handle object so that Mojo services can
preserve the security state beyond the lifetime of the
RenderProcessHostImpl object. This allows consistent security
checks to occur even during the period when the renderer process is
shutting down and there are still pending Mojo operations in flight.
This will be used to remove all remaining uses of
ChildProcessSecurityPolicyImpl::HasSecurityState() in follow-up CLs.

- Implements new Handle object that allows security checks to provide
  consistent results after ChildProcessSecurityPolicyImpl::Remove() is
  called.
- Convert blob code to use Handle instead of the HasSecurityState()
  workaround.

This is an updated version of https://crrev.com/c/1534368 . Further
discussion of the history and reasons for this CL can be found there.

Bug: 1035399, 943887
Change-Id: I6165fad4308643a1ddc845690443e8efceac65f4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1975165
Reviewed-by: Aaron Colwell <acolwell@chromium.org>
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
Reviewed-by: Łukasz Anforowicz <lukasza@chromium.org>
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
Commit-Queue: Aaron Colwell <acolwell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#732296}
2020-01-16 07:10:59 +00:00

765 lines
28 KiB
C++

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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/command_line.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/guid.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/no_destructor.h"
#include "base/rand_util.h"
#include "base/supports_user_data.h"
#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "content/browser/background_sync/background_sync_scheduler.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/browsing_data/browsing_data_remover_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/content_service_delegate_impl.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/media/browser_feature_provider.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/push_messaging/push_messaging_router.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/indexed_db_context.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/shared_cors_origin_access_list.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/system_connector.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.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/learning/common/media_learning_tasks.h"
#include "media/learning/impl/learning_session_impl.h"
#include "media/mojo/services/video_decode_perf_history.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/cookies/cookie_store.h"
#include "net/url_request/url_request_context.h"
#include "services/content/service.h"
#include "services/network/public/cpp/features.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/service.h"
#include "services/service_manager/public/mojom/service.mojom.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"
using base::UserDataAdapter;
namespace content {
namespace {
using TokenToContextMap = std::map<base::Token, BrowserContext*>;
TokenToContextMap& GetTokenToContextMap() {
static base::NoDestructor<TokenToContextMap> map;
return *map;
}
class ServiceInstanceGroupHolder : public base::SupportsUserData::Data {
public:
explicit ServiceInstanceGroupHolder(const base::Token& instance_group)
: instance_group_(instance_group) {}
~ServiceInstanceGroupHolder() override {}
const base::Token& instance_group() const { return instance_group_; }
private:
base::Token instance_group_;
DISALLOW_COPY_AND_ASSIGN(ServiceInstanceGroupHolder);
};
class ContentServiceHolder : public base::SupportsUserData::Data {
public:
explicit ContentServiceHolder(BrowserContext* browser_context)
: delegate_(browser_context) {
delegate_.AddService(&service_);
}
~ContentServiceHolder() override = default;
content::Service& service() { return service_; }
private:
ContentServiceDelegateImpl delegate_;
content::Service service_{&delegate_};
DISALLOW_COPY_AND_ASSIGN(ContentServiceHolder);
};
// Key names on BrowserContext.
const char kBrowsingDataRemoverKey[] = "browsing-data-remover";
const char kContentServiceKey[] = "content-service";
const char kDownloadManagerKeyName[] = "download_manager";
const char kPermissionControllerKey[] = "permission-controller";
const char kServiceManagerConnection[] = "service-manager-connection";
const char kServiceInstanceGroup[] = "service-instance-group";
const char kStoragePartitionMapKeyName[] = "content_storage_partition_map";
const char kVideoDecodePerfHistoryId[] = "video-decode-perf-history";
const char kLearningSession[] = "learning-session";
#if defined(OS_CHROMEOS)
const char kMountPointsKey[] = "mount_points";
#endif // defined(OS_CHROMEOS)
void RemoveBrowserContextFromInstanceGroupMap(BrowserContext* browser_context) {
ServiceInstanceGroupHolder* holder = static_cast<ServiceInstanceGroupHolder*>(
browser_context->GetUserData(kServiceInstanceGroup));
if (holder) {
auto it = GetTokenToContextMap().find(holder->instance_group());
if (it != GetTokenToContextMap().end())
GetTokenToContextMap().erase(it);
}
}
StoragePartitionImplMap* GetStoragePartitionMap(
BrowserContext* browser_context) {
StoragePartitionImplMap* partition_map =
static_cast<StoragePartitionImplMap*>(
browser_context->GetUserData(kStoragePartitionMapKeyName));
if (!partition_map) {
auto partition_map_owned =
std::make_unique<StoragePartitionImplMap>(browser_context);
partition_map = partition_map_owned.get();
browser_context->SetUserData(kStoragePartitionMapKeyName,
std::move(partition_map_owned));
}
return partition_map;
}
StoragePartition* GetStoragePartitionFromConfig(
BrowserContext* browser_context,
const std::string& partition_domain,
const std::string& partition_name,
bool in_memory,
bool can_create) {
StoragePartitionImplMap* partition_map =
GetStoragePartitionMap(browser_context);
if (browser_context->IsOffTheRecord())
in_memory = true;
return partition_map->Get(partition_domain, partition_name, in_memory,
can_create);
}
void SaveSessionStateOnIOThread(AppCacheServiceImpl* appcache_service) {
appcache_service->set_force_keep_session_state();
}
void SaveSessionStateOnIndexedDBThread(
scoped_refptr<IndexedDBContext> indexed_db_context) {
indexed_db_context->SetForceKeepSessionState();
}
void ShutdownServiceWorkerContext(StoragePartition* partition) {
ServiceWorkerContextWrapper* wrapper =
static_cast<ServiceWorkerContextWrapper*>(
partition->GetServiceWorkerContext());
wrapper->process_manager()->Shutdown();
}
void SetDownloadManager(
BrowserContext* context,
std::unique_ptr<content::DownloadManager> download_manager) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(download_manager);
context->SetUserData(kDownloadManagerKeyName, std::move(download_manager));
}
class BrowserContextServiceManagerConnectionHolder
: public base::SupportsUserData::Data {
public:
explicit BrowserContextServiceManagerConnectionHolder(
service_manager::mojom::ServiceRequest request)
: service_manager_connection_(ServiceManagerConnection::Create(
std::move(request),
base::CreateSingleThreadTaskRunner({BrowserThread::IO}))) {}
~BrowserContextServiceManagerConnectionHolder() override {}
ServiceManagerConnection* service_manager_connection() {
return service_manager_connection_.get();
}
private:
std::unique_ptr<ServiceManagerConnection> service_manager_connection_;
DISALLOW_COPY_AND_ASSIGN(BrowserContextServiceManagerConnectionHolder);
};
base::WeakPtr<storage::BlobStorageContext> BlobStorageContextGetterForBrowser(
scoped_refptr<ChromeBlobStorageContext> blob_context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return blob_context->context()->AsWeakPtr();
}
} // namespace
// static
void BrowserContext::AsyncObliterateStoragePartition(
BrowserContext* browser_context,
const std::string& partition_domain,
base::OnceClosure on_gc_required) {
GetStoragePartitionMap(browser_context)
->AsyncObliterate(partition_domain, std::move(on_gc_required));
}
// static
void BrowserContext::GarbageCollectStoragePartitions(
BrowserContext* browser_context,
std::unique_ptr<std::unordered_set<base::FilePath>> active_paths,
base::OnceClosure done) {
GetStoragePartitionMap(browser_context)
->GarbageCollect(std::move(active_paths), std::move(done));
}
DownloadManager* BrowserContext::GetDownloadManager(BrowserContext* context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!context->GetUserData(kDownloadManagerKeyName)) {
DownloadManager* download_manager = new DownloadManagerImpl(context);
SetDownloadManager(context, base::WrapUnique(download_manager));
download_manager->SetDelegate(context->GetDownloadManagerDelegate());
}
return static_cast<DownloadManager*>(
context->GetUserData(kDownloadManagerKeyName));
}
// static
storage::ExternalMountPoints* BrowserContext::GetMountPoints(
BrowserContext* context) {
// Ensure that these methods are called on the UI thread, except for
// unittests where a UI thread might not have been created.
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
!BrowserThread::IsThreadInitialized(BrowserThread::UI));
#if defined(OS_CHROMEOS)
if (!context->GetUserData(kMountPointsKey)) {
scoped_refptr<storage::ExternalMountPoints> mount_points =
storage::ExternalMountPoints::CreateRefCounted();
context->SetUserData(
kMountPointsKey,
std::make_unique<UserDataAdapter<storage::ExternalMountPoints>>(
mount_points.get()));
}
return UserDataAdapter<storage::ExternalMountPoints>::Get(context,
kMountPointsKey);
#else
return nullptr;
#endif
}
// static
content::BrowsingDataRemover* content::BrowserContext::GetBrowsingDataRemover(
BrowserContext* context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!context->GetUserData(kBrowsingDataRemoverKey)) {
std::unique_ptr<BrowsingDataRemoverImpl> remover =
std::make_unique<BrowsingDataRemoverImpl>(context);
remover->SetEmbedderDelegate(context->GetBrowsingDataRemoverDelegate());
context->SetUserData(kBrowsingDataRemoverKey, std::move(remover));
}
return static_cast<BrowsingDataRemoverImpl*>(
context->GetUserData(kBrowsingDataRemoverKey));
}
// static
content::PermissionController* content::BrowserContext::GetPermissionController(
BrowserContext* context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!context->GetUserData(kPermissionControllerKey)) {
context->SetUserData(kPermissionControllerKey,
std::make_unique<PermissionControllerImpl>(context));
}
return static_cast<PermissionControllerImpl*>(
context->GetUserData(kPermissionControllerKey));
}
StoragePartition* BrowserContext::GetStoragePartition(
BrowserContext* browser_context,
SiteInstance* site_instance,
bool can_create) {
std::string partition_domain;
std::string partition_name;
bool in_memory = false;
if (site_instance) {
GetContentClient()->browser()->GetStoragePartitionConfigForSite(
browser_context, site_instance->GetSiteURL(), true, &partition_domain,
&partition_name, &in_memory);
}
return GetStoragePartitionFromConfig(browser_context, partition_domain,
partition_name, in_memory, can_create);
}
StoragePartition* BrowserContext::GetStoragePartitionForSite(
BrowserContext* browser_context,
const GURL& site,
bool can_create) {
std::string partition_domain;
std::string partition_name;
bool in_memory;
GetContentClient()->browser()->GetStoragePartitionConfigForSite(
browser_context, site, true, &partition_domain, &partition_name,
&in_memory);
return GetStoragePartitionFromConfig(browser_context, partition_domain,
partition_name, in_memory, can_create);
}
void BrowserContext::ForEachStoragePartition(
BrowserContext* browser_context,
StoragePartitionCallback callback) {
StoragePartitionImplMap* partition_map =
static_cast<StoragePartitionImplMap*>(
browser_context->GetUserData(kStoragePartitionMapKeyName));
if (!partition_map)
return;
partition_map->ForEach(std::move(callback));
}
StoragePartition* BrowserContext::GetDefaultStoragePartition(
BrowserContext* browser_context) {
return GetStoragePartition(browser_context, nullptr);
}
// static
void BrowserContext::CreateMemoryBackedBlob(BrowserContext* browser_context,
base::span<const uint8_t> data,
const std::string& content_type,
BlobCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
ChromeBlobStorageContext* blob_context =
ChromeBlobStorageContext::GetFor(browser_context);
base::PostTaskAndReplyWithResult(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ChromeBlobStorageContext::CreateMemoryBackedBlob,
base::WrapRefCounted(blob_context), data, content_type),
std::move(callback));
}
// static
BrowserContext::BlobContextGetter BrowserContext::GetBlobStorageContext(
BrowserContext* browser_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
scoped_refptr<ChromeBlobStorageContext> chrome_blob_context =
ChromeBlobStorageContext::GetFor(browser_context);
return base::BindRepeating(&BlobStorageContextGetterForBrowser,
chrome_blob_context);
}
// static
mojo::PendingRemote<blink::mojom::Blob> BrowserContext::GetBlobRemote(
BrowserContext* browser_context,
const std::string& uuid) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return ChromeBlobStorageContext::GetBlobRemote(browser_context, uuid);
}
// static
void BrowserContext::DeliverPushMessage(
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
const std::string& message_id,
base::Optional<std::string> payload,
base::OnceCallback<void(blink::mojom::PushDeliveryStatus)> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PushMessagingRouter::DeliverMessage(
browser_context, origin, service_worker_registration_id, message_id,
std::move(payload), std::move(callback));
}
// static
void BrowserContext::NotifyWillBeDestroyed(BrowserContext* browser_context) {
// Make sure NotifyWillBeDestroyed is idempotent. This helps facilitate the
// pattern where NotifyWillBeDestroyed is called from *both*
// ShellBrowserContext and its derived classes (e.g. WebTestBrowserContext).
if (browser_context->was_notify_will_be_destroyed_called_)
return;
browser_context->was_notify_will_be_destroyed_called_ = true;
// Stop the ServiceManagerConnection from handling any new incoming requests
// before we tear anything down. This prevents races at shutdown.
BrowserContextServiceManagerConnectionHolder* connection_holder =
static_cast<BrowserContextServiceManagerConnectionHolder*>(
browser_context->GetUserData(kServiceManagerConnection));
if (connection_holder)
connection_holder->service_manager_connection()->Stop();
// Subclasses of BrowserContext may expect there to be no more
// RenderProcessHosts using them by the time this function returns. We
// therefore explicitly tear down embedded Content Service instances now to
// ensure that all their WebContents (and therefore RPHs) are torn down too.
browser_context->RemoveUserData(kContentServiceKey);
// Service Workers must shutdown before the browser context is destroyed,
// since they keep render process hosts alive and the codebase assumes that
// render process hosts die before their profile (browser context) dies.
ForEachStoragePartition(browser_context,
base::BindRepeating(ShutdownServiceWorkerContext));
// Shared workers also keep render process hosts alive, and are expected to
// return ref counts to 0 after documents close. However, to ensure that
// hosts are destructed now, forcibly release their ref counts here.
for (RenderProcessHost::iterator host_iterator =
RenderProcessHost::AllHostsIterator();
!host_iterator.IsAtEnd(); host_iterator.Advance()) {
RenderProcessHost* host = host_iterator.GetCurrentValue();
if (host->GetBrowserContext() == browser_context) {
// This will also clean up spare RPH references.
host->DisableKeepAliveRefCount();
}
}
// Clean up any isolated origins and other security state associated with this
// BrowserContext. This should be safe now that all RenderProcessHosts are
// destroyed, since future navigations or security decisions shouldn't ever
// need to consult these isolated origins and other security state.
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
policy->RemoveStateForBrowserContext(*browser_context);
}
void BrowserContext::EnsureResourceContextInitialized(BrowserContext* context) {
// 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 UserData map. It will
// end up rewriting the same value but this still causes a race condition.
//
// See http://crbug.com/115678.
GetDefaultStoragePartition(context);
}
void BrowserContext::SaveSessionState(BrowserContext* browser_context) {
StoragePartition* storage_partition =
BrowserContext::GetDefaultStoragePartition(browser_context);
storage::DatabaseTracker* database_tracker =
storage_partition->GetDatabaseTracker();
database_tracker->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&storage::DatabaseTracker::SetForceKeepSessionState,
base::WrapRefCounted(database_tracker)));
if (BrowserThread::IsThreadInitialized(BrowserThread::IO)) {
base::PostTask(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SaveSessionStateOnIOThread,
static_cast<AppCacheServiceImpl*>(
storage_partition->GetAppCacheService())));
}
storage_partition->GetCookieManagerForBrowserProcess()
->SetForceKeepSessionState();
DOMStorageContextWrapper* dom_storage_context_proxy =
static_cast<DOMStorageContextWrapper*>(
storage_partition->GetDOMStorageContext());
dom_storage_context_proxy->SetForceKeepSessionState();
scoped_refptr<IndexedDBContext> indexed_db_context =
storage_partition->GetIndexedDBContext();
IndexedDBContext* const indexed_db_context_ptr = indexed_db_context.get();
indexed_db_context_ptr->IDBTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&SaveSessionStateOnIndexedDBThread,
std::move(indexed_db_context)));
}
void BrowserContext::SetDownloadManagerForTesting(
BrowserContext* browser_context,
std::unique_ptr<content::DownloadManager> download_manager) {
SetDownloadManager(browser_context, std::move(download_manager));
}
// static
void BrowserContext::SetPermissionControllerForTesting(
BrowserContext* browser_context,
std::unique_ptr<PermissionController> permission_controller) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(permission_controller);
browser_context->SetUserData(kPermissionControllerKey,
std::move(permission_controller));
}
// static
void BrowserContext::Initialize(BrowserContext* browser_context,
const base::FilePath& path) {
const base::Token new_group = base::Token::CreateRandom();
RemoveBrowserContextFromInstanceGroupMap(browser_context);
GetTokenToContextMap()[new_group] = browser_context;
browser_context->SetUserData(
kServiceInstanceGroup,
std::make_unique<ServiceInstanceGroupHolder>(new_group));
auto* system_connector = GetSystemConnector();
if (system_connector && base::ThreadTaskRunnerHandle::IsSet()) {
// NOTE: Many unit tests create a TestBrowserContext without initializing
// Mojo or the global service manager connection.
mojo::PendingRemote<service_manager::mojom::Service> service;
auto service_receiver = service.InitWithNewPipeAndPassReceiver();
mojo::Remote<service_manager::mojom::ProcessMetadata> metadata;
service_manager::Identity identity(mojom::kBrowserServiceName, new_group,
base::Token{},
base::Token::CreateRandom());
system_connector->RegisterServiceInstance(
identity, std::move(service), metadata.BindNewPipeAndPassReceiver());
metadata->SetPID(base::GetCurrentProcId());
BrowserContextServiceManagerConnectionHolder* connection_holder =
new BrowserContextServiceManagerConnectionHolder(
std::move(service_receiver));
browser_context->SetUserData(kServiceManagerConnection,
base::WrapUnique(connection_holder));
ServiceManagerConnection* connection =
connection_holder->service_manager_connection();
connection->Start();
}
}
// static
const base::Token& BrowserContext::GetServiceInstanceGroupFor(
BrowserContext* browser_context) {
ServiceInstanceGroupHolder* holder = static_cast<ServiceInstanceGroupHolder*>(
browser_context->GetUserData(kServiceInstanceGroup));
CHECK(holder) << "Attempting to get the instance group for a BrowserContext "
<< "that was never Initialized().";
return holder->instance_group();
}
// static
BrowserContext* BrowserContext::GetBrowserContextForServiceInstanceGroup(
const base::Token& instance_group) {
auto it = GetTokenToContextMap().find(instance_group);
return it != GetTokenToContextMap().end() ? it->second : nullptr;
}
// static
service_manager::Connector* BrowserContext::GetConnectorFor(
BrowserContext* browser_context) {
ServiceManagerConnection* connection =
GetServiceManagerConnectionFor(browser_context);
return connection ? connection->GetConnector() : nullptr;
}
// static
ServiceManagerConnection* BrowserContext::GetServiceManagerConnectionFor(
BrowserContext* browser_context) {
BrowserContextServiceManagerConnectionHolder* connection_holder =
static_cast<BrowserContextServiceManagerConnectionHolder*>(
browser_context->GetUserData(kServiceManagerConnection));
return connection_holder ? connection_holder->service_manager_connection()
: nullptr;
}
BrowserContext::BrowserContext()
: unique_id_(base::UnguessableToken::Create().ToString()) {}
BrowserContext::~BrowserContext() {
CHECK(GetUserData(kServiceInstanceGroup))
<< "Attempting to destroy a BrowserContext that never called "
<< "Initialize()";
DCHECK(!GetUserData(kStoragePartitionMapKeyName))
<< "StoragePartitionMap is not shut down properly";
if (!was_notify_will_be_destroyed_called_) {
NOTREACHED();
base::debug::DumpWithoutCrashing();
}
RemoveBrowserContextFromInstanceGroupMap(this);
if (GetUserData(kDownloadManagerKeyName))
GetDownloadManager(this)->Shutdown();
}
void BrowserContext::ShutdownStoragePartitions() {
// The BackgroundSyncScheduler keeps raw pointers to partitions; clear it
// first.
if (GetUserData(kBackgroundSyncSchedulerKey))
RemoveUserData(kBackgroundSyncSchedulerKey);
if (GetUserData(kStoragePartitionMapKeyName))
RemoveUserData(kStoragePartitionMapKeyName);
}
std::string BrowserContext::GetMediaDeviceIDSalt() {
return unique_id_;
}
// static
std::string BrowserContext::CreateRandomMediaDeviceIDSalt() {
return base::UnguessableToken::Create().ToString();
}
const std::string& BrowserContext::UniqueId() {
return unique_id_;
}
void BrowserContext::BindNavigableContentsFactory(
mojo::PendingReceiver<content::mojom::NavigableContentsFactory> receiver) {
auto* service_holder =
static_cast<ContentServiceHolder*>(GetUserData(kContentServiceKey));
if (!service_holder) {
auto new_holder = std::make_unique<ContentServiceHolder>(this);
service_holder = new_holder.get();
SetUserData(kContentServiceKey, std::move(new_holder));
}
service_holder->service().BindNavigableContentsFactory(std::move(receiver));
}
media::VideoDecodePerfHistory* BrowserContext::GetVideoDecodePerfHistory() {
media::VideoDecodePerfHistory* decode_history =
static_cast<media::VideoDecodePerfHistory*>(
GetUserData(kVideoDecodePerfHistoryId));
// Lazily created. Note, this does not trigger loading the DB from disk. That
// occurs later upon first VideoDecodePerfHistory API request that requires DB
// access. DB operations will not block the UI thread.
if (!decode_history) {
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(this)->GetProtoDatabaseProvider();
stats_db = media::VideoDecodeStatsDBImpl::Create(
GetPath().Append(FILE_PATH_LITERAL("VideoDecodeStats")), db_provider);
}
auto new_decode_history = std::make_unique<media::VideoDecodePerfHistory>(
std::move(stats_db), BrowserFeatureProvider::GetFactoryCB());
decode_history = new_decode_history.get();
SetUserData(kVideoDecodePerfHistoryId, std::move(new_decode_history));
}
return decode_history;
}
media::learning::LearningSession* BrowserContext::GetLearningSession() {
media::learning::LearningSession* learning_session =
static_cast<media::learning::LearningSession*>(
GetUserData(kLearningSession));
if (!learning_session) {
auto new_learning_session =
std::make_unique<media::learning::LearningSessionImpl>(
base::SequencedTaskRunnerHandle::Get());
// Register all the LearningTasks.
auto cb = base::BindRepeating(
[](media::learning::LearningSessionImpl* session,
const media::learning::LearningTask& task) {
session->RegisterTask(task);
},
new_learning_session.get());
media::learning::MediaLearningTasks::Register(std::move(cb));
learning_session = new_learning_session.get();
SetUserData(kLearningSession, std::move(new_learning_session));
}
return learning_session;
}
download::InProgressDownloadManager*
BrowserContext::RetriveInProgressDownloadManager() {
return nullptr;
}
void BrowserContext::SetCorsOriginAccessListForOrigin(
const url::Origin& source_origin,
std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
std::vector<network::mojom::CorsOriginPatternPtr> block_patterns,
base::OnceClosure closure) {
NOTREACHED() << "Sub-classes should implement this method to communicate "
"with NetworkService to bypass CORS checks.";
}
SharedCorsOriginAccessList* BrowserContext::GetSharedCorsOriginAccessList() {
// Need to return a valid instance regardless of CORS bypass supports.
static const base::NoDestructor<scoped_refptr<SharedCorsOriginAccessList>>
empty_list(SharedCorsOriginAccessList::Create());
return empty_list->get();
}
bool BrowserContext::ShouldEnableOutOfBlinkCors() {
return base::FeatureList::IsEnabled(network::features::kOutOfBlinkCors);
}
NativeFileSystemPermissionContext*
BrowserContext::GetNativeFileSystemPermissionContext() {
return nullptr;
}
ContentIndexProvider* BrowserContext::GetContentIndexProvider() {
return nullptr;
}
bool BrowserContext::CanUseDiskWhenOffTheRecord() {
return false;
}
} // namespace content