Simplify ownership of CefBrowserContext objects (issue #2083)

This commit is contained in:
Marshall Greenblatt 2017-02-14 17:27:19 -05:00
parent 43001c0a94
commit 897c0f01ed
21 changed files with 351 additions and 307 deletions

View File

@ -15,25 +15,14 @@
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_partition.h"
#if DCHECK_IS_ON()
base::AtomicRefCount CefBrowserContext::DebugObjCt = 0;
#endif
CefBrowserContext::CefBrowserContext(bool is_proxy) CefBrowserContext::CefBrowserContext(bool is_proxy)
: is_proxy_(is_proxy), : is_proxy_(is_proxy),
extension_system_(NULL) { extension_system_(NULL) {
#if DCHECK_IS_ON()
base::AtomicRefCountInc(&DebugObjCt);
#endif
} }
CefBrowserContext::~CefBrowserContext() { CefBrowserContext::~CefBrowserContext() {
// Should be cleared in Shutdown(). // Should be cleared in Shutdown().
DCHECK(!resource_context_.get()); DCHECK(!resource_context_.get());
#if DCHECK_IS_ON()
base::AtomicRefCountDec(&DebugObjCt);
#endif
} }
void CefBrowserContext::Initialize() { void CefBrowserContext::Initialize() {
@ -129,28 +118,27 @@ void CefBrowserContext::OnRenderFrameDeleted(int render_process_id,
int render_frame_id, int render_frame_id,
bool is_main_frame, bool is_main_frame,
bool is_guest_view) { bool is_guest_view) {
CEF_POST_TASK(CEF_IOT, CEF_REQUIRE_UIT();
base::Bind(&CefBrowserContext::RenderFrameDeletedOnIOThread, this,
render_process_id, render_frame_id, is_main_frame,
is_guest_view));
}
void CefBrowserContext::OnPurgePluginListCache() {
CEF_POST_TASK(CEF_IOT,
base::Bind(&CefBrowserContext::PurgePluginListCacheOnIOThread, this));
}
void CefBrowserContext::RenderFrameDeletedOnIOThread(int render_process_id,
int render_frame_id,
bool is_main_frame,
bool is_guest_view) {
if (resource_context_ && is_main_frame) { if (resource_context_ && is_main_frame) {
DCHECK_GE(render_process_id, 0); DCHECK_GE(render_process_id, 0);
resource_context_->ClearPluginLoadDecision(render_process_id); // Using base::Unretained() is safe because both this callback and possible
// deletion of |resource_context_| will execute on the IO thread, and this
// callback will be executed first.
CEF_POST_TASK(CEF_IOT,
base::Bind(&CefResourceContext::ClearPluginLoadDecision,
base::Unretained(resource_context_.get()),
render_process_id));
} }
} }
void CefBrowserContext::PurgePluginListCacheOnIOThread() { void CefBrowserContext::OnPurgePluginListCache() {
if (resource_context_) CEF_REQUIRE_UIT();
resource_context_->ClearPluginLoadDecision(-1); if (resource_context_) {
// Using base::Unretained() is safe because both this callback and possible
// deletion of |resource_context_| will execute on the IO thread, and this
// callback will be executed first.
CEF_POST_TASK(CEF_IOT,
base::Bind(&CefResourceContext::ClearPluginLoadDecision,
base::Unretained(resource_context_.get()), -1));
}
} }

View File

@ -33,12 +33,12 @@
// //
// BCI = CefBrowserContextImpl // BCI = CefBrowserContextImpl
// Entry point from WC when using an isolated RCI. Owns the RC and creates the // Entry point from WC when using an isolated RCI. Owns the RC and creates the
// SPI indirectly. Life span controlled by RCI and (for the global context) // SPI indirectly. Owned by CefBrowserMainParts for the global context or RCI
// CefBrowserMainParts. // for non-global contexts.
// //
// BCP = CefBrowserContextProxy // BCP = CefBrowserContextProxy
// Entry point from WC when using a custom RCI. Owns the RC and creates the // Entry point from WC when using a custom RCI. Owns the RC and creates the
// URCGP and SPP. Life span controlled by RCI. // URCGP and SPP. Owned by RCI.
// //
// SPI = content::StoragePartitionImpl // SPI = content::StoragePartitionImpl
// Owns storage-related objects like Quota, IndexedDB, Cache, etc. Created by // Owns storage-related objects like Quota, IndexedDB, Cache, etc. Created by
@ -83,29 +83,29 @@
// //
// Relationship diagram: // Relationship diagram:
// ref = reference (CefRefPtr/scoped_refptr) // ref = reference (CefRefPtr/scoped_refptr)
// own = ownership (scoped_ptr) // own = ownership (std::unique_ptr)
// ptr = raw pointer // ptr = raw pointer
// //
// CefBrowserMainParts----\ isolated cookie manager, etc. // CefBrowserMainParts----\ isolated cookie manager, etc.
// | \ ^ // | \ ^
// ref ref ref/own // own ref ref/own
// v v | // v v |
// /---> BCI -own-> SPI -ref-> URCGI --own-> URCI <-ptr-- CSP // /---> BCI -own-> SPI -ref-> URCGI --own-> URCI <-ptr-- CSP
// / ^ ^ ^ ^ // / ^ ^ ^ ^
// ptr ref ptr ref / // ptr ptr ptr ref /
// / | | | / // / | | | /
// BHI -own-> WC -ptr-> BCP -own-> SPP -ref-> URCGP -own-> URCP --ref-/ // BHI -own-> WC -ptr-> BCP -own-> SPP -ref-> URCGP -own-> URCP --ref-/
// //
// BHI -ref-> RCI -ref-> BCI/BCP -own-> RC -ref-> URCGI/URCGP // BHI -ref-> RCI -own-> BCI/BCP -own-> RC -ref-> URCGI/URCGP
// //
// //
// How shutdown works: // How shutdown works:
// 1. CefBrowserHostImpl is destroyed on any thread due to browser close, // 1. CefBrowserHostImpl is destroyed on any thread due to browser close,
// ref release, etc. // ref release, etc.
// 2. CefRequestContextImpl is destroyed on any thread due to // 2. CefRequestContextImpl is destroyed (possibly asynchronously) on the UI
// CefBrowserHostImpl destruction, ref release, etc. // thread due to CefBrowserHostImpl destruction, ref release, etc.
// 3. CefBrowserContext* is destroyed on the UI thread due to // 3. CefBrowserContext* is destroyed on the UI thread due to
// CefRequestContextImpl destruction (*Impl, *Proxy) or ref release in // CefRequestContextImpl destruction (*Impl, *Proxy) or deletion in
// CefBrowserMainParts::PostMainMessageLoopRun() (*Impl). // CefBrowserMainParts::PostMainMessageLoopRun() (*Impl).
// 4. CefResourceContext is destroyed asynchronously on the IO thread due to // 4. CefResourceContext is destroyed asynchronously on the IO thread due to
// CefBrowserContext* destruction. This cancels/destroys any pending // CefBrowserContext* destruction. This cancels/destroys any pending
@ -128,10 +128,7 @@ class CefExtensionSystem;
// Main entry point for configuring behavior on a per-browser basis. An instance // Main entry point for configuring behavior on a per-browser basis. An instance
// of this class is passed to WebContents::Create in CefBrowserHostImpl:: // of this class is passed to WebContents::Create in CefBrowserHostImpl::
// CreateInternal. Only accessed on the UI thread unless otherwise indicated. // CreateInternal. Only accessed on the UI thread unless otherwise indicated.
class CefBrowserContext class CefBrowserContext : public ChromeProfileStub {
: public ChromeProfileStub,
public base::RefCountedThreadSafe<
CefBrowserContext, content::BrowserThread::DeleteOnUIThread> {
public: public:
explicit CefBrowserContext(bool is_proxy); explicit CefBrowserContext(bool is_proxy);
@ -183,10 +180,9 @@ class CefBrowserContext
return extension_system_; return extension_system_;
} }
#if DCHECK_IS_ON() bool is_proxy() const {
// Simple tracking of allocated objects. return is_proxy_;
static base::AtomicRefCount DebugObjCt; // NOLINT(runtime/int) }
#endif
protected: protected:
~CefBrowserContext() override; ~CefBrowserContext() override;
@ -195,17 +191,6 @@ class CefBrowserContext
void Shutdown(); void Shutdown();
private: private:
// Only allow deletion via scoped_refptr().
friend struct content::BrowserThread::DeleteOnThread<
content::BrowserThread::UI>;
friend class base::DeleteHelper<CefBrowserContext>;
void RenderFrameDeletedOnIOThread(int render_process_id,
int render_frame_id,
bool is_main_frame,
bool is_guest_view);
void PurgePluginListCacheOnIOThread();
// True if this CefBrowserContext is a CefBrowserContextProxy. // True if this CefBrowserContext is a CefBrowserContextProxy.
const bool is_proxy_; const bool is_proxy_;

View File

@ -8,6 +8,7 @@
#include <utility> #include <utility>
#include "libcef/browser/browser_context_proxy.h" #include "libcef/browser/browser_context_proxy.h"
#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/context.h" #include "libcef/browser/context.h"
#include "libcef/browser/download_manager_delegate.h" #include "libcef/browser/download_manager_delegate.h"
#include "libcef/browser/extensions/extension_system.h" #include "libcef/browser/extensions/extension_system.h"
@ -85,9 +86,19 @@ class ImplManager {
const content::BrowserContext* context) { const content::BrowserContext* context) {
CEF_REQUIRE_UIT(); CEF_REQUIRE_UIT();
const CefBrowserContext* cef_context =
static_cast<const CefBrowserContext*>(context);
const CefBrowserContextImpl* cef_context_impl = nullptr;
if (cef_context->is_proxy()) {
cef_context_impl =
static_cast<const CefBrowserContextProxy*>(cef_context)->parent();
} else {
cef_context_impl = static_cast<const CefBrowserContextImpl*>(cef_context);
}
Vector::iterator it = all_.begin(); Vector::iterator it = all_.begin();
for (; it != all_.end(); ++it) { for (; it != all_.end(); ++it) {
if (*it == context || (*it)->HasProxy(context)) if (*it == cef_context_impl)
return *it; return *it;
} }
return NULL; return NULL;
@ -139,6 +150,7 @@ base::LazyInstance<ImplManager> g_manager = LAZY_INSTANCE_INITIALIZER;
class CefVisitedLinkListener : public visitedlink::VisitedLinkMaster::Listener { class CefVisitedLinkListener : public visitedlink::VisitedLinkMaster::Listener {
public: public:
CefVisitedLinkListener() { CefVisitedLinkListener() {
DCHECK(listener_map_.empty());
} }
void CreateListenerForContext(const CefBrowserContext* context) { void CreateListenerForContext(const CefBrowserContext* context) {
@ -196,11 +208,18 @@ CefBrowserContextImpl::CefBrowserContextImpl(
} }
CefBrowserContextImpl::~CefBrowserContextImpl() { CefBrowserContextImpl::~CefBrowserContextImpl() {
CEF_REQUIRE_UIT();
// No CefRequestContextImpl should be referencing this object any longer.
DCHECK_EQ(request_context_count_, 0);
// Unregister the context first to avoid re-entrancy during shutdown. // Unregister the context first to avoid re-entrancy during shutdown.
g_manager.Get().RemoveImpl(this, cache_path_); g_manager.Get().RemoveImpl(this, cache_path_);
Shutdown(); Shutdown();
visitedlink_listener_->RemoveListenerForContext(this);
// The FontFamilyCache references the ProxyService so delete it before the // The FontFamilyCache references the ProxyService so delete it before the
// ProxyService is deleted. // ProxyService is deleted.
SetUserData(&kFontFamilyCacheKey, NULL); SetUserData(&kFontFamilyCacheKey, NULL);
@ -281,48 +300,39 @@ void CefBrowserContextImpl::Initialize() {
void CefBrowserContextImpl::AddProxy(const CefBrowserContextProxy* proxy) { void CefBrowserContextImpl::AddProxy(const CefBrowserContextProxy* proxy) {
CEF_REQUIRE_UIT(); CEF_REQUIRE_UIT();
DCHECK(!HasProxy(proxy));
proxy_list_.push_back(proxy);
visitedlink_listener_->CreateListenerForContext(proxy); visitedlink_listener_->CreateListenerForContext(proxy);
} }
void CefBrowserContextImpl::RemoveProxy(const CefBrowserContextProxy* proxy) { void CefBrowserContextImpl::RemoveProxy(const CefBrowserContextProxy* proxy) {
CEF_REQUIRE_UIT(); CEF_REQUIRE_UIT();
visitedlink_listener_->RemoveListenerForContext(proxy); visitedlink_listener_->RemoveListenerForContext(proxy);
bool found = false;
ProxyList::iterator it = proxy_list_.begin();
for (; it != proxy_list_.end(); ++it) {
if (*it == proxy) {
proxy_list_.erase(it);
found = true;
break;
}
}
DCHECK(found);
} }
bool CefBrowserContextImpl::HasProxy( void CefBrowserContextImpl::AddRequestContext() {
const content::BrowserContext* context) const {
CEF_REQUIRE_UIT(); CEF_REQUIRE_UIT();
ProxyList::const_iterator it = proxy_list_.begin(); request_context_count_++;
for (; it != proxy_list_.end(); ++it) { }
if (*it == context)
return true; void CefBrowserContextImpl::RemoveRequestContext() {
CEF_REQUIRE_UIT();
request_context_count_--;
DCHECK_GE(request_context_count_, 0);
// Delete non-global contexts when the reference count reaches zero.
if (request_context_count_ == 0 &&
this != CefContentBrowserClient::Get()->browser_context()) {
delete this;
} }
return false;
} }
// static // static
scoped_refptr<CefBrowserContextImpl> CefBrowserContextImpl::GetForCachePath( CefBrowserContextImpl* CefBrowserContextImpl::GetForCachePath(
const base::FilePath& cache_path) { const base::FilePath& cache_path) {
return g_manager.Get().GetImplForPath(cache_path); return g_manager.Get().GetImplForPath(cache_path);
} }
// static // static
CefRefPtr<CefBrowserContextImpl> CefBrowserContextImpl::GetForContext( CefBrowserContextImpl* CefBrowserContextImpl::GetForContext(
content::BrowserContext* context) { content::BrowserContext* context) {
return g_manager.Get().GetImplForContext(context); return g_manager.Get().GetImplForContext(context);
} }

View File

@ -25,9 +25,9 @@ class VisitedLinkMaster;
} }
// Isolated BrowserContext implementation. Life span is controlled by // Isolated BrowserContext implementation. Life span is controlled by
// CefRequestContextImpl and (for the main context) CefBrowserMainParts. Only // CefBrowserMainParts for the global context and CefRequestContextImpl
// accessed on the UI thread unless otherwise indicated. See browser_context.h // for non-global contexts. Only accessed on the UI thread unless otherwise
// for an object relationship diagram. // indicated. See browser_context.h for an object relationship diagram.
class CefBrowserContextImpl : public CefBrowserContext, class CefBrowserContextImpl : public CefBrowserContext,
public visitedlink::VisitedLinkDelegate { public visitedlink::VisitedLinkDelegate {
public: public:
@ -35,11 +35,11 @@ class CefBrowserContextImpl : public CefBrowserContext,
// Returns the existing instance, if any, associated with the specified // Returns the existing instance, if any, associated with the specified
// |cache_path|. // |cache_path|.
static scoped_refptr<CefBrowserContextImpl> GetForCachePath( static CefBrowserContextImpl* GetForCachePath(
const base::FilePath& cache_path); const base::FilePath& cache_path);
// Returns the underlying CefBrowserContextImpl if any. // Returns the underlying CefBrowserContextImpl if any.
static CefRefPtr<CefBrowserContextImpl> GetForContext( static CefBrowserContextImpl* GetForContext(
content::BrowserContext* context); content::BrowserContext* context);
// Returns all existing CefBrowserContextImpl. // Returns all existing CefBrowserContextImpl.
@ -48,10 +48,14 @@ class CefBrowserContextImpl : public CefBrowserContext,
// Must be called immediately after this object is created. // Must be called immediately after this object is created.
void Initialize() override; void Initialize() override;
// Track associated proxy objects. // Track associated CefBrowserContextProxy objects.
void AddProxy(const CefBrowserContextProxy* proxy); void AddProxy(const CefBrowserContextProxy* proxy);
void RemoveProxy(const CefBrowserContextProxy* proxy); void RemoveProxy(const CefBrowserContextProxy* proxy);
bool HasProxy(const content::BrowserContext* context) const;
// Track associated CefRequestContextImpl objects. If this object is a non-
// global context then it will delete itself when the count reaches zero.
void AddRequestContext();
void RemoveRequestContext();
// BrowserContext methods. // BrowserContext methods.
base::FilePath GetPath() const override; base::FilePath GetPath() const override;
@ -98,10 +102,8 @@ class CefBrowserContextImpl : public CefBrowserContext,
} }
private: private:
// Only allow deletion via scoped_refptr(). // Allow deletion via std::unique_ptr().
friend struct content::BrowserThread::DeleteOnThread< friend std::default_delete<CefBrowserContextImpl>;
content::BrowserThread::UI>;
friend class base::DeleteHelper<CefBrowserContextImpl>;
~CefBrowserContextImpl() override; ~CefBrowserContextImpl() override;
@ -109,9 +111,8 @@ class CefBrowserContextImpl : public CefBrowserContext,
CefRequestContextSettings settings_; CefRequestContextSettings settings_;
base::FilePath cache_path_; base::FilePath cache_path_;
// Not owned by this class. // Number of CefRequestContextImpl objects referencing this object.
typedef std::vector<const CefBrowserContextProxy*> ProxyList; int request_context_count_ = 0;
ProxyList proxy_list_;
std::unique_ptr<PrefService> pref_service_; std::unique_ptr<PrefService> pref_service_;
std::unique_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_; std::unique_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_;

View File

@ -59,16 +59,18 @@ bool ShouldProxyUserData(const void* key) {
CefBrowserContextProxy::CefBrowserContextProxy( CefBrowserContextProxy::CefBrowserContextProxy(
CefRefPtr<CefRequestContextHandler> handler, CefRefPtr<CefRequestContextHandler> handler,
scoped_refptr<CefBrowserContextImpl> parent) CefBrowserContextImpl* parent)
: CefBrowserContext(true), : CefBrowserContext(true),
handler_(handler), handler_(handler),
parent_(parent) { parent_(parent) {
DCHECK(handler_.get()); DCHECK(handler_.get());
DCHECK(parent_.get()); DCHECK(parent_);
parent_->AddProxy(this); parent_->AddProxy(this);
} }
CefBrowserContextProxy::~CefBrowserContextProxy() { CefBrowserContextProxy::~CefBrowserContextProxy() {
CEF_REQUIRE_UIT();
Shutdown(); Shutdown();
parent_->RemoveProxy(this); parent_->RemoveProxy(this);

View File

@ -21,7 +21,7 @@ class CefStoragePartitionProxy;
class CefBrowserContextProxy : public CefBrowserContext { class CefBrowserContextProxy : public CefBrowserContext {
public: public:
CefBrowserContextProxy(CefRefPtr<CefRequestContextHandler> handler, CefBrowserContextProxy(CefRefPtr<CefRequestContextHandler> handler,
scoped_refptr<CefBrowserContextImpl> parent); CefBrowserContextImpl* parent);
// Must be called immediately after this object is created. // Must be called immediately after this object is created.
void Initialize() override; void Initialize() override;
@ -67,21 +67,19 @@ class CefBrowserContextProxy : public CefBrowserContext {
content::StoragePartition* GetOrCreateStoragePartitionProxy( content::StoragePartition* GetOrCreateStoragePartitionProxy(
content::StoragePartition* partition_impl); content::StoragePartition* partition_impl);
scoped_refptr<CefBrowserContextImpl> parent() const { CefBrowserContextImpl* parent() const {
return parent_; return parent_;
} }
private: private:
// Only allow deletion via scoped_refptr(). // Allow deletion via std::unique_ptr() only.
friend struct content::BrowserThread::DeleteOnThread< friend std::default_delete<CefBrowserContextProxy>;
content::BrowserThread::UI>;
friend class base::DeleteHelper<CefBrowserContextProxy>;
~CefBrowserContextProxy() override; ~CefBrowserContextProxy() override;
// Members initialized during construction are safe to access from any thread. // Members initialized during construction are safe to access from any thread.
CefRefPtr<CefRequestContextHandler> handler_; CefRefPtr<CefRequestContextHandler> handler_;
scoped_refptr<CefBrowserContextImpl> parent_; CefBrowserContextImpl* parent_; // Guaranteed to outlive this object.
std::unique_ptr<CefDownloadManagerDelegate> download_manager_delegate_; std::unique_ptr<CefDownloadManagerDelegate> download_manager_delegate_;
std::unique_ptr<CefStoragePartitionProxy> storage_partition_proxy_; std::unique_ptr<CefStoragePartitionProxy> storage_partition_proxy_;

View File

@ -281,10 +281,10 @@ CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::Create(
// Get or create the request context and browser context. // Get or create the request context and browser context.
CefRefPtr<CefRequestContextImpl> request_context_impl = CefRefPtr<CefRequestContextImpl> request_context_impl =
CefRequestContextImpl::GetForRequestContext( CefRequestContextImpl::GetOrCreateForRequestContext(
create_params.request_context); create_params.request_context);
DCHECK(request_context_impl); DCHECK(request_context_impl);
scoped_refptr<CefBrowserContext> browser_context = CefBrowserContext* browser_context =
request_context_impl->GetBrowserContext(); request_context_impl->GetBrowserContext();
DCHECK(browser_context); DCHECK(browser_context);
@ -298,8 +298,7 @@ CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::Create(
create_params.request_context = request_context_impl.get(); create_params.request_context = request_context_impl.get();
} }
content::WebContents::CreateParams wc_create_params( content::WebContents::CreateParams wc_create_params(browser_context);
browser_context.get());
if (platform_delegate->IsWindowless()) { if (platform_delegate->IsWindowless()) {
// Create the OSR view for the WebContents. // Create the OSR view for the WebContents.
@ -692,13 +691,13 @@ void CefBrowserHostImpl::StartDownload(const CefString& url) {
if (!web_contents()) if (!web_contents())
return; return;
scoped_refptr<CefBrowserContext> context = CefBrowserContext* context =
static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext()); static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext());
if (!context.get()) if (!context)
return; return;
content::DownloadManager* manager = content::DownloadManager* manager =
content::BrowserContext::GetDownloadManager(context.get()); content::BrowserContext::GetDownloadManager(context);
if (!manager) if (!manager)
return; return;
@ -2272,11 +2271,11 @@ void CefBrowserHostImpl::WebContentsCreated(
CefRefPtr<CefBrowserHostImpl> opener = GetBrowserForContents(source_contents); CefRefPtr<CefBrowserHostImpl> opener = GetBrowserForContents(source_contents);
DCHECK(opener.get()); DCHECK(opener.get());
scoped_refptr<CefBrowserContext> browser_context = CefBrowserContext* browser_context =
static_cast<CefBrowserContext*>(new_contents->GetBrowserContext()); static_cast<CefBrowserContext*>(new_contents->GetBrowserContext());
DCHECK(browser_context.get()); DCHECK(browser_context);
CefRefPtr<CefRequestContext> request_context = CefRefPtr<CefRequestContext> request_context =
CefRequestContextImpl::GetForBrowserContext(browser_context).get(); CefRequestContextImpl::CreateForBrowserContext(browser_context).get();
DCHECK(request_context.get()); DCHECK(request_context.get());
CefRefPtr<CefBrowserHostImpl> browser = CefBrowserHostImpl::CreateInternal( CefRefPtr<CefBrowserHostImpl> browser = CefBrowserHostImpl::CreateInternal(
@ -2406,7 +2405,7 @@ void CefBrowserHostImpl::RenderFrameDeleted(
if (web_contents()) { if (web_contents()) {
const bool is_main_frame = (render_frame_host->GetParent() == nullptr); const bool is_main_frame = (render_frame_host->GetParent() == nullptr);
scoped_refptr<CefBrowserContext> context = CefBrowserContext* context =
static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext()); static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext());
if (context) { if (context) {
context->OnRenderFrameDeleted(render_process_id, render_routing_id, context->OnRenderFrameDeleted(render_process_id, render_routing_id,
@ -2578,9 +2577,9 @@ void CefBrowserHostImpl::DidNavigateAnyFrame(
if (!web_contents()) if (!web_contents())
return; return;
scoped_refptr<CefBrowserContext> context = CefBrowserContext* context =
static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext()); static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext());
if (!context.get()) if (!context)
return; return;
context->AddVisitedURLs(params.redirects); context->AddVisitedURLs(params.redirects);

View File

@ -193,7 +193,7 @@ void CefBrowserMainParts::PreMainMessageLoopRun() {
CefContext::Get()->PopulateRequestContextSettings(&settings); CefContext::Get()->PopulateRequestContextSettings(&settings);
// Create the global BrowserContext. // Create the global BrowserContext.
global_browser_context_ = new CefBrowserContextImpl(settings); global_browser_context_.reset(new CefBrowserContextImpl(settings));
global_browser_context_->Initialize(); global_browser_context_->Initialize();
CefDevToolsManagerDelegate::StartHttpHandler(global_browser_context_.get()); CefDevToolsManagerDelegate::StartHttpHandler(global_browser_context_.get());
@ -212,7 +212,7 @@ void CefBrowserMainParts::PostMainMessageLoopRun() {
// NOTE: Destroy objects in reverse order of creation. // NOTE: Destroy objects in reverse order of creation.
CefDevToolsManagerDelegate::StopHttpHandler(); CefDevToolsManagerDelegate::StopHttpHandler();
global_browser_context_ = NULL; global_browser_context_.reset(nullptr);
if (extensions::ExtensionsEnabled()) { if (extensions::ExtensionsEnabled()) {
extensions::ExtensionsBrowserClient::Set(NULL); extensions::ExtensionsBrowserClient::Set(NULL);

View File

@ -6,7 +6,6 @@
#define CEF_LIBCEF_BROWSER_BROWSER_MAIN_H_ #define CEF_LIBCEF_BROWSER_BROWSER_MAIN_H_
#pragma once #pragma once
#include "libcef/browser/browser_context_impl.h"
#include "libcef/browser/net/url_request_context_getter_impl.h" #include "libcef/browser/net/url_request_context_getter_impl.h"
#include "base/macros.h" #include "base/macros.h"
@ -31,6 +30,7 @@ class ExtensionsBrowserClient;
class ExtensionsClient; class ExtensionsClient;
} }
class CefBrowserContextImpl;
class CefDevToolsDelegate; class CefDevToolsDelegate;
class CefBrowserMainParts : public content::BrowserMainParts { class CefBrowserMainParts : public content::BrowserMainParts {
@ -47,8 +47,8 @@ class CefBrowserMainParts : public content::BrowserMainParts {
void PostMainMessageLoopRun() override; void PostMainMessageLoopRun() override;
void PostDestroyThreads() override; void PostDestroyThreads() override;
scoped_refptr<CefBrowserContextImpl> browser_context() const { CefBrowserContextImpl* browser_context() const {
return global_browser_context_; return global_browser_context_.get();
} }
CefDevToolsDelegate* devtools_delegate() const { CefDevToolsDelegate* devtools_delegate() const {
return devtools_delegate_; return devtools_delegate_;
@ -59,7 +59,7 @@ class CefBrowserMainParts : public content::BrowserMainParts {
void PlatformInitialize(); void PlatformInitialize();
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
scoped_refptr<CefBrowserContextImpl> global_browser_context_; std::unique_ptr<CefBrowserContextImpl> global_browser_context_;
CefDevToolsDelegate* devtools_delegate_; // Deletes itself. CefDevToolsDelegate* devtools_delegate_; // Deletes itself.
std::unique_ptr<base::MessageLoop> message_loop_; std::unique_ptr<base::MessageLoop> message_loop_;

View File

@ -190,11 +190,11 @@ class CefBrowserURLRequest::Context
// Get or create the request context and browser context. // Get or create the request context and browser context.
CefRefPtr<CefRequestContextImpl> request_context_impl = CefRefPtr<CefRequestContextImpl> request_context_impl =
CefRequestContextImpl::GetForRequestContext(request_context_); CefRequestContextImpl::GetOrCreateForRequestContext(request_context_);
DCHECK(request_context_impl.get()); DCHECK(request_context_impl.get());
scoped_refptr<CefBrowserContext> browser_context = CefBrowserContext* browser_context =
request_context_impl->GetBrowserContext(); request_context_impl->GetBrowserContext();
DCHECK(browser_context.get()); DCHECK(browser_context);
if (!request_context_.get()) if (!request_context_.get())
request_context_ = request_context_impl.get(); request_context_ = request_context_impl.get();

View File

@ -360,7 +360,7 @@ ChromeBrowserProcessStub::GetPhysicalWebDataSource() {
content::BrowserContext* content::BrowserContext*
ChromeBrowserProcessStub::GetBrowserContextRedirectedInIncognito( ChromeBrowserProcessStub::GetBrowserContextRedirectedInIncognito(
content::BrowserContext* context) { content::BrowserContext* context) {
return CefBrowserContextImpl::GetForContext(context).get(); return CefBrowserContextImpl::GetForContext(context);
} }
content::BrowserContext* content::BrowserContext*

View File

@ -21,7 +21,7 @@ namespace {
// Return the main context for now since we don't currently have a good way to // Return the main context for now since we don't currently have a good way to
// determine that. // determine that.
CefBrowserContextImpl* GetActiveBrowserContext() { CefBrowserContextImpl* GetActiveBrowserContext() {
return CefContentBrowserClient::Get()->browser_context().get(); return CefContentBrowserClient::Get()->browser_context();
} }
} // namespace } // namespace
@ -35,7 +35,7 @@ ChromeProfileManagerStub::~ChromeProfileManagerStub() {
Profile* ChromeProfileManagerStub::GetProfile( Profile* ChromeProfileManagerStub::GetProfile(
const base::FilePath& profile_dir) { const base::FilePath& profile_dir) {
scoped_refptr<CefBrowserContextImpl> browser_context = CefBrowserContextImpl* browser_context =
CefBrowserContextImpl::GetForCachePath(profile_dir); CefBrowserContextImpl::GetForCachePath(profile_dir);
if (!browser_context) { if (!browser_context) {
// ProfileManager makes assumptions about profile directory paths that do // ProfileManager makes assumptions about profile directory paths that do
@ -46,7 +46,7 @@ Profile* ChromeProfileManagerStub::GetProfile(
// asking for. // asking for.
browser_context = GetActiveBrowserContext(); browser_context = GetActiveBrowserContext();
} }
return browser_context.get(); return browser_context;
} }
bool ChromeProfileManagerStub::IsValidProfile(const void* profile) { bool ChromeProfileManagerStub::IsValidProfile(const void* profile) {
@ -54,7 +54,7 @@ bool ChromeProfileManagerStub::IsValidProfile(const void* profile) {
return false; return false;
return !!CefBrowserContextImpl::GetForContext( return !!CefBrowserContextImpl::GetForContext(
reinterpret_cast<content::BrowserContext*>( reinterpret_cast<content::BrowserContext*>(
const_cast<void*>(profile))).get(); const_cast<void*>(profile)));
} }
Profile* ChromeProfileManagerStub::GetLastUsedProfile( Profile* ChromeProfileManagerStub::GetLastUsedProfile(

View File

@ -7,6 +7,7 @@
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include "libcef/browser/browser_context.h"
#include "libcef/browser/browser_info.h" #include "libcef/browser/browser_info.h"
#include "libcef/browser/browser_info_manager.h" #include "libcef/browser/browser_info_manager.h"
#include "libcef/browser/browser_host_impl.h" #include "libcef/browser/browser_host_impl.h"
@ -42,6 +43,7 @@
#include "base/json/json_reader.h" #include "base/json/json_reader.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "cef/grit/cef_resources.h" #include "cef/grit/cef_resources.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/spellchecker/spellcheck_message_filter.h" #include "chrome/browser/spellchecker/spellcheck_message_filter.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "components/navigation_interception/intercept_navigation_throttle.h" #include "components/navigation_interception/intercept_navigation_throttle.h"
@ -979,8 +981,7 @@ void CefContentBrowserClient::RegisterCustomScheme(const std::string& scheme) {
policy->RegisterWebSafeScheme(scheme); policy->RegisterWebSafeScheme(scheme);
} }
scoped_refptr<CefBrowserContextImpl> CefBrowserContextImpl* CefContentBrowserClient::browser_context() const {
CefContentBrowserClient::browser_context() const {
return browser_main_parts_->browser_context(); return browser_main_parts_->browser_context();
} }

View File

@ -10,7 +10,6 @@
#include <utility> #include <utility>
#include "include/cef_request_context_handler.h" #include "include/cef_request_context_handler.h"
#include "libcef/browser/browser_context_impl.h"
#include "libcef/browser/net/url_request_context_getter_impl.h" #include "libcef/browser/net/url_request_context_getter_impl.h"
#include "base/macros.h" #include "base/macros.h"
@ -20,6 +19,7 @@
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
class CefBrowserMainParts; class CefBrowserMainParts;
class CefBrowserContextImpl;
class CefDevToolsDelegate; class CefDevToolsDelegate;
class CefResourceDispatcherHostDelegate; class CefResourceDispatcherHostDelegate;
@ -28,6 +28,10 @@ class PluginServiceFilter;
class SiteInstance; class SiteInstance;
} }
namespace extensions {
class Extension;
}
class CefContentBrowserClient : public content::ContentBrowserClient { class CefContentBrowserClient : public content::ContentBrowserClient {
public: public:
CefContentBrowserClient(); CefContentBrowserClient();
@ -113,7 +117,7 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
// Perform browser process registration for the custom scheme. // Perform browser process registration for the custom scheme.
void RegisterCustomScheme(const std::string& scheme); void RegisterCustomScheme(const std::string& scheme);
scoped_refptr<CefBrowserContextImpl> browser_context() const; CefBrowserContextImpl* browser_context() const;
CefDevToolsDelegate* devtools_delegate() const; CefDevToolsDelegate* devtools_delegate() const;
private: private:

View File

@ -57,10 +57,10 @@ bool GetTabById(int tab_id,
if (!request_context) if (!request_context)
continue; continue;
CefRefPtr<CefRequestContextImpl> request_context_impl = CefRefPtr<CefRequestContextImpl> request_context_impl =
CefRequestContextImpl::GetForRequestContext(request_context); CefRequestContextImpl::GetOrCreateForRequestContext(request_context);
if (!request_context_impl) if (!request_context_impl)
continue; continue;
scoped_refptr<CefBrowserContext> browser_context = CefBrowserContext* browser_context =
request_context_impl->GetBrowserContext(); request_context_impl->GetBrowserContext();
if (!browser_context) if (!browser_context)
continue; continue;

View File

@ -44,7 +44,7 @@ CefExtensionsAPIClient::CreateGuestViewManagerDelegate(
// *Proxy object that has already been deleted. // *Proxy object that has already been deleted.
return base::WrapUnique( return base::WrapUnique(
new extensions::ExtensionsGuestViewManagerDelegate( new extensions::ExtensionsGuestViewManagerDelegate(
CefBrowserContextImpl::GetForContext(context).get())); CefBrowserContextImpl::GetForContext(context)));
} }
std::unique_ptr<MimeHandlerViewGuestDelegate> std::unique_ptr<MimeHandlerViewGuestDelegate>

View File

@ -64,8 +64,8 @@ bool CefExtensionsBrowserClient::IsSameContext(BrowserContext* first,
BrowserContext* second) { BrowserContext* second) {
// Returns true if |first| and |second| share the same underlying // Returns true if |first| and |second| share the same underlying
// CefBrowserContextImpl. // CefBrowserContextImpl.
return CefBrowserContextImpl::GetForContext(first).get() == return CefBrowserContextImpl::GetForContext(first) ==
CefBrowserContextImpl::GetForContext(second).get(); CefBrowserContextImpl::GetForContext(second);
} }
bool CefExtensionsBrowserClient::HasOffTheRecordContext( bool CefExtensionsBrowserClient::HasOffTheRecordContext(

View File

@ -5,6 +5,7 @@
#include "libcef/browser/extensions/mime_handler_view_guest_delegate.h" #include "libcef/browser/extensions/mime_handler_view_guest_delegate.h"
#include "libcef/browser/browser_context.h"
#include "libcef/browser/browser_host_impl.h" #include "libcef/browser/browser_host_impl.h"
#include "libcef/browser/browser_info.h" #include "libcef/browser/browser_info.h"
#include "libcef/browser/content_browser_client.h" #include "libcef/browser/content_browser_client.h"
@ -91,7 +92,7 @@ void CefMimeHandlerViewGuestDelegate::OnGuestDetached(
info->guest_render_id_manager()->remove_render_frame_id( info->guest_render_id_manager()->remove_render_frame_id(
render_process_id, render_frame_id); render_process_id, render_frame_id);
scoped_refptr<CefBrowserContext> context = CefBrowserContext* context =
static_cast<CefBrowserContext*>(web_contents->GetBrowserContext()); static_cast<CefBrowserContext*>(web_contents->GetBrowserContext());
if (context) { if (context) {
context->OnRenderFrameDeleted(render_process_id, render_frame_id, context->OnRenderFrameDeleted(render_process_id, render_frame_id,

View File

@ -64,7 +64,7 @@ struct ResolveHostHelper {
resolved_ips.push_back(iter->ToStringWithoutPort()); resolved_ips.push_back(iter->ToStringWithoutPort());
CEF_POST_TASK(CEF_UIT, CEF_POST_TASK(CEF_UIT,
base::Bind(&CefResolveCallback::OnResolveCompleted, callback_.get(), base::Bind(&CefResolveCallback::OnResolveCompleted, callback_,
static_cast<cef_errorcode_t>(result), resolved_ips)); static_cast<cef_errorcode_t>(result), resolved_ips));
delete this; delete this;
@ -88,8 +88,9 @@ CefRefPtr<CefRequestContext> CefRequestContext::GetGlobalContext() {
return NULL; return NULL;
} }
return CefRequestContextImpl::GetForBrowserContext( CefRequestContextImpl::Config config;
CefContentBrowserClient::Get()->browser_context()); config.is_global = true;
return new CefRequestContextImpl(config);
} }
// static // static
@ -102,7 +103,11 @@ CefRefPtr<CefRequestContext> CefRequestContext::CreateContext(
return NULL; return NULL;
} }
return new CefRequestContextImpl(settings, handler); CefRequestContextImpl::Config config;
config.settings = settings;
config.handler = handler;
config.unique_id = g_next_id.GetNext();
return new CefRequestContextImpl(config);
} }
// static // static
@ -118,18 +123,31 @@ CefRefPtr<CefRequestContext> CefRequestContext::CreateContext(
if (!other.get()) if (!other.get())
return NULL; return NULL;
return new CefRequestContextImpl( CefRequestContextImpl::Config config;
static_cast<CefRequestContextImpl*>(other.get()), handler); config.other = static_cast<CefRequestContextImpl*>(other.get());
config.handler = handler;
config.unique_id = g_next_id.GetNext();
return new CefRequestContextImpl(config);
} }
// CefBrowserContextImpl // CefRequestContextImpl
CefRequestContextImpl::~CefRequestContextImpl() { CefRequestContextImpl::~CefRequestContextImpl() {
// Delete the proxy first because it also references |browser_context_impl_|.
if (browser_context_proxy_)
browser_context_proxy_.reset(nullptr);
if (browser_context_impl_) {
// May result in |browser_context_impl_| being deleted if it's not the
// global context and no other CefRequestContextImpl are referencing it.
browser_context_impl_->RemoveRequestContext();
}
} }
// static // static
CefRefPtr<CefRequestContextImpl> CefRequestContextImpl::GetForRequestContext( CefRefPtr<CefRequestContextImpl>
CefRequestContextImpl::GetOrCreateForRequestContext(
CefRefPtr<CefRequestContext> request_context) { CefRefPtr<CefRequestContext> request_context) {
if (request_context.get()) { if (request_context.get()) {
// Use the context from the provided CefRequestContext. // Use the context from the provided CefRequestContext.
@ -137,87 +155,27 @@ CefRefPtr<CefRequestContextImpl> CefRequestContextImpl::GetForRequestContext(
} }
// Use the global context. // Use the global context.
scoped_refptr<CefBrowserContext> browser_context = CefRequestContextImpl::Config config;
CefContentBrowserClient::Get()->browser_context(); config.is_global = true;
return GetForBrowserContext(browser_context); return new CefRequestContextImpl(config);
} }
// static // static
CefRefPtr<CefRequestContextImpl> CefRequestContextImpl::GetForBrowserContext( CefRefPtr<CefRequestContextImpl> CefRequestContextImpl::CreateForBrowserContext(
scoped_refptr<CefBrowserContext> browser_context) { CefBrowserContext* browser_context) {
DCHECK(browser_context.get()); DCHECK(browser_context);
return new CefRequestContextImpl(browser_context); CefRequestContextImpl::Config config;
config.handler = browser_context->GetHandler();
CefRefPtr<CefRequestContextImpl> impl = new CefRequestContextImpl(config);
// Force immediate initialization because it's not safe to keep a raw pointer
// to |browser_context|.
impl->Initialize(browser_context);
return impl;
} }
scoped_refptr<CefBrowserContext> CefRequestContextImpl::GetBrowserContext() { CefBrowserContext* CefRequestContextImpl::GetBrowserContext() {
CEF_REQUIRE_UIT(); EnsureBrowserContext();
return browser_context();
if (!browser_context_) {
scoped_refptr<CefBrowserContextImpl> parent;
if (other_.get()) {
// Share storage with |other_|.
parent = CefBrowserContextImpl::GetForContext(
other_->GetBrowserContext().get());
}
if (!parent.get()) {
const base::FilePath& cache_path =
base::FilePath(CefString(&settings_.cache_path));
if (!cache_path.empty()) {
// Check if a CefBrowserContextImpl is already globally registered for
// the specified cache path. If so then use it.
parent = CefBrowserContextImpl::GetForCachePath(cache_path);
}
}
if (!parent.get()) {
// Create a new CefBrowserContextImpl instance. If the cache path is non-
// empty then this new instance will become the globally registered
// CefBrowserContextImpl for that path. Otherwise, this new instance will
// be a completely isolated "incongento mode" context.
parent = new CefBrowserContextImpl(settings_);
parent->Initialize();
}
// The parent's settings may be different. Force our settings to match the
// parent.
settings_ = parent->GetSettings();
if (handler_.get()) {
// Use a proxy that will execute handler callbacks where appropriate and
// otherwise forward all requests to the parent implementation.
browser_context_ = new CefBrowserContextProxy(handler_, parent);
browser_context_->Initialize();
} else {
// Use the parent implementation directly.
browser_context_ = parent;
}
request_context_impl_ = parent->request_context().get();
DCHECK(request_context_impl_);
if (handler_.get()) {
// Keep the handler alive until the associated request context is
// destroyed.
request_context_impl_->AddHandler(handler_);
}
}
if (!request_context_impl_) {
request_context_impl_ =
CefBrowserContextImpl::GetForContext(browser_context_.get())->
request_context().get();
DCHECK(request_context_impl_);
}
if (other_.get()) {
// Clear the reference to |other_| after setting |request_context_impl_|.
// This is the reverse order of checks in IsSharedWith().
other_ = NULL;
}
return browser_context_;
} }
void CefRequestContextImpl::GetBrowserContext( void CefRequestContextImpl::GetBrowserContext(
@ -235,8 +193,8 @@ void CefRequestContextImpl::GetRequestContextImpl(
task_runner = base::MessageLoop::current()->task_runner(); task_runner = base::MessageLoop::current()->task_runner();
if (request_context_impl_) { if (request_context_impl_) {
// The browser context already exists. // The browser context already exists.
DCHECK(browser_context_.get()); DCHECK(browser_context());
GetRequestContextImplOnIOThread(task_runner, callback, browser_context_); GetRequestContextImplOnIOThread(task_runner, callback, browser_context());
} else { } else {
// Need to initialize the browser context first. // Need to initialize the browser context first.
GetBrowserContextOnUIThread( GetBrowserContextOnUIThread(
@ -252,14 +210,28 @@ bool CefRequestContextImpl::IsSame(CefRefPtr<CefRequestContext> other) {
if (!other_impl) if (!other_impl)
return false; 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. // Compare CefBrowserContext pointers if one has been associated.
if (browser_context_ && other_impl->browser_context_) if (browser_context() && other_impl->browser_context()) {
return (browser_context_ == other_impl->browser_context_); if (browser_context()->is_proxy() &&
else if (browser_context_ || other_impl->browser_context_) other_impl->browser_context()->is_proxy()) {
CefBrowserContextProxy* proxy =
static_cast<CefBrowserContextProxy*>(browser_context());
CefBrowserContextProxy* other_proxy =
static_cast<CefBrowserContextProxy*>(other_impl->browser_context());
return (proxy->parent() == other_proxy->parent() &&
proxy->GetHandler() == other_proxy->GetHandler());
}
return (browser_context() == other_impl->browser_context());
} else if (browser_context() || other_impl->browser_context()) {
return false; return false;
}
// Otherwise compare unique IDs. // Otherwise compare unique IDs.
return (unique_id_ == other_impl->unique_id_); return (config_.unique_id == other_impl->config_.unique_id);
} }
bool CefRequestContextImpl::IsSharingWith(CefRefPtr<CefRequestContext> other) { bool CefRequestContextImpl::IsSharingWith(CefRefPtr<CefRequestContext> other) {
@ -271,14 +243,14 @@ bool CefRequestContextImpl::IsSharingWith(CefRefPtr<CefRequestContext> other) {
if (IsSame(other)) if (IsSame(other))
return true; return true;
CefRefPtr<CefRequestContext> pending_other = other_; CefRefPtr<CefRequestContext> pending_other = config_.other;
if (pending_other.get()) { if (pending_other.get()) {
// This object is not initialized but we know what context this object will // This object is not initialized but we know what context this object will
// share with. Compare to that other context instead. // share with. Compare to that other context instead.
return pending_other->IsSharingWith(other); return pending_other->IsSharingWith(other);
} }
pending_other = other_impl->other_; pending_other = other_impl->config_.other;
if (pending_other.get()) { if (pending_other.get()) {
// The other object is not initialized but we know what context that object // The other object is not initialized but we know what context that object
// will share with. Compare to that other context instead. // will share with. Compare to that other context instead.
@ -292,26 +264,26 @@ bool CefRequestContextImpl::IsSharingWith(CefRefPtr<CefRequestContext> other) {
// This or the other object is not initialized. Compare the cache path values. // 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 both are non-empty and the same then they'll share the same storage.
if (settings_.cache_path.length > 0 && if (config_.settings.cache_path.length > 0 &&
other_impl->settings_.cache_path.length > 0) { other_impl->config_.settings.cache_path.length > 0) {
return (base::FilePath(CefString(&settings_.cache_path)) == return (base::FilePath(CefString(&config_.settings.cache_path)) ==
base::FilePath(CefString(&other_impl->settings_.cache_path))); base::FilePath(
CefString(&other_impl->config_.settings.cache_path)));
} }
return false; return false;
} }
bool CefRequestContextImpl::IsGlobal() { bool CefRequestContextImpl::IsGlobal() {
return (browser_context_ == return config_.is_global;
CefContentBrowserClient::Get()->browser_context());
} }
CefRefPtr<CefRequestContextHandler> CefRequestContextImpl::GetHandler() { CefRefPtr<CefRequestContextHandler> CefRequestContextImpl::GetHandler() {
return handler_; return config_.handler;
} }
CefString CefRequestContextImpl::GetCachePath() { CefString CefRequestContextImpl::GetCachePath() {
return CefString(&settings_.cache_path); return CefString(&config_.settings.cache_path);
} }
CefRefPtr<CefCookieManager> CefRequestContextImpl::GetDefaultCookieManager( CefRefPtr<CefCookieManager> CefRequestContextImpl::GetDefaultCookieManager(
@ -357,7 +329,7 @@ bool CefRequestContextImpl::HasPreference(const CefString& name) {
// Make sure the browser context exists. // Make sure the browser context exists.
EnsureBrowserContext(); EnsureBrowserContext();
PrefService* pref_service = browser_context_->GetPrefs(); PrefService* pref_service = browser_context()->GetPrefs();
return (pref_service->FindPreference(name) != NULL); return (pref_service->FindPreference(name) != NULL);
} }
@ -372,7 +344,7 @@ CefRefPtr<CefValue> CefRequestContextImpl::GetPreference(
// Make sure the browser context exists. // Make sure the browser context exists.
EnsureBrowserContext(); EnsureBrowserContext();
PrefService* pref_service = browser_context_->GetPrefs(); PrefService* pref_service = browser_context()->GetPrefs();
const PrefService::Preference* pref = pref_service->FindPreference(name); const PrefService::Preference* pref = pref_service->FindPreference(name);
if (!pref) if (!pref)
return NULL; return NULL;
@ -390,7 +362,7 @@ CefRefPtr<CefDictionaryValue> CefRequestContextImpl::GetAllPreferences(
// Make sure the browser context exists. // Make sure the browser context exists.
EnsureBrowserContext(); EnsureBrowserContext();
PrefService* pref_service = browser_context_->GetPrefs(); PrefService* pref_service = browser_context()->GetPrefs();
std::unique_ptr<base::DictionaryValue> values; std::unique_ptr<base::DictionaryValue> values;
if (include_defaults) if (include_defaults)
@ -412,7 +384,7 @@ bool CefRequestContextImpl::CanSetPreference(const CefString& name) {
// Make sure the browser context exists. // Make sure the browser context exists.
EnsureBrowserContext(); EnsureBrowserContext();
PrefService* pref_service = browser_context_->GetPrefs(); PrefService* pref_service = browser_context()->GetPrefs();
const PrefService::Preference* pref = pref_service->FindPreference(name); const PrefService::Preference* pref = pref_service->FindPreference(name);
return (pref && pref->IsUserModifiable()); return (pref && pref->IsUserModifiable());
} }
@ -429,7 +401,7 @@ bool CefRequestContextImpl::SetPreference(const CefString& name,
// Make sure the browser context exists. // Make sure the browser context exists.
EnsureBrowserContext(); EnsureBrowserContext();
PrefService* pref_service = browser_context_->GetPrefs(); PrefService* pref_service = browser_context()->GetPrefs();
// The below validation logic should match PrefService::SetUserPrefValue. // The below validation logic should match PrefService::SetUserPrefValue.
@ -530,35 +502,91 @@ cef_errorcode_t CefRequestContextImpl::ResolveHostCached(
} }
CefRequestContextImpl::CefRequestContextImpl( CefRequestContextImpl::CefRequestContextImpl(
scoped_refptr<CefBrowserContext> browser_context) const CefRequestContextImpl::Config& config)
: browser_context_(browser_context), : config_(config) {
settings_(browser_context->GetSettings()),
handler_(browser_context->GetHandler()),
unique_id_(0),
request_context_impl_(NULL) {
} }
CefRequestContextImpl::CefRequestContextImpl( void CefRequestContextImpl::Initialize() {
const CefRequestContextSettings& settings, CefBrowserContext* other_browser_context = nullptr;
CefRefPtr<CefRequestContextHandler> handler) if (config_.is_global)
: settings_(settings), other_browser_context = CefContentBrowserClient::Get()->browser_context();
handler_(handler), else if (config_.other.get())
unique_id_(g_next_id.GetNext()), other_browser_context = config_.other->GetBrowserContext();
request_context_impl_(NULL) {
Initialize(other_browser_context);
if (config_.other.get()) {
// Clear the reference to |other_| after setting |request_context_impl_|.
// This is the reverse order of checks in IsSharedWith().
config_.other = NULL;
}
} }
CefRequestContextImpl::CefRequestContextImpl( void CefRequestContextImpl::Initialize(
CefRefPtr<CefRequestContextImpl> other, CefBrowserContext* other_browser_context) {
CefRefPtr<CefRequestContextHandler> handler) CEF_REQUIRE_UIT();
: other_(other),
handler_(handler), DCHECK(!browser_context_impl_);
unique_id_(g_next_id.GetNext()), DCHECK(!request_context_impl_);
request_context_impl_(NULL) {
if (other_browser_context) {
// Share storage with |other_browser_context|.
browser_context_impl_ = CefBrowserContextImpl::GetForContext(
other_browser_context);
}
if (!browser_context_impl_) {
const base::FilePath& cache_path =
base::FilePath(CefString(&config_.settings.cache_path));
if (!cache_path.empty()) {
// Check if a CefBrowserContextImpl is already globally registered for
// the specified cache path. If so then use it.
browser_context_impl_ =
CefBrowserContextImpl::GetForCachePath(cache_path);
}
}
if (!browser_context_impl_) {
// Create a new CefBrowserContextImpl instance. If the cache path is non-
// empty then this new instance will become the globally registered
// CefBrowserContextImpl for that path. Otherwise, this new instance will
// be a completely isolated "incongento mode" context.
browser_context_impl_ = new CefBrowserContextImpl(config_.settings);
browser_context_impl_->Initialize();
}
// We'll disassociate from |browser_context_impl_| on destruction.
browser_context_impl_->AddRequestContext();
// Force our settings to match |browser_context_impl_|.
config_.settings = browser_context_impl_->GetSettings();
if (config_.handler.get()) {
// Use a proxy that will execute handler callbacks where appropriate and
// otherwise forward all requests to |browser_context_impl_|.
browser_context_proxy_.reset(
new CefBrowserContextProxy(config_.handler, browser_context_impl_));
browser_context_proxy_->Initialize();
DCHECK(!config_.is_global);
} else {
config_.is_global = (browser_context_impl_ ==
CefContentBrowserClient::Get()->browser_context());
}
request_context_impl_ = browser_context_impl_->request_context().get();
DCHECK(request_context_impl_);
if (config_.handler.get()) {
// Keep the handler alive until the associated request context is
// destroyed.
request_context_impl_->AddHandler(config_.handler);
}
} }
void CefRequestContextImpl::EnsureBrowserContext() { void CefRequestContextImpl::EnsureBrowserContext() {
GetBrowserContext(); if (!browser_context())
DCHECK(browser_context_.get()); Initialize();
DCHECK(browser_context());
DCHECK(request_context_impl_); DCHECK(request_context_impl_);
} }
@ -577,17 +605,17 @@ void CefRequestContextImpl::GetBrowserContextOnUIThread(
if (task_runner->BelongsToCurrentThread()) { if (task_runner->BelongsToCurrentThread()) {
// Execute the callback immediately. // Execute the callback immediately.
callback.Run(browser_context_); callback.Run(browser_context());
} else { } else {
// Execute the callback on the target thread. // Execute the callback on the target thread.
task_runner->PostTask(FROM_HERE, base::Bind(callback, browser_context_)); task_runner->PostTask(FROM_HERE, base::Bind(callback, browser_context()));
} }
} }
void CefRequestContextImpl::GetRequestContextImplOnIOThread( void CefRequestContextImpl::GetRequestContextImplOnIOThread(
scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_refptr<base::SingleThreadTaskRunner> task_runner,
const RequestContextCallback& callback, const RequestContextCallback& callback,
scoped_refptr<CefBrowserContext> browser_context) { CefBrowserContext* browser_context) {
if (!CEF_CURRENTLY_ON_IOT()) { if (!CEF_CURRENTLY_ON_IOT()) {
CEF_POST_TASK(CEF_IOT, CEF_POST_TASK(CEF_IOT,
base::Bind(&CefRequestContextImpl::GetRequestContextImplOnIOThread, base::Bind(&CefRequestContextImpl::GetRequestContextImplOnIOThread,
@ -628,16 +656,16 @@ void CefRequestContextImpl::ClearSchemeHandlerFactoriesInternal(
void CefRequestContextImpl::PurgePluginListCacheInternal( void CefRequestContextImpl::PurgePluginListCacheInternal(
bool reload_pages, bool reload_pages,
scoped_refptr<CefBrowserContext> browser_context) { CefBrowserContext* browser_context) {
CEF_REQUIRE_UIT(); CEF_REQUIRE_UIT();
browser_context->OnPurgePluginListCache(); browser_context->OnPurgePluginListCache();
content::PluginService::GetInstance()->PurgePluginListCache( content::PluginService::GetInstance()->PurgePluginListCache(
browser_context.get(), false); browser_context, false);
} }
void CefRequestContextImpl::ClearCertificateExceptionsInternal( void CefRequestContextImpl::ClearCertificateExceptionsInternal(
CefRefPtr<CefCompletionCallback> callback, CefRefPtr<CefCompletionCallback> callback,
scoped_refptr<CefBrowserContext> browser_context) { CefBrowserContext* browser_context) {
CEF_REQUIRE_UIT(); CEF_REQUIRE_UIT();
content::SSLHostStateDelegate* ssl_delegate = content::SSLHostStateDelegate* ssl_delegate =
@ -647,7 +675,7 @@ void CefRequestContextImpl::ClearCertificateExceptionsInternal(
if (callback) { if (callback) {
CEF_POST_TASK(CEF_UIT, CEF_POST_TASK(CEF_UIT,
base::Bind(&CefCompletionCallback::OnComplete, callback.get())); base::Bind(&CefCompletionCallback::OnComplete, callback));
} }
} }
@ -669,7 +697,7 @@ void CefRequestContextImpl::CloseAllConnectionsInternal(
if (callback) { if (callback) {
CEF_POST_TASK(CEF_UIT, CEF_POST_TASK(CEF_UIT,
base::Bind(&CefCompletionCallback::OnComplete, callback.get())); base::Bind(&CefCompletionCallback::OnComplete, callback));
} }
} }
@ -702,3 +730,10 @@ void CefRequestContextImpl::ResolveHostInternal(
helper->OnResolveCompleted(retval); helper->OnResolveCompleted(retval);
} }
CefBrowserContext* CefRequestContextImpl::browser_context() const {
if (browser_context_proxy_)
return browser_context_proxy_.get();
return browser_context_impl_;
}

View File

@ -8,32 +8,35 @@
#include "include/cef_request_context.h" #include "include/cef_request_context.h"
#include "libcef/browser/browser_context.h" #include "libcef/browser/browser_context.h"
#include "libcef/browser/thread_util.h"
class CefBrowserContextImpl;
class CefBrowserContextProxy;
// Implementation of the CefRequestContext interface. All methods are thread- // Implementation of the CefRequestContext interface. All methods are thread-
// safe unless otherwise indicated. // safe unless otherwise indicated. Will be deleted on the UI thread.
class CefRequestContextImpl : public CefRequestContext { class CefRequestContextImpl : public CefRequestContext {
public: public:
~CefRequestContextImpl() override; ~CefRequestContextImpl() override;
// Returns a CefRequestContextImpl for the specified |request_context|. // Returns a CefRequestContextImpl for the specified |request_context|.
// Will return the global context if |request_context| is NULL. // Will return the global context if |request_context| is NULL.
static CefRefPtr<CefRequestContextImpl> GetForRequestContext( static CefRefPtr<CefRequestContextImpl> GetOrCreateForRequestContext(
CefRefPtr<CefRequestContext> request_context); CefRefPtr<CefRequestContext> request_context);
// Returns a CefRequestContextImpl for the specified |browser_context|. // Returns a CefRequestContextImpl for the specified |browser_context|.
// |browser_context| must be non-NULL. // |browser_context| must be non-NULL.
static CefRefPtr<CefRequestContextImpl> GetForBrowserContext( static CefRefPtr<CefRequestContextImpl> CreateForBrowserContext(
scoped_refptr<CefBrowserContext> browser_context); CefBrowserContext* browser_context);
// Returns the browser context object. Can only be called on the UI thread. // Returns the browser context object. Can only be called on the UI thread.
scoped_refptr<CefBrowserContext> GetBrowserContext(); CefBrowserContext* GetBrowserContext();
// Executes |callback| either synchronously or asynchronously with the browser // Executes |callback| either synchronously or asynchronously with the browser
// context object when it's available. If |task_runner| is NULL the callback // context object when it's available. If |task_runner| is NULL the callback
// will be executed on the originating thread. The resulting context object // will be executed on the originating thread. The resulting context object
// can only be accessed on the UI thread. // can only be accessed on the UI thread.
typedef base::Callback<void(scoped_refptr<CefBrowserContext>)> typedef base::Callback<void(CefBrowserContext*)> BrowserContextCallback;
BrowserContextCallback;
void GetBrowserContext( void GetBrowserContext(
scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_refptr<base::SingleThreadTaskRunner> task_runner,
const BrowserContextCallback& callback); const BrowserContextCallback& callback);
@ -79,17 +82,36 @@ class CefRequestContextImpl : public CefRequestContext {
const CefString& origin, const CefString& origin,
std::vector<CefString>& resolved_ips) override; std::vector<CefString>& resolved_ips) override;
const CefRequestContextSettings& settings() const { return settings_; } const CefRequestContextSettings& settings() const { return config_.settings; }
private: private:
friend class CefRequestContext; friend class CefRequestContext;
explicit CefRequestContextImpl( struct Config {
scoped_refptr<CefBrowserContext> browser_context); // True if wrapping the global context.
CefRequestContextImpl(const CefRequestContextSettings& settings, bool is_global = false;
CefRefPtr<CefRequestContextHandler> handler);
CefRequestContextImpl(CefRefPtr<CefRequestContextImpl> other, // |settings| or |other| will be set when creating a new CefRequestContext
CefRefPtr<CefRequestContextHandler> handler); // via the API. When wrapping an existing CefBrowserContext* both will be
// empty and Initialize(CefBrowserContext*) will be called immediately after
// CefRequestContextImpl construction.
CefRequestContextSettings settings;
CefRefPtr<CefRequestContextImpl> other;
// Optionally use this handler, in which case a CefBrowserContextProxy will
// be created.
CefRefPtr<CefRequestContextHandler> handler;
// Used to uniquely identify CefRequestContext objects before an associated
// CefBrowserContext has been created. Should be set when a new
// CefRequestContext via the API.
int unique_id = -1;
};
explicit CefRequestContextImpl(const Config& config);
void Initialize();
void Initialize(CefBrowserContext* other_browser_context);
// Make sure the browser context exists. Only called on the UI thread. // Make sure the browser context exists. Only called on the UI thread.
void EnsureBrowserContext(); void EnsureBrowserContext();
@ -100,7 +122,7 @@ class CefRequestContextImpl : public CefRequestContext {
void GetRequestContextImplOnIOThread( void GetRequestContextImplOnIOThread(
scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_refptr<base::SingleThreadTaskRunner> task_runner,
const RequestContextCallback& callback, const RequestContextCallback& callback,
scoped_refptr<CefBrowserContext> browser_context); CefBrowserContext* browser_context);
void RegisterSchemeHandlerFactoryInternal( void RegisterSchemeHandlerFactoryInternal(
const CefString& scheme_name, const CefString& scheme_name,
@ -111,10 +133,10 @@ class CefRequestContextImpl : public CefRequestContext {
scoped_refptr<CefURLRequestContextGetterImpl> request_context); scoped_refptr<CefURLRequestContextGetterImpl> request_context);
void PurgePluginListCacheInternal( void PurgePluginListCacheInternal(
bool reload_pages, bool reload_pages,
scoped_refptr<CefBrowserContext> browser_context); CefBrowserContext* browser_context);
void ClearCertificateExceptionsInternal( void ClearCertificateExceptionsInternal(
CefRefPtr<CefCompletionCallback> callback, CefRefPtr<CefCompletionCallback> callback,
scoped_refptr<CefBrowserContext> browser_context); CefBrowserContext* browser_context);
void CloseAllConnectionsInternal( void CloseAllConnectionsInternal(
CefRefPtr<CefCompletionCallback> callback, CefRefPtr<CefCompletionCallback> callback,
scoped_refptr<CefURLRequestContextGetterImpl> request_context); scoped_refptr<CefURLRequestContextGetterImpl> request_context);
@ -123,19 +145,19 @@ class CefRequestContextImpl : public CefRequestContext {
CefRefPtr<CefResolveCallback> callback, CefRefPtr<CefResolveCallback> callback,
scoped_refptr<CefURLRequestContextGetterImpl> request_context); scoped_refptr<CefURLRequestContextGetterImpl> request_context);
scoped_refptr<CefBrowserContext> browser_context_; CefBrowserContext* browser_context() const;
CefRequestContextSettings settings_;
CefRefPtr<CefRequestContextImpl> other_;
CefRefPtr<CefRequestContextHandler> handler_;
// Used to uniquely identify CefRequestContext objects before an associated // If *Impl then we must disassociate from it on destruction.
// CefBrowserContext has been created. CefBrowserContextImpl* browser_context_impl_ = nullptr;
int unique_id_; // If *Proxy then we own it.
std::unique_ptr<CefBrowserContextProxy> browser_context_proxy_;
Config config_;
// Owned by the CefBrowserContext. // Owned by the CefBrowserContext.
CefURLRequestContextGetterImpl* request_context_impl_; CefURLRequestContextGetterImpl* request_context_impl_ = nullptr;
IMPLEMENT_REFCOUNTING(CefRequestContextImpl); IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefRequestContextImpl);
DISALLOW_COPY_AND_ASSIGN(CefRequestContextImpl); DISALLOW_COPY_AND_ASSIGN(CefRequestContextImpl);
}; };

View File

@ -671,8 +671,6 @@ class MethodTestHandler : public TestHandler {
} }
~CompletionCallback() override { ~CompletionCallback() override {
EXPECT_UI_THREAD();
// OnComplete should be executed. // OnComplete should be executed.
EXPECT_FALSE(test_handler_); EXPECT_FALSE(test_handler_);
} }