Files
cef/libcef/browser/request_context_impl.cc
Marshall Greenblatt 48fc0bd220 Make CefBrowserContext an abstract base class (see issue #2969)
Existing CefBrowserContext functionality is now split between
CefBrowserContext and AlloyBrowserContext. Runtime implementations of
CefBrowserContext will provide access to the content::BrowserContext and
Profile types via different inheritance paths. For example, the Alloy
runtime uses ChromeProfileAlloy and the Chrome runtime uses ProfileImpl.

This change also renames CefResourceContext to CefIOThreadState to more
accurately represent its purpose as it no longer needs to extend
content::ResourceContext.
2020-07-01 15:35:07 -04:00

791 lines
25 KiB
C++

// Copyright (c) 2013 The Chromium Embedded Framework 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 "libcef/browser/request_context_impl.h"
#include "libcef/browser/browser_context.h"
#include "libcef/browser/context.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/app_manager.h"
#include "libcef/common/task_runner_impl.h"
#include "libcef/common/values_impl.h"
#include "libcef/features/runtime_checks.h"
#include "base/atomic_sequence_num.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/profiles/profile.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/ssl_host_state_delegate.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/cpp/resolve_host_client_base.h"
#include "services/network/public/mojom/network_context.mojom.h"
using content::BrowserThread;
namespace {
base::AtomicSequenceNumber g_next_id;
const char* GetTypeString(base::Value::Type type) {
switch (type) {
case base::Value::Type::NONE:
return "NULL";
case base::Value::Type::BOOLEAN:
return "BOOLEAN";
case base::Value::Type::INTEGER:
return "INTEGER";
case base::Value::Type::DOUBLE:
return "DOUBLE";
case base::Value::Type::STRING:
return "STRING";
case base::Value::Type::BINARY:
return "BINARY";
case base::Value::Type::DICTIONARY:
return "DICTIONARY";
case base::Value::Type::LIST:
return "LIST";
case base::Value::Type::DEAD:
return "DEAD";
}
NOTREACHED();
return "UNKNOWN";
}
// Helper for HostResolver::Resolve.
struct ResolveHostHelperOld {
explicit ResolveHostHelperOld(CefRefPtr<CefResolveCallback> callback)
: callback_(callback) {}
void OnResolveCompleted(int result) {
std::vector<CefString> resolved_ips;
base::Optional<net::AddressList> maybe_address_list =
request_->GetAddressResults();
if (maybe_address_list) {
net::AddressList::const_iterator iter = maybe_address_list->begin();
for (; iter != maybe_address_list->end(); ++iter)
resolved_ips.push_back(iter->ToStringWithoutPort());
}
CEF_POST_TASK(
CEF_UIT,
base::Bind(&CefResolveCallback::OnResolveCompleted, callback_,
static_cast<cef_errorcode_t>(result), resolved_ips));
delete this;
}
CefRefPtr<CefResolveCallback> callback_;
std::unique_ptr<net::HostResolver::ResolveHostRequest> request_;
};
class ResolveHostHelper : public network::ResolveHostClientBase {
public:
explicit ResolveHostHelper(CefRefPtr<CefResolveCallback> callback)
: callback_(callback), receiver_(this) {}
void Start(CefBrowserContext* browser_context, const CefString& origin) {
CEF_REQUIRE_UIT();
browser_context->GetNetworkContext()->CreateHostResolver(
base::nullopt, host_resolver_.BindNewPipeAndPassReceiver());
host_resolver_.set_disconnect_handler(base::BindOnce(
&ResolveHostHelper::OnComplete, base::Unretained(this), net::ERR_FAILED,
net::ResolveErrorInfo(net::ERR_FAILED), base::nullopt));
host_resolver_->ResolveHost(
net::HostPortPair::FromURL(GURL(origin.ToString())),
net::NetworkIsolationKey::CreateTransient(), nullptr,
receiver_.BindNewPipeAndPassRemote());
}
private:
void OnComplete(
int32_t result,
const ::net::ResolveErrorInfo& resolve_error_info,
const base::Optional<net::AddressList>& resolved_addresses) override {
CEF_REQUIRE_UIT();
host_resolver_.reset();
receiver_.reset();
std::vector<CefString> resolved_ips;
if (result == net::OK) {
DCHECK(resolved_addresses && !resolved_addresses->empty());
for (const auto& value : resolved_addresses.value()) {
resolved_ips.push_back(value.ToStringWithoutPort());
}
}
callback_->OnResolveCompleted(static_cast<cef_errorcode_t>(result),
resolved_ips);
delete this;
}
CefRefPtr<CefResolveCallback> callback_;
mojo::Remote<network::mojom::HostResolver> host_resolver_;
mojo::Receiver<network::mojom::ResolveHostClient> receiver_;
DISALLOW_COPY_AND_ASSIGN(ResolveHostHelper);
};
} // namespace
// CefBrowserContext
// static
CefRefPtr<CefRequestContext> CefRequestContext::GetGlobalContext() {
// Verify that the context is in a valid state.
if (!CONTEXT_STATE_VALID()) {
NOTREACHED() << "context not valid";
return nullptr;
}
CefRequestContextImpl::Config config;
config.is_global = true;
return CefRequestContextImpl::GetOrCreateRequestContext(config);
}
// static
CefRefPtr<CefRequestContext> CefRequestContext::CreateContext(
const CefRequestContextSettings& settings,
CefRefPtr<CefRequestContextHandler> handler) {
// Verify that the context is in a valid state.
if (!CONTEXT_STATE_VALID()) {
NOTREACHED() << "context not valid";
return nullptr;
}
CefRequestContextImpl::Config config;
config.settings = settings;
config.handler = handler;
config.unique_id = g_next_id.GetNext();
return CefRequestContextImpl::GetOrCreateRequestContext(config);
}
// static
CefRefPtr<CefRequestContext> CefRequestContext::CreateContext(
CefRefPtr<CefRequestContext> other,
CefRefPtr<CefRequestContextHandler> handler) {
// Verify that the context is in a valid state.
if (!CONTEXT_STATE_VALID()) {
NOTREACHED() << "context not valid";
return nullptr;
}
if (!other.get())
return nullptr;
CefRequestContextImpl::Config config;
config.other = static_cast<CefRequestContextImpl*>(other.get());
config.handler = handler;
config.unique_id = g_next_id.GetNext();
return CefRequestContextImpl::GetOrCreateRequestContext(config);
}
// CefRequestContextImpl
CefRequestContextImpl::~CefRequestContextImpl() {
CEF_REQUIRE_UIT();
if (browser_context_) {
// May result in |browser_context_| being deleted if no other
// CefRequestContextImpl are referencing it.
browser_context_->RemoveCefRequestContext(this);
}
}
// static
CefRefPtr<CefRequestContextImpl>
CefRequestContextImpl::CreateGlobalRequestContext(
const CefRequestContextSettings& settings) {
// Create and initialize the global context immediately.
Config config;
config.is_global = true;
config.settings = settings;
CefRefPtr<CefRequestContextImpl> impl = new CefRequestContextImpl(config);
impl->Initialize();
return impl;
}
// static
CefRefPtr<CefRequestContextImpl>
CefRequestContextImpl::GetOrCreateForRequestContext(
CefRefPtr<CefRequestContext> request_context) {
if (request_context.get()) {
// Use the context from the provided CefRequestContext.
return static_cast<CefRequestContextImpl*>(request_context.get());
}
// Use the global context.
Config config;
config.is_global = true;
return CefRequestContextImpl::GetOrCreateRequestContext(config);
}
CefBrowserContext* CefRequestContextImpl::GetBrowserContext() {
EnsureBrowserContext();
return browser_context();
}
void CefRequestContextImpl::GetBrowserContext(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
const BrowserContextCallback& callback) {
if (!task_runner.get())
task_runner = CefTaskRunnerImpl::GetCurrentTaskRunner();
GetBrowserContextOnUIThread(task_runner, callback);
}
bool CefRequestContextImpl::IsSame(CefRefPtr<CefRequestContext> other) {
CefRequestContextImpl* other_impl =
static_cast<CefRequestContextImpl*>(other.get());
if (!other_impl)
return false;
// Compare whether both are the global context.
if (config_.is_global && other_impl->config_.is_global)
return true;
// Compare CefBrowserContext pointers if one has been associated.
if (browser_context() && other_impl->browser_context()) {
return (browser_context() == other_impl->browser_context());
} else if (browser_context() || other_impl->browser_context()) {
return false;
}
// Otherwise compare unique IDs.
return (config_.unique_id == other_impl->config_.unique_id);
}
bool CefRequestContextImpl::IsSharingWith(CefRefPtr<CefRequestContext> other) {
CefRequestContextImpl* other_impl =
static_cast<CefRequestContextImpl*>(other.get());
if (!other_impl)
return false;
if (IsSame(other))
return true;
CefRefPtr<CefRequestContext> pending_other = config_.other;
if (pending_other.get()) {
// This object is not initialized but we know what context this object will
// share with. Compare to that other context instead.
return pending_other->IsSharingWith(other);
}
pending_other = other_impl->config_.other;
if (pending_other.get()) {
// The other object is not initialized but we know what context that object
// will share with. Compare to that other context instead.
return pending_other->IsSharingWith(this);
}
// This or the other object is not initialized. Compare the cache path values.
// If both are non-empty and the same then they'll share the same storage.
if (config_.settings.cache_path.length > 0 &&
other_impl->config_.settings.cache_path.length > 0) {
return (
base::FilePath(CefString(&config_.settings.cache_path)) ==
base::FilePath(CefString(&other_impl->config_.settings.cache_path)));
}
return false;
}
bool CefRequestContextImpl::IsGlobal() {
return config_.is_global;
}
CefRefPtr<CefRequestContextHandler> CefRequestContextImpl::GetHandler() {
return config_.handler;
}
CefString CefRequestContextImpl::GetCachePath() {
return CefString(&config_.settings.cache_path);
}
CefRefPtr<CefCookieManager> CefRequestContextImpl::GetCookieManager(
CefRefPtr<CefCompletionCallback> callback) {
CefRefPtr<CefCookieManagerImpl> cookie_manager = new CefCookieManagerImpl();
InitializeCookieManagerOnUIThread(cookie_manager, callback);
return cookie_manager.get();
}
bool CefRequestContextImpl::RegisterSchemeHandlerFactory(
const CefString& scheme_name,
const CefString& domain_name,
CefRefPtr<CefSchemeHandlerFactory> factory) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT,
base::BindOnce(
base::IgnoreResult(
&CefRequestContextImpl::RegisterSchemeHandlerFactory),
this, scheme_name, domain_name, factory));
return true;
}
// Make sure the browser context exists.
EnsureBrowserContext();
browser_context()->RegisterSchemeHandlerFactory(scheme_name, domain_name,
factory);
return true;
}
bool CefRequestContextImpl::ClearSchemeHandlerFactories() {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(
CEF_UIT,
base::BindOnce(base::IgnoreResult(
&CefRequestContextImpl::ClearSchemeHandlerFactories),
this));
return true;
}
// Make sure the browser context exists.
EnsureBrowserContext();
browser_context()->ClearSchemeHandlerFactories();
return true;
}
void CefRequestContextImpl::PurgePluginListCache(bool reload_pages) {
GetBrowserContext(
base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
base::Bind(&CefRequestContextImpl::PurgePluginListCacheInternal, this,
reload_pages));
}
bool CefRequestContextImpl::HasPreference(const CefString& name) {
// Verify that this method is being called on the UI thread.
if (!CEF_CURRENTLY_ON_UIT()) {
NOTREACHED() << "called on invalid thread";
return false;
}
// Make sure the browser context exists.
EnsureBrowserContext();
PrefService* pref_service = browser_context()->AsProfile()->GetPrefs();
return (pref_service->FindPreference(name) != nullptr);
}
CefRefPtr<CefValue> CefRequestContextImpl::GetPreference(
const CefString& name) {
// Verify that this method is being called on the UI thread.
if (!CEF_CURRENTLY_ON_UIT()) {
NOTREACHED() << "called on invalid thread";
return nullptr;
}
// Make sure the browser context exists.
EnsureBrowserContext();
PrefService* pref_service = browser_context()->AsProfile()->GetPrefs();
const PrefService::Preference* pref = pref_service->FindPreference(name);
if (!pref)
return nullptr;
return new CefValueImpl(pref->GetValue()->DeepCopy());
}
CefRefPtr<CefDictionaryValue> CefRequestContextImpl::GetAllPreferences(
bool include_defaults) {
// Verify that this method is being called on the UI thread.
if (!CEF_CURRENTLY_ON_UIT()) {
NOTREACHED() << "called on invalid thread";
return nullptr;
}
// Make sure the browser context exists.
EnsureBrowserContext();
PrefService* pref_service = browser_context()->AsProfile()->GetPrefs();
std::unique_ptr<base::DictionaryValue> values =
pref_service->GetPreferenceValues(include_defaults
? PrefService::INCLUDE_DEFAULTS
: PrefService::EXCLUDE_DEFAULTS);
// CefDictionaryValueImpl takes ownership of |values|.
return new CefDictionaryValueImpl(values.release(), true, false);
}
bool CefRequestContextImpl::CanSetPreference(const CefString& name) {
// Verify that this method is being called on the UI thread.
if (!CEF_CURRENTLY_ON_UIT()) {
NOTREACHED() << "called on invalid thread";
return false;
}
// Make sure the browser context exists.
EnsureBrowserContext();
PrefService* pref_service = browser_context()->AsProfile()->GetPrefs();
const PrefService::Preference* pref = pref_service->FindPreference(name);
return (pref && pref->IsUserModifiable());
}
bool CefRequestContextImpl::SetPreference(const CefString& name,
CefRefPtr<CefValue> value,
CefString& error) {
// Verify that this method is being called on the UI thread.
if (!CEF_CURRENTLY_ON_UIT()) {
NOTREACHED() << "called on invalid thread";
return false;
}
// Make sure the browser context exists.
EnsureBrowserContext();
PrefService* pref_service = browser_context()->AsProfile()->GetPrefs();
// The below validation logic should match PrefService::SetUserPrefValue.
const PrefService::Preference* pref = pref_service->FindPreference(name);
if (!pref) {
error = "Trying to modify an unregistered preference";
return false;
}
if (!pref->IsUserModifiable()) {
error = "Trying to modify a preference that is not user modifiable";
return false;
}
if (!value.get()) {
// Reset the preference to its default value.
pref_service->ClearPref(name);
return true;
}
if (!value->IsValid()) {
error = "A valid value is required";
return false;
}
CefValueImpl* impl = static_cast<CefValueImpl*>(value.get());
CefValueImpl::ScopedLockedValue scoped_locked_value(impl);
base::Value* impl_value = impl->GetValueUnsafe();
if (pref->GetType() != impl_value->type()) {
error = base::StringPrintf(
"Trying to set a preference of type %s to value of type %s",
GetTypeString(pref->GetType()), GetTypeString(impl_value->type()));
return false;
}
// PrefService will make a DeepCopy of |impl_value|.
pref_service->Set(name, *impl_value);
return true;
}
void CefRequestContextImpl::ClearCertificateExceptions(
CefRefPtr<CefCompletionCallback> callback) {
GetBrowserContext(
base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
base::Bind(&CefRequestContextImpl::ClearCertificateExceptionsInternal,
this, callback));
}
void CefRequestContextImpl::ClearHttpAuthCredentials(
CefRefPtr<CefCompletionCallback> callback) {
GetBrowserContext(
base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
base::Bind(&CefRequestContextImpl::ClearHttpAuthCredentialsInternal, this,
callback));
}
void CefRequestContextImpl::CloseAllConnections(
CefRefPtr<CefCompletionCallback> callback) {
GetBrowserContext(
base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
base::Bind(&CefRequestContextImpl::CloseAllConnectionsInternal, this,
callback));
}
void CefRequestContextImpl::ResolveHost(
const CefString& origin,
CefRefPtr<CefResolveCallback> callback) {
GetBrowserContext(base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
base::Bind(&CefRequestContextImpl::ResolveHostInternal,
this, origin, callback));
}
void CefRequestContextImpl::LoadExtension(
const CefString& root_directory,
CefRefPtr<CefDictionaryValue> manifest,
CefRefPtr<CefExtensionHandler> handler) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT,
base::BindOnce(&CefRequestContextImpl::LoadExtension, this,
root_directory, manifest, handler));
return;
}
// Make sure the browser context exists.
EnsureBrowserContext();
browser_context()->LoadExtension(root_directory, manifest, handler, this);
}
bool CefRequestContextImpl::DidLoadExtension(const CefString& extension_id) {
CefRefPtr<CefExtension> extension = GetExtension(extension_id);
// GetLoaderContext() will return NULL for internal extensions.
return extension && IsSame(extension->GetLoaderContext());
}
bool CefRequestContextImpl::HasExtension(const CefString& extension_id) {
return !!GetExtension(extension_id);
}
bool CefRequestContextImpl::GetExtensions(
std::vector<CefString>& extension_ids) {
extension_ids.clear();
if (!CEF_CURRENTLY_ON_UIT()) {
NOTREACHED() << "called on invalid thread";
return false;
}
// Make sure the browser context exists.
EnsureBrowserContext();
return browser_context()->GetExtensions(extension_ids);
}
CefRefPtr<CefExtension> CefRequestContextImpl::GetExtension(
const CefString& extension_id) {
if (!CEF_CURRENTLY_ON_UIT()) {
NOTREACHED() << "called on invalid thread";
return nullptr;
}
// Make sure the browser context exists.
EnsureBrowserContext();
return browser_context()->GetExtension(extension_id);
}
CefRefPtr<CefMediaRouter> CefRequestContextImpl::GetMediaRouter() {
CefRefPtr<CefMediaRouterImpl> media_router = new CefMediaRouterImpl();
InitializeMediaRouterOnUIThread(media_router);
return media_router.get();
}
void CefRequestContextImpl::OnRenderFrameCreated(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
bool is_main_frame,
bool is_guest_view) {
browser_context_->OnRenderFrameCreated(this, render_process_id,
render_frame_id, frame_tree_node_id,
is_main_frame, is_guest_view);
}
void CefRequestContextImpl::OnRenderFrameDeleted(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
bool is_main_frame,
bool is_guest_view) {
browser_context_->OnRenderFrameDeleted(this, render_process_id,
render_frame_id, frame_tree_node_id,
is_main_frame, is_guest_view);
}
// static
CefRefPtr<CefRequestContextImpl>
CefRequestContextImpl::GetOrCreateRequestContext(const Config& config) {
// TODO(chrome-runtime): Add support for this method.
REQUIRE_ALLOY_RUNTIME();
if (config.is_global ||
(config.other && config.other->IsGlobal() && !config.handler)) {
// Return the singleton global context.
return static_cast<CefRequestContextImpl*>(
CefAppManager::Get()->GetGlobalRequestContext().get());
}
// The new context will be initialized later by EnsureBrowserContext().
return new CefRequestContextImpl(config);
}
CefRequestContextImpl::CefRequestContextImpl(
const CefRequestContextImpl::Config& config)
: config_(config) {}
void CefRequestContextImpl::Initialize() {
CEF_REQUIRE_UIT();
DCHECK(!browser_context_);
if (config_.other) {
// Share storage with |config_.other|.
browser_context_ = config_.other->GetBrowserContext();
DCHECK(browser_context_);
}
if (!browser_context_) {
if (!config_.is_global) {
// User-specified settings need to be normalized.
CefContext::Get()->NormalizeRequestContextSettings(&config_.settings);
}
const base::FilePath& cache_path =
base::FilePath(CefString(&config_.settings.cache_path));
if (!cache_path.empty()) {
// Check if a CefBrowserContext is already globally registered for
// the specified cache path. If so then use it.
browser_context_ = CefBrowserContext::FromCachePath(cache_path);
}
}
if (!browser_context_) {
// Create a new CefBrowserContext instance. If the cache path is non-
// empty then this new instance will become the globally registered
// CefBrowserContext for that path. Otherwise, this new instance will
// be a completely isolated "incognito mode" context.
browser_context_ =
CefAppManager::Get()->CreateNewBrowserContext(config_.settings);
} else {
// Share the same settings as the existing context.
config_.settings = browser_context_->settings();
}
// We'll disassociate from |browser_context_| on destruction.
browser_context_->AddCefRequestContext(this);
if (config_.other) {
// Clear the reference to |config_.other| after setting
// |request_context_getter_|. This is the reverse order of checks in
// IsSharedWith().
config_.other = nullptr;
}
if (config_.handler)
config_.handler->OnRequestContextInitialized(this);
}
void CefRequestContextImpl::EnsureBrowserContext() {
CEF_REQUIRE_UIT();
if (!browser_context())
Initialize();
DCHECK(browser_context());
}
void CefRequestContextImpl::GetBrowserContextOnUIThread(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
const BrowserContextCallback& callback) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(
CEF_UIT, base::Bind(&CefRequestContextImpl::GetBrowserContextOnUIThread,
this, task_runner, callback));
return;
}
// Make sure the browser context exists.
EnsureBrowserContext();
if (task_runner->BelongsToCurrentThread()) {
// Execute the callback immediately.
callback.Run(browser_context());
} else {
// Execute the callback on the target thread.
task_runner->PostTask(FROM_HERE, base::Bind(callback, browser_context()));
}
}
void CefRequestContextImpl::PurgePluginListCacheInternal(
bool reload_pages,
CefBrowserContext* browser_context) {
CEF_REQUIRE_UIT();
browser_context->ClearPluginLoadDecision(-1);
content::PluginService::GetInstance()->PurgePluginListCache(
browser_context->AsBrowserContext(), false);
}
void CefRequestContextImpl::ClearCertificateExceptionsInternal(
CefRefPtr<CefCompletionCallback> callback,
CefBrowserContext* browser_context) {
CEF_REQUIRE_UIT();
content::SSLHostStateDelegate* ssl_delegate =
browser_context->AsBrowserContext()->GetSSLHostStateDelegate();
if (ssl_delegate)
ssl_delegate->Clear(base::Callback<bool(const std::string&)>());
if (callback) {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefCompletionCallback::OnComplete, callback));
}
}
void CefRequestContextImpl::ClearHttpAuthCredentialsInternal(
CefRefPtr<CefCompletionCallback> callback,
CefBrowserContext* browser_context) {
CEF_REQUIRE_UIT();
browser_context->GetNetworkContext()->ClearHttpAuthCache(
base::Time(), base::Bind(&CefCompletionCallback::OnComplete, callback));
}
void CefRequestContextImpl::CloseAllConnectionsInternal(
CefRefPtr<CefCompletionCallback> callback,
CefBrowserContext* browser_context) {
CEF_REQUIRE_UIT();
browser_context->GetNetworkContext()->CloseAllConnections(
base::Bind(&CefCompletionCallback::OnComplete, callback));
}
void CefRequestContextImpl::ResolveHostInternal(
const CefString& origin,
CefRefPtr<CefResolveCallback> callback,
CefBrowserContext* browser_context) {
CEF_REQUIRE_UIT();
// |helper| will be deleted in ResolveHostHelper::OnComplete().
ResolveHostHelper* helper = new ResolveHostHelper(callback);
helper->Start(browser_context, origin);
}
void CefRequestContextImpl::InitializeCookieManagerOnUIThread(
CefRefPtr<CefCookieManagerImpl> cookie_manager,
CefRefPtr<CefCompletionCallback> callback) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(
CEF_UIT,
base::Bind(&CefRequestContextImpl::InitializeCookieManagerOnUIThread,
this, cookie_manager, callback));
return;
}
auto browser_context = GetBrowserContext();
cookie_manager->Initialize(browser_context->getter(), callback);
}
void CefRequestContextImpl::InitializeMediaRouterOnUIThread(
CefRefPtr<CefMediaRouterImpl> media_router) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(
CEF_UIT,
base::Bind(&CefRequestContextImpl::InitializeMediaRouterOnUIThread,
this, media_router));
return;
}
auto browser_context = GetBrowserContext();
media_router->Initialize(browser_context->getter());
}
CefBrowserContext* CefRequestContextImpl::browser_context() const {
return browser_context_;
}