mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	Simplify ownership of CefBrowserContext objects (issue #2083)
This commit is contained in:
		| @@ -15,25 +15,14 @@ | ||||
| #include "content/public/browser/browser_thread.h" | ||||
| #include "content/public/browser/storage_partition.h" | ||||
|  | ||||
| #if DCHECK_IS_ON() | ||||
| base::AtomicRefCount CefBrowserContext::DebugObjCt = 0; | ||||
| #endif | ||||
|  | ||||
| CefBrowserContext::CefBrowserContext(bool is_proxy) | ||||
|     : is_proxy_(is_proxy), | ||||
|       extension_system_(NULL) { | ||||
| #if DCHECK_IS_ON() | ||||
|   base::AtomicRefCountInc(&DebugObjCt); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| CefBrowserContext::~CefBrowserContext() { | ||||
|   // Should be cleared in Shutdown(). | ||||
|   DCHECK(!resource_context_.get()); | ||||
|  | ||||
| #if DCHECK_IS_ON() | ||||
|   base::AtomicRefCountDec(&DebugObjCt); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void CefBrowserContext::Initialize() { | ||||
| @@ -129,28 +118,27 @@ void CefBrowserContext::OnRenderFrameDeleted(int render_process_id, | ||||
|                                              int render_frame_id, | ||||
|                                              bool is_main_frame, | ||||
|                                              bool is_guest_view) { | ||||
|   CEF_REQUIRE_UIT(); | ||||
|   if (resource_context_ && is_main_frame) { | ||||
|     DCHECK_GE(render_process_id, 0); | ||||
|     // 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(&CefBrowserContext::RenderFrameDeletedOnIOThread, this, | ||||
|                  render_process_id, render_frame_id, is_main_frame, | ||||
|                  is_guest_view)); | ||||
|         base::Bind(&CefResourceContext::ClearPluginLoadDecision, | ||||
|                    base::Unretained(resource_context_.get()), | ||||
|                    render_process_id)); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void CefBrowserContext::OnPurgePluginListCache() { | ||||
|   CEF_REQUIRE_UIT(); | ||||
|   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(&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) { | ||||
|     DCHECK_GE(render_process_id, 0); | ||||
|     resource_context_->ClearPluginLoadDecision(render_process_id); | ||||
|         base::Bind(&CefResourceContext::ClearPluginLoadDecision, | ||||
|                    base::Unretained(resource_context_.get()), -1)); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void CefBrowserContext::PurgePluginListCacheOnIOThread() { | ||||
|   if (resource_context_) | ||||
|     resource_context_->ClearPluginLoadDecision(-1); | ||||
| } | ||||
|   | ||||
| @@ -33,12 +33,12 @@ | ||||
| // | ||||
| // BCI = CefBrowserContextImpl | ||||
| //   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) | ||||
| //   CefBrowserMainParts. | ||||
| //   SPI indirectly. Owned by CefBrowserMainParts for the global context or RCI | ||||
| //   for non-global contexts. | ||||
| // | ||||
| // BCP = CefBrowserContextProxy | ||||
| //   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 | ||||
| //   Owns storage-related objects like Quota, IndexedDB, Cache, etc. Created by | ||||
| @@ -83,29 +83,29 @@ | ||||
| // | ||||
| // Relationship diagram: | ||||
| //   ref = reference (CefRefPtr/scoped_refptr) | ||||
| //   own = ownership (scoped_ptr) | ||||
| //   own = ownership (std::unique_ptr) | ||||
| //   ptr = raw pointer | ||||
| // | ||||
| //                     CefBrowserMainParts----\   isolated cookie manager, etc. | ||||
| //                       |                     \             ^ | ||||
| //                      ref                    ref        ref/own | ||||
| //                      own                    ref        ref/own | ||||
| //                       v                      v            | | ||||
| //                /---> 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 -ref-> RCI -ref-> BCI/BCP -own-> RC -ref-> URCGI/URCGP | ||||
| // BHI -ref-> RCI -own-> BCI/BCP -own-> RC -ref-> URCGI/URCGP | ||||
| // | ||||
| // | ||||
| // How shutdown works: | ||||
| // 1. CefBrowserHostImpl is destroyed on any thread due to browser close, | ||||
| //    ref release, etc. | ||||
| // 2. CefRequestContextImpl is destroyed on any thread due to | ||||
| //    CefBrowserHostImpl destruction, ref release, etc. | ||||
| // 2. CefRequestContextImpl is destroyed (possibly asynchronously) on the UI | ||||
| //    thread due to CefBrowserHostImpl destruction, ref release, etc. | ||||
| // 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). | ||||
| // 4. CefResourceContext is destroyed asynchronously on the IO thread due to | ||||
| //    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 | ||||
| // of this class is passed to WebContents::Create in CefBrowserHostImpl:: | ||||
| // CreateInternal. Only accessed on the UI thread unless otherwise indicated. | ||||
| class CefBrowserContext | ||||
|     : public ChromeProfileStub, | ||||
|       public base::RefCountedThreadSafe< | ||||
|           CefBrowserContext, content::BrowserThread::DeleteOnUIThread> { | ||||
| class CefBrowserContext : public ChromeProfileStub { | ||||
|  public: | ||||
|   explicit CefBrowserContext(bool is_proxy); | ||||
|  | ||||
| @@ -183,10 +180,9 @@ class CefBrowserContext | ||||
|     return extension_system_; | ||||
|   } | ||||
|  | ||||
| #if DCHECK_IS_ON() | ||||
|   // Simple tracking of allocated objects. | ||||
|   static base::AtomicRefCount DebugObjCt;  // NOLINT(runtime/int) | ||||
| #endif | ||||
|   bool is_proxy() const { | ||||
|     return is_proxy_; | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
|   ~CefBrowserContext() override; | ||||
| @@ -195,17 +191,6 @@ class CefBrowserContext | ||||
|   void Shutdown(); | ||||
|  | ||||
|  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. | ||||
|   const bool is_proxy_; | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #include <utility> | ||||
|  | ||||
| #include "libcef/browser/browser_context_proxy.h" | ||||
| #include "libcef/browser/content_browser_client.h" | ||||
| #include "libcef/browser/context.h" | ||||
| #include "libcef/browser/download_manager_delegate.h" | ||||
| #include "libcef/browser/extensions/extension_system.h" | ||||
| @@ -85,9 +86,19 @@ class ImplManager { | ||||
|       const content::BrowserContext* context) { | ||||
|     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(); | ||||
|     for (; it != all_.end(); ++it) { | ||||
|       if (*it == context || (*it)->HasProxy(context)) | ||||
|       if (*it == cef_context_impl) | ||||
|         return *it; | ||||
|     } | ||||
|     return NULL; | ||||
| @@ -139,6 +150,7 @@ base::LazyInstance<ImplManager> g_manager = LAZY_INSTANCE_INITIALIZER; | ||||
| class CefVisitedLinkListener : public visitedlink::VisitedLinkMaster::Listener { | ||||
|  public: | ||||
|   CefVisitedLinkListener() { | ||||
|     DCHECK(listener_map_.empty()); | ||||
|   } | ||||
|  | ||||
|   void CreateListenerForContext(const CefBrowserContext* context) { | ||||
| @@ -196,11 +208,18 @@ 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. | ||||
|   g_manager.Get().RemoveImpl(this, cache_path_); | ||||
|  | ||||
|   Shutdown(); | ||||
|  | ||||
|   visitedlink_listener_->RemoveListenerForContext(this); | ||||
|  | ||||
|   // The FontFamilyCache references the ProxyService so delete it before the | ||||
|   // ProxyService is deleted. | ||||
|   SetUserData(&kFontFamilyCacheKey, NULL); | ||||
| @@ -281,48 +300,39 @@ void CefBrowserContextImpl::Initialize() { | ||||
|  | ||||
| void CefBrowserContextImpl::AddProxy(const CefBrowserContextProxy* proxy) { | ||||
|   CEF_REQUIRE_UIT(); | ||||
|   DCHECK(!HasProxy(proxy)); | ||||
|   proxy_list_.push_back(proxy); | ||||
|  | ||||
|   visitedlink_listener_->CreateListenerForContext(proxy); | ||||
| } | ||||
|  | ||||
| void CefBrowserContextImpl::RemoveProxy(const CefBrowserContextProxy* proxy) { | ||||
|   CEF_REQUIRE_UIT(); | ||||
|  | ||||
|   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( | ||||
|     const content::BrowserContext* context) const { | ||||
| void CefBrowserContextImpl::AddRequestContext() { | ||||
|   CEF_REQUIRE_UIT(); | ||||
|   ProxyList::const_iterator it = proxy_list_.begin(); | ||||
|   for (; it != proxy_list_.end(); ++it) { | ||||
|     if (*it == context) | ||||
|       return true; | ||||
|   request_context_count_++; | ||||
| } | ||||
|  | ||||
| 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 | ||||
| scoped_refptr<CefBrowserContextImpl> CefBrowserContextImpl::GetForCachePath( | ||||
| CefBrowserContextImpl* CefBrowserContextImpl::GetForCachePath( | ||||
|     const base::FilePath& cache_path) { | ||||
|   return g_manager.Get().GetImplForPath(cache_path); | ||||
| } | ||||
|  | ||||
| // static | ||||
| CefRefPtr<CefBrowserContextImpl> CefBrowserContextImpl::GetForContext( | ||||
| CefBrowserContextImpl* CefBrowserContextImpl::GetForContext( | ||||
|     content::BrowserContext* context) { | ||||
|   return g_manager.Get().GetImplForContext(context); | ||||
| } | ||||
|   | ||||
| @@ -25,9 +25,9 @@ class VisitedLinkMaster; | ||||
| } | ||||
|  | ||||
| // Isolated BrowserContext implementation. Life span is controlled by | ||||
| // CefRequestContextImpl and (for the main context) CefBrowserMainParts. Only | ||||
| // accessed on the UI thread unless otherwise indicated. See browser_context.h | ||||
| // for an object relationship diagram. | ||||
| // CefBrowserMainParts for the global context and CefRequestContextImpl | ||||
| // for non-global contexts. Only accessed on the UI thread unless otherwise | ||||
| // indicated. See browser_context.h for an object relationship diagram. | ||||
| class CefBrowserContextImpl : public CefBrowserContext, | ||||
|                               public visitedlink::VisitedLinkDelegate { | ||||
|  public: | ||||
| @@ -35,11 +35,11 @@ class CefBrowserContextImpl : public CefBrowserContext, | ||||
|  | ||||
|   // Returns the existing instance, if any, associated with the specified | ||||
|   // |cache_path|. | ||||
|   static scoped_refptr<CefBrowserContextImpl> GetForCachePath( | ||||
|   static CefBrowserContextImpl* GetForCachePath( | ||||
|       const base::FilePath& cache_path); | ||||
|  | ||||
|   // Returns the underlying CefBrowserContextImpl if any. | ||||
|   static CefRefPtr<CefBrowserContextImpl> GetForContext( | ||||
|   static CefBrowserContextImpl* GetForContext( | ||||
|       content::BrowserContext* context); | ||||
|  | ||||
|   // Returns all existing CefBrowserContextImpl. | ||||
| @@ -48,10 +48,14 @@ class CefBrowserContextImpl : public CefBrowserContext, | ||||
|   // Must be called immediately after this object is created. | ||||
|   void Initialize() override; | ||||
|  | ||||
|   // Track associated proxy objects. | ||||
|   // Track associated CefBrowserContextProxy objects. | ||||
|   void AddProxy(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. | ||||
|   base::FilePath GetPath() const override; | ||||
| @@ -98,10 +102,8 @@ class CefBrowserContextImpl : public CefBrowserContext, | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   // Only allow deletion via scoped_refptr(). | ||||
|   friend struct content::BrowserThread::DeleteOnThread< | ||||
|       content::BrowserThread::UI>; | ||||
|   friend class base::DeleteHelper<CefBrowserContextImpl>; | ||||
|   // Allow deletion via std::unique_ptr(). | ||||
|   friend std::default_delete<CefBrowserContextImpl>; | ||||
|  | ||||
|   ~CefBrowserContextImpl() override; | ||||
|  | ||||
| @@ -109,9 +111,8 @@ class CefBrowserContextImpl : public CefBrowserContext, | ||||
|   CefRequestContextSettings settings_; | ||||
|   base::FilePath cache_path_; | ||||
|  | ||||
|   // Not owned by this class. | ||||
|   typedef std::vector<const CefBrowserContextProxy*> ProxyList; | ||||
|   ProxyList proxy_list_; | ||||
|   // Number of CefRequestContextImpl objects referencing this object. | ||||
|   int request_context_count_ = 0; | ||||
|  | ||||
|   std::unique_ptr<PrefService> pref_service_; | ||||
|   std::unique_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_; | ||||
|   | ||||
| @@ -59,16 +59,18 @@ bool ShouldProxyUserData(const void* key) { | ||||
|  | ||||
| CefBrowserContextProxy::CefBrowserContextProxy( | ||||
|     CefRefPtr<CefRequestContextHandler> handler, | ||||
|     scoped_refptr<CefBrowserContextImpl> parent) | ||||
|     CefBrowserContextImpl* parent) | ||||
|     : CefBrowserContext(true), | ||||
|       handler_(handler), | ||||
|       parent_(parent) { | ||||
|   DCHECK(handler_.get()); | ||||
|   DCHECK(parent_.get()); | ||||
|   DCHECK(parent_); | ||||
|   parent_->AddProxy(this); | ||||
| } | ||||
|  | ||||
| CefBrowserContextProxy::~CefBrowserContextProxy() { | ||||
|   CEF_REQUIRE_UIT(); | ||||
|  | ||||
|   Shutdown(); | ||||
|  | ||||
|   parent_->RemoveProxy(this); | ||||
|   | ||||
| @@ -21,7 +21,7 @@ class CefStoragePartitionProxy; | ||||
| class CefBrowserContextProxy : public CefBrowserContext { | ||||
|  public: | ||||
|   CefBrowserContextProxy(CefRefPtr<CefRequestContextHandler> handler, | ||||
|                          scoped_refptr<CefBrowserContextImpl> parent); | ||||
|                          CefBrowserContextImpl* parent); | ||||
|  | ||||
|   // Must be called immediately after this object is created. | ||||
|   void Initialize() override; | ||||
| @@ -67,21 +67,19 @@ class CefBrowserContextProxy : public CefBrowserContext { | ||||
|   content::StoragePartition* GetOrCreateStoragePartitionProxy( | ||||
|     content::StoragePartition* partition_impl); | ||||
|  | ||||
|   scoped_refptr<CefBrowserContextImpl> parent() const { | ||||
|   CefBrowserContextImpl* parent() const { | ||||
|     return parent_; | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   // Only allow deletion via scoped_refptr(). | ||||
|   friend struct content::BrowserThread::DeleteOnThread< | ||||
|       content::BrowserThread::UI>; | ||||
|   friend class base::DeleteHelper<CefBrowserContextProxy>; | ||||
|   // Allow deletion via std::unique_ptr() only. | ||||
|   friend std::default_delete<CefBrowserContextProxy>; | ||||
|  | ||||
|   ~CefBrowserContextProxy() override; | ||||
|  | ||||
|   // Members initialized during construction are safe to access from any thread. | ||||
|   CefRefPtr<CefRequestContextHandler> handler_; | ||||
|   scoped_refptr<CefBrowserContextImpl> parent_; | ||||
|   CefBrowserContextImpl* parent_;  // Guaranteed to outlive this object. | ||||
|  | ||||
|   std::unique_ptr<CefDownloadManagerDelegate> download_manager_delegate_; | ||||
|   std::unique_ptr<CefStoragePartitionProxy> storage_partition_proxy_; | ||||
|   | ||||
| @@ -281,10 +281,10 @@ CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::Create( | ||||
|  | ||||
|   // Get or create the request context and browser context. | ||||
|   CefRefPtr<CefRequestContextImpl> request_context_impl = | ||||
|       CefRequestContextImpl::GetForRequestContext( | ||||
|       CefRequestContextImpl::GetOrCreateForRequestContext( | ||||
|           create_params.request_context); | ||||
|   DCHECK(request_context_impl); | ||||
|   scoped_refptr<CefBrowserContext> browser_context = | ||||
|   CefBrowserContext* browser_context = | ||||
|       request_context_impl->GetBrowserContext(); | ||||
|   DCHECK(browser_context); | ||||
|  | ||||
| @@ -298,8 +298,7 @@ CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::Create( | ||||
|     create_params.request_context = request_context_impl.get(); | ||||
|   } | ||||
|  | ||||
|   content::WebContents::CreateParams wc_create_params( | ||||
|       browser_context.get()); | ||||
|   content::WebContents::CreateParams wc_create_params(browser_context); | ||||
|  | ||||
|   if (platform_delegate->IsWindowless()) { | ||||
|     // Create the OSR view for the WebContents. | ||||
| @@ -692,13 +691,13 @@ void CefBrowserHostImpl::StartDownload(const CefString& url) { | ||||
|   if (!web_contents()) | ||||
|     return; | ||||
|  | ||||
|   scoped_refptr<CefBrowserContext> context = | ||||
|   CefBrowserContext* context = | ||||
|       static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext()); | ||||
|   if (!context.get()) | ||||
|   if (!context) | ||||
|     return; | ||||
|  | ||||
|   content::DownloadManager* manager = | ||||
|       content::BrowserContext::GetDownloadManager(context.get()); | ||||
|       content::BrowserContext::GetDownloadManager(context); | ||||
|   if (!manager) | ||||
|     return; | ||||
|  | ||||
| @@ -2272,11 +2271,11 @@ void CefBrowserHostImpl::WebContentsCreated( | ||||
|   CefRefPtr<CefBrowserHostImpl> opener = GetBrowserForContents(source_contents); | ||||
|   DCHECK(opener.get()); | ||||
|  | ||||
|   scoped_refptr<CefBrowserContext> browser_context = | ||||
|   CefBrowserContext* browser_context = | ||||
|       static_cast<CefBrowserContext*>(new_contents->GetBrowserContext()); | ||||
|   DCHECK(browser_context.get()); | ||||
|   DCHECK(browser_context); | ||||
|   CefRefPtr<CefRequestContext> request_context = | ||||
|       CefRequestContextImpl::GetForBrowserContext(browser_context).get(); | ||||
|       CefRequestContextImpl::CreateForBrowserContext(browser_context).get(); | ||||
|   DCHECK(request_context.get()); | ||||
|  | ||||
|   CefRefPtr<CefBrowserHostImpl> browser = CefBrowserHostImpl::CreateInternal( | ||||
| @@ -2406,7 +2405,7 @@ void CefBrowserHostImpl::RenderFrameDeleted( | ||||
|  | ||||
|   if (web_contents()) { | ||||
|     const bool is_main_frame = (render_frame_host->GetParent() == nullptr); | ||||
|     scoped_refptr<CefBrowserContext> context = | ||||
|     CefBrowserContext* context = | ||||
|         static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext()); | ||||
|     if (context) { | ||||
|       context->OnRenderFrameDeleted(render_process_id, render_routing_id, | ||||
| @@ -2578,9 +2577,9 @@ void CefBrowserHostImpl::DidNavigateAnyFrame( | ||||
|   if (!web_contents()) | ||||
|     return; | ||||
|  | ||||
|   scoped_refptr<CefBrowserContext> context = | ||||
|   CefBrowserContext* context = | ||||
|       static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext()); | ||||
|   if (!context.get()) | ||||
|   if (!context) | ||||
|     return; | ||||
|  | ||||
|   context->AddVisitedURLs(params.redirects); | ||||
|   | ||||
| @@ -193,7 +193,7 @@ void CefBrowserMainParts::PreMainMessageLoopRun() { | ||||
|   CefContext::Get()->PopulateRequestContextSettings(&settings); | ||||
|  | ||||
|   // Create the global BrowserContext. | ||||
|   global_browser_context_ = new CefBrowserContextImpl(settings); | ||||
|   global_browser_context_.reset(new CefBrowserContextImpl(settings)); | ||||
|   global_browser_context_->Initialize(); | ||||
|  | ||||
|   CefDevToolsManagerDelegate::StartHttpHandler(global_browser_context_.get()); | ||||
| @@ -212,7 +212,7 @@ void CefBrowserMainParts::PostMainMessageLoopRun() { | ||||
|   // NOTE: Destroy objects in reverse order of creation. | ||||
|   CefDevToolsManagerDelegate::StopHttpHandler(); | ||||
|  | ||||
|   global_browser_context_ = NULL; | ||||
|   global_browser_context_.reset(nullptr); | ||||
|  | ||||
|   if (extensions::ExtensionsEnabled()) { | ||||
|     extensions::ExtensionsBrowserClient::Set(NULL); | ||||
|   | ||||
| @@ -6,7 +6,6 @@ | ||||
| #define CEF_LIBCEF_BROWSER_BROWSER_MAIN_H_ | ||||
| #pragma once | ||||
|  | ||||
| #include "libcef/browser/browser_context_impl.h" | ||||
| #include "libcef/browser/net/url_request_context_getter_impl.h" | ||||
|  | ||||
| #include "base/macros.h" | ||||
| @@ -31,6 +30,7 @@ class ExtensionsBrowserClient; | ||||
| class ExtensionsClient; | ||||
| } | ||||
|  | ||||
| class CefBrowserContextImpl; | ||||
| class CefDevToolsDelegate; | ||||
|  | ||||
| class CefBrowserMainParts : public content::BrowserMainParts { | ||||
| @@ -47,8 +47,8 @@ class CefBrowserMainParts : public content::BrowserMainParts { | ||||
|   void PostMainMessageLoopRun() override; | ||||
|   void PostDestroyThreads() override; | ||||
|  | ||||
|   scoped_refptr<CefBrowserContextImpl> browser_context() const { | ||||
|     return global_browser_context_; | ||||
|   CefBrowserContextImpl* browser_context() const { | ||||
|     return global_browser_context_.get(); | ||||
|   } | ||||
|   CefDevToolsDelegate* devtools_delegate() const { | ||||
|     return devtools_delegate_; | ||||
| @@ -59,7 +59,7 @@ class CefBrowserMainParts : public content::BrowserMainParts { | ||||
|   void PlatformInitialize(); | ||||
| #endif  // defined(OS_WIN) | ||||
|  | ||||
|   scoped_refptr<CefBrowserContextImpl> global_browser_context_; | ||||
|   std::unique_ptr<CefBrowserContextImpl> global_browser_context_; | ||||
|   CefDevToolsDelegate* devtools_delegate_;  // Deletes itself. | ||||
|   std::unique_ptr<base::MessageLoop> message_loop_; | ||||
|  | ||||
|   | ||||
| @@ -190,11 +190,11 @@ class CefBrowserURLRequest::Context | ||||
|  | ||||
|     // Get or create the request context and browser context. | ||||
|     CefRefPtr<CefRequestContextImpl> request_context_impl = | ||||
|         CefRequestContextImpl::GetForRequestContext(request_context_); | ||||
|         CefRequestContextImpl::GetOrCreateForRequestContext(request_context_); | ||||
|     DCHECK(request_context_impl.get()); | ||||
|     scoped_refptr<CefBrowserContext> browser_context = | ||||
|     CefBrowserContext* browser_context = | ||||
|         request_context_impl->GetBrowserContext(); | ||||
|     DCHECK(browser_context.get()); | ||||
|     DCHECK(browser_context); | ||||
|  | ||||
|     if (!request_context_.get()) | ||||
|       request_context_ = request_context_impl.get(); | ||||
|   | ||||
| @@ -360,7 +360,7 @@ ChromeBrowserProcessStub::GetPhysicalWebDataSource() { | ||||
| content::BrowserContext* | ||||
| ChromeBrowserProcessStub::GetBrowserContextRedirectedInIncognito( | ||||
|     content::BrowserContext* context) { | ||||
|   return CefBrowserContextImpl::GetForContext(context).get(); | ||||
|   return CefBrowserContextImpl::GetForContext(context); | ||||
| } | ||||
|  | ||||
| content::BrowserContext* | ||||
|   | ||||
| @@ -21,7 +21,7 @@ namespace { | ||||
| // Return the main context for now since we don't currently have a good way to | ||||
| // determine that. | ||||
| CefBrowserContextImpl* GetActiveBrowserContext() { | ||||
|   return CefContentBrowserClient::Get()->browser_context().get(); | ||||
|   return CefContentBrowserClient::Get()->browser_context(); | ||||
| } | ||||
|  | ||||
| }  // namespace | ||||
| @@ -35,7 +35,7 @@ ChromeProfileManagerStub::~ChromeProfileManagerStub() { | ||||
|  | ||||
| Profile* ChromeProfileManagerStub::GetProfile( | ||||
|     const base::FilePath& profile_dir) { | ||||
|   scoped_refptr<CefBrowserContextImpl> browser_context = | ||||
|   CefBrowserContextImpl* browser_context = | ||||
|       CefBrowserContextImpl::GetForCachePath(profile_dir); | ||||
|   if (!browser_context) { | ||||
|     // ProfileManager makes assumptions about profile directory paths that do | ||||
| @@ -46,7 +46,7 @@ Profile* ChromeProfileManagerStub::GetProfile( | ||||
|     // asking for. | ||||
|     browser_context = GetActiveBrowserContext(); | ||||
|   } | ||||
|   return browser_context.get(); | ||||
|   return browser_context; | ||||
| } | ||||
|  | ||||
| bool ChromeProfileManagerStub::IsValidProfile(const void* profile) { | ||||
| @@ -54,7 +54,7 @@ bool ChromeProfileManagerStub::IsValidProfile(const void* profile) { | ||||
|     return false; | ||||
|   return !!CefBrowserContextImpl::GetForContext( | ||||
|       reinterpret_cast<content::BrowserContext*>( | ||||
|           const_cast<void*>(profile))).get(); | ||||
|           const_cast<void*>(profile))); | ||||
| } | ||||
|  | ||||
| Profile* ChromeProfileManagerStub::GetLastUsedProfile( | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
| #include <algorithm> | ||||
| #include <utility> | ||||
|  | ||||
| #include "libcef/browser/browser_context.h" | ||||
| #include "libcef/browser/browser_info.h" | ||||
| #include "libcef/browser/browser_info_manager.h" | ||||
| #include "libcef/browser/browser_host_impl.h" | ||||
| @@ -42,6 +43,7 @@ | ||||
| #include "base/json/json_reader.h" | ||||
| #include "base/path_service.h" | ||||
| #include "cef/grit/cef_resources.h" | ||||
| #include "chrome/browser/profiles/profile.h" | ||||
| #include "chrome/browser/spellchecker/spellcheck_message_filter.h" | ||||
| #include "chrome/common/chrome_switches.h" | ||||
| #include "components/navigation_interception/intercept_navigation_throttle.h" | ||||
| @@ -979,8 +981,7 @@ void CefContentBrowserClient::RegisterCustomScheme(const std::string& scheme) { | ||||
|     policy->RegisterWebSafeScheme(scheme); | ||||
| } | ||||
|  | ||||
| scoped_refptr<CefBrowserContextImpl> | ||||
| CefContentBrowserClient::browser_context() const { | ||||
| CefBrowserContextImpl* CefContentBrowserClient::browser_context() const { | ||||
|   return browser_main_parts_->browser_context(); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -10,7 +10,6 @@ | ||||
| #include <utility> | ||||
|  | ||||
| #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 "base/macros.h" | ||||
| @@ -20,6 +19,7 @@ | ||||
| #include "third_party/skia/include/core/SkColor.h" | ||||
|  | ||||
| class CefBrowserMainParts; | ||||
| class CefBrowserContextImpl; | ||||
| class CefDevToolsDelegate; | ||||
| class CefResourceDispatcherHostDelegate; | ||||
|  | ||||
| @@ -28,6 +28,10 @@ class PluginServiceFilter; | ||||
| class SiteInstance; | ||||
| } | ||||
|  | ||||
| namespace extensions { | ||||
| class Extension; | ||||
| } | ||||
|  | ||||
| class CefContentBrowserClient : public content::ContentBrowserClient { | ||||
|  public: | ||||
|   CefContentBrowserClient(); | ||||
| @@ -113,7 +117,7 @@ class CefContentBrowserClient : public content::ContentBrowserClient { | ||||
|   // Perform browser process registration for the custom scheme. | ||||
|   void RegisterCustomScheme(const std::string& scheme); | ||||
|  | ||||
|   scoped_refptr<CefBrowserContextImpl> browser_context() const; | ||||
|   CefBrowserContextImpl* browser_context() const; | ||||
|   CefDevToolsDelegate* devtools_delegate() const; | ||||
|  | ||||
|  private: | ||||
|   | ||||
| @@ -57,10 +57,10 @@ bool GetTabById(int tab_id, | ||||
|     if (!request_context) | ||||
|       continue; | ||||
|     CefRefPtr<CefRequestContextImpl> request_context_impl = | ||||
|         CefRequestContextImpl::GetForRequestContext(request_context); | ||||
|         CefRequestContextImpl::GetOrCreateForRequestContext(request_context); | ||||
|     if (!request_context_impl) | ||||
|       continue; | ||||
|     scoped_refptr<CefBrowserContext> browser_context = | ||||
|     CefBrowserContext* browser_context = | ||||
|         request_context_impl->GetBrowserContext(); | ||||
|     if (!browser_context) | ||||
|       continue; | ||||
|   | ||||
| @@ -44,7 +44,7 @@ CefExtensionsAPIClient::CreateGuestViewManagerDelegate( | ||||
|   // *Proxy object that has already been deleted. | ||||
|   return base::WrapUnique( | ||||
|       new extensions::ExtensionsGuestViewManagerDelegate( | ||||
|           CefBrowserContextImpl::GetForContext(context).get())); | ||||
|           CefBrowserContextImpl::GetForContext(context))); | ||||
| } | ||||
|  | ||||
| std::unique_ptr<MimeHandlerViewGuestDelegate> | ||||
|   | ||||
| @@ -64,8 +64,8 @@ bool CefExtensionsBrowserClient::IsSameContext(BrowserContext* first, | ||||
|                                                BrowserContext* second) { | ||||
|   // Returns true if |first| and |second| share the same underlying | ||||
|   // CefBrowserContextImpl. | ||||
|   return CefBrowserContextImpl::GetForContext(first).get() == | ||||
|          CefBrowserContextImpl::GetForContext(second).get(); | ||||
|   return CefBrowserContextImpl::GetForContext(first) == | ||||
|          CefBrowserContextImpl::GetForContext(second); | ||||
| } | ||||
|  | ||||
| bool CefExtensionsBrowserClient::HasOffTheRecordContext( | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
|  | ||||
| #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_info.h" | ||||
| #include "libcef/browser/content_browser_client.h" | ||||
| @@ -91,7 +92,7 @@ void CefMimeHandlerViewGuestDelegate::OnGuestDetached( | ||||
|   info->guest_render_id_manager()->remove_render_frame_id( | ||||
|       render_process_id, render_frame_id); | ||||
|  | ||||
|   scoped_refptr<CefBrowserContext> context = | ||||
|   CefBrowserContext* context = | ||||
|       static_cast<CefBrowserContext*>(web_contents->GetBrowserContext()); | ||||
|   if (context) { | ||||
|     context->OnRenderFrameDeleted(render_process_id, render_frame_id, | ||||
|   | ||||
| @@ -64,7 +64,7 @@ struct ResolveHostHelper { | ||||
|       resolved_ips.push_back(iter->ToStringWithoutPort()); | ||||
|  | ||||
|     CEF_POST_TASK(CEF_UIT, | ||||
|         base::Bind(&CefResolveCallback::OnResolveCompleted, callback_.get(), | ||||
|         base::Bind(&CefResolveCallback::OnResolveCompleted, callback_, | ||||
|                    static_cast<cef_errorcode_t>(result), resolved_ips)); | ||||
|  | ||||
|     delete this; | ||||
| @@ -88,8 +88,9 @@ CefRefPtr<CefRequestContext> CefRequestContext::GetGlobalContext() { | ||||
|     return NULL; | ||||
|   } | ||||
|  | ||||
|   return CefRequestContextImpl::GetForBrowserContext( | ||||
|       CefContentBrowserClient::Get()->browser_context()); | ||||
|   CefRequestContextImpl::Config config; | ||||
|   config.is_global = true; | ||||
|   return new CefRequestContextImpl(config); | ||||
| } | ||||
|  | ||||
| // static | ||||
| @@ -102,7 +103,11 @@ CefRefPtr<CefRequestContext> CefRequestContext::CreateContext( | ||||
|     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 | ||||
| @@ -118,18 +123,31 @@ CefRefPtr<CefRequestContext> CefRequestContext::CreateContext( | ||||
|   if (!other.get()) | ||||
|     return NULL; | ||||
|  | ||||
|   return new CefRequestContextImpl( | ||||
|       static_cast<CefRequestContextImpl*>(other.get()), handler); | ||||
|   CefRequestContextImpl::Config config; | ||||
|   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() { | ||||
|   // 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 | ||||
| CefRefPtr<CefRequestContextImpl> CefRequestContextImpl::GetForRequestContext( | ||||
| CefRefPtr<CefRequestContextImpl> | ||||
| CefRequestContextImpl::GetOrCreateForRequestContext( | ||||
|       CefRefPtr<CefRequestContext> request_context) { | ||||
|    if (request_context.get()) { | ||||
|     // Use the context from the provided CefRequestContext. | ||||
| @@ -137,87 +155,27 @@ CefRefPtr<CefRequestContextImpl> CefRequestContextImpl::GetForRequestContext( | ||||
|   } | ||||
|    | ||||
|   // Use the global context. | ||||
|   scoped_refptr<CefBrowserContext> browser_context = | ||||
|       CefContentBrowserClient::Get()->browser_context(); | ||||
|   return GetForBrowserContext(browser_context); | ||||
|   CefRequestContextImpl::Config config; | ||||
|   config.is_global = true; | ||||
|   return new CefRequestContextImpl(config); | ||||
| } | ||||
|  | ||||
| // static | ||||
| CefRefPtr<CefRequestContextImpl> CefRequestContextImpl::GetForBrowserContext( | ||||
|       scoped_refptr<CefBrowserContext> browser_context) { | ||||
|   DCHECK(browser_context.get()); | ||||
|   return new CefRequestContextImpl(browser_context); | ||||
| CefRefPtr<CefRequestContextImpl> CefRequestContextImpl::CreateForBrowserContext( | ||||
|       CefBrowserContext* browser_context) { | ||||
|   DCHECK(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() { | ||||
|   CEF_REQUIRE_UIT(); | ||||
|  | ||||
|   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_; | ||||
| CefBrowserContext* CefRequestContextImpl::GetBrowserContext() { | ||||
|   EnsureBrowserContext(); | ||||
|   return browser_context(); | ||||
| } | ||||
|  | ||||
| void CefRequestContextImpl::GetBrowserContext( | ||||
| @@ -235,8 +193,8 @@ void CefRequestContextImpl::GetRequestContextImpl( | ||||
|     task_runner = base::MessageLoop::current()->task_runner(); | ||||
|   if (request_context_impl_) { | ||||
|     // The browser context already exists. | ||||
|     DCHECK(browser_context_.get()); | ||||
|     GetRequestContextImplOnIOThread(task_runner, callback, browser_context_); | ||||
|     DCHECK(browser_context()); | ||||
|     GetRequestContextImplOnIOThread(task_runner, callback, browser_context()); | ||||
|   } else { | ||||
|     // Need to initialize the browser context first. | ||||
|     GetBrowserContextOnUIThread( | ||||
| @@ -252,14 +210,28 @@ bool CefRequestContextImpl::IsSame(CefRefPtr<CefRequestContext> other) { | ||||
|   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_) | ||||
|   if (browser_context() && other_impl->browser_context()) { | ||||
|     if (browser_context()->is_proxy() && | ||||
|         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; | ||||
|   } | ||||
|  | ||||
|   // 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) { | ||||
| @@ -271,14 +243,14 @@ bool CefRequestContextImpl::IsSharingWith(CefRefPtr<CefRequestContext> other) { | ||||
|   if (IsSame(other)) | ||||
|     return true; | ||||
|  | ||||
|   CefRefPtr<CefRequestContext> pending_other = other_; | ||||
|   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->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. | ||||
| @@ -292,26 +264,26 @@ bool CefRequestContextImpl::IsSharingWith(CefRefPtr<CefRequestContext> other) { | ||||
|  | ||||
|   // 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 (settings_.cache_path.length > 0 && | ||||
|       other_impl->settings_.cache_path.length > 0) { | ||||
|     return (base::FilePath(CefString(&settings_.cache_path)) == | ||||
|             base::FilePath(CefString(&other_impl->settings_.cache_path))); | ||||
|   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 (browser_context_ == | ||||
|           CefContentBrowserClient::Get()->browser_context()); | ||||
|   return config_.is_global; | ||||
| } | ||||
|  | ||||
| CefRefPtr<CefRequestContextHandler> CefRequestContextImpl::GetHandler() { | ||||
|   return handler_; | ||||
|   return config_.handler; | ||||
| } | ||||
|  | ||||
| CefString CefRequestContextImpl::GetCachePath() { | ||||
|   return CefString(&settings_.cache_path); | ||||
|   return CefString(&config_.settings.cache_path); | ||||
| } | ||||
|  | ||||
| CefRefPtr<CefCookieManager> CefRequestContextImpl::GetDefaultCookieManager( | ||||
| @@ -357,7 +329,7 @@ bool CefRequestContextImpl::HasPreference(const CefString& name) { | ||||
|   // Make sure the browser context exists. | ||||
|   EnsureBrowserContext(); | ||||
|  | ||||
|   PrefService* pref_service = browser_context_->GetPrefs(); | ||||
|   PrefService* pref_service = browser_context()->GetPrefs(); | ||||
|   return (pref_service->FindPreference(name) != NULL); | ||||
| } | ||||
|  | ||||
| @@ -372,7 +344,7 @@ CefRefPtr<CefValue> CefRequestContextImpl::GetPreference( | ||||
|   // Make sure the browser context exists. | ||||
|   EnsureBrowserContext(); | ||||
|  | ||||
|   PrefService* pref_service = browser_context_->GetPrefs(); | ||||
|   PrefService* pref_service = browser_context()->GetPrefs(); | ||||
|   const PrefService::Preference* pref = pref_service->FindPreference(name); | ||||
|   if (!pref) | ||||
|     return NULL; | ||||
| @@ -390,7 +362,7 @@ CefRefPtr<CefDictionaryValue> CefRequestContextImpl::GetAllPreferences( | ||||
|   // Make sure the browser context exists. | ||||
|   EnsureBrowserContext(); | ||||
|  | ||||
|   PrefService* pref_service = browser_context_->GetPrefs(); | ||||
|   PrefService* pref_service = browser_context()->GetPrefs(); | ||||
|  | ||||
|   std::unique_ptr<base::DictionaryValue> values; | ||||
|   if (include_defaults) | ||||
| @@ -412,7 +384,7 @@ bool CefRequestContextImpl::CanSetPreference(const CefString& name) { | ||||
|   // Make sure the browser context exists. | ||||
|   EnsureBrowserContext(); | ||||
|  | ||||
|   PrefService* pref_service = browser_context_->GetPrefs(); | ||||
|   PrefService* pref_service = browser_context()->GetPrefs(); | ||||
|   const PrefService::Preference* pref = pref_service->FindPreference(name); | ||||
|   return (pref && pref->IsUserModifiable()); | ||||
| } | ||||
| @@ -429,7 +401,7 @@ bool CefRequestContextImpl::SetPreference(const CefString& name, | ||||
|   // Make sure the browser context exists. | ||||
|   EnsureBrowserContext(); | ||||
|  | ||||
|   PrefService* pref_service = browser_context_->GetPrefs(); | ||||
|   PrefService* pref_service = browser_context()->GetPrefs(); | ||||
|  | ||||
|   // The below validation logic should match PrefService::SetUserPrefValue. | ||||
|  | ||||
| @@ -530,35 +502,91 @@ cef_errorcode_t CefRequestContextImpl::ResolveHostCached( | ||||
| } | ||||
|  | ||||
| CefRequestContextImpl::CefRequestContextImpl( | ||||
|     scoped_refptr<CefBrowserContext> browser_context) | ||||
|     : browser_context_(browser_context), | ||||
|       settings_(browser_context->GetSettings()), | ||||
|       handler_(browser_context->GetHandler()), | ||||
|       unique_id_(0), | ||||
|       request_context_impl_(NULL) { | ||||
|     const CefRequestContextImpl::Config& config) | ||||
|     : config_(config) { | ||||
| } | ||||
|  | ||||
| CefRequestContextImpl::CefRequestContextImpl( | ||||
|     const CefRequestContextSettings& settings, | ||||
|     CefRefPtr<CefRequestContextHandler> handler) | ||||
|     : settings_(settings), | ||||
|       handler_(handler), | ||||
|       unique_id_(g_next_id.GetNext()), | ||||
|       request_context_impl_(NULL) { | ||||
| void CefRequestContextImpl::Initialize() { | ||||
|   CefBrowserContext* other_browser_context = nullptr; | ||||
|   if (config_.is_global) | ||||
|     other_browser_context = CefContentBrowserClient::Get()->browser_context(); | ||||
|   else if (config_.other.get()) | ||||
|     other_browser_context = config_.other->GetBrowserContext(); | ||||
|  | ||||
|   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( | ||||
|     CefRefPtr<CefRequestContextImpl> other, | ||||
|     CefRefPtr<CefRequestContextHandler> handler) | ||||
|     : other_(other), | ||||
|       handler_(handler), | ||||
|       unique_id_(g_next_id.GetNext()), | ||||
|       request_context_impl_(NULL) { | ||||
| void CefRequestContextImpl::Initialize( | ||||
|     CefBrowserContext* other_browser_context) { | ||||
|   CEF_REQUIRE_UIT(); | ||||
|  | ||||
|   DCHECK(!browser_context_impl_); | ||||
|   DCHECK(!request_context_impl_); | ||||
|  | ||||
|   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() { | ||||
|   GetBrowserContext(); | ||||
|   DCHECK(browser_context_.get()); | ||||
|   if (!browser_context()) | ||||
|     Initialize(); | ||||
|   DCHECK(browser_context()); | ||||
|   DCHECK(request_context_impl_); | ||||
| } | ||||
|  | ||||
| @@ -577,17 +605,17 @@ void CefRequestContextImpl::GetBrowserContextOnUIThread( | ||||
|  | ||||
|   if (task_runner->BelongsToCurrentThread()) { | ||||
|     // Execute the callback immediately. | ||||
|     callback.Run(browser_context_); | ||||
|     callback.Run(browser_context()); | ||||
|   } else { | ||||
|     // 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( | ||||
|     scoped_refptr<base::SingleThreadTaskRunner> task_runner, | ||||
|     const RequestContextCallback& callback, | ||||
|     scoped_refptr<CefBrowserContext> browser_context) { | ||||
|     CefBrowserContext* browser_context) { | ||||
|   if (!CEF_CURRENTLY_ON_IOT()) { | ||||
|     CEF_POST_TASK(CEF_IOT, | ||||
|         base::Bind(&CefRequestContextImpl::GetRequestContextImplOnIOThread, | ||||
| @@ -628,16 +656,16 @@ void CefRequestContextImpl::ClearSchemeHandlerFactoriesInternal( | ||||
|  | ||||
| void CefRequestContextImpl::PurgePluginListCacheInternal( | ||||
|     bool reload_pages, | ||||
|     scoped_refptr<CefBrowserContext> browser_context) { | ||||
|     CefBrowserContext* browser_context) { | ||||
|   CEF_REQUIRE_UIT(); | ||||
|   browser_context->OnPurgePluginListCache(); | ||||
|   content::PluginService::GetInstance()->PurgePluginListCache( | ||||
|       browser_context.get(), false); | ||||
|       browser_context, false); | ||||
| } | ||||
|  | ||||
| void CefRequestContextImpl::ClearCertificateExceptionsInternal( | ||||
|     CefRefPtr<CefCompletionCallback> callback, | ||||
|     scoped_refptr<CefBrowserContext> browser_context) { | ||||
|     CefBrowserContext* browser_context) { | ||||
|   CEF_REQUIRE_UIT(); | ||||
|  | ||||
|   content::SSLHostStateDelegate* ssl_delegate = | ||||
| @@ -647,7 +675,7 @@ void CefRequestContextImpl::ClearCertificateExceptionsInternal( | ||||
|  | ||||
|   if (callback) { | ||||
|     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) { | ||||
|     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); | ||||
| } | ||||
|  | ||||
| CefBrowserContext* CefRequestContextImpl::browser_context() const { | ||||
|   if (browser_context_proxy_) | ||||
|     return browser_context_proxy_.get(); | ||||
|   return browser_context_impl_; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -8,32 +8,35 @@ | ||||
|  | ||||
| #include "include/cef_request_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- | ||||
| // safe unless otherwise indicated. | ||||
| // safe unless otherwise indicated. Will be deleted on the UI thread. | ||||
| class CefRequestContextImpl : public CefRequestContext { | ||||
|  public: | ||||
|   ~CefRequestContextImpl() override; | ||||
|  | ||||
|   // Returns a CefRequestContextImpl for the specified |request_context|. | ||||
|   // Will return the global context if |request_context| is NULL. | ||||
|   static CefRefPtr<CefRequestContextImpl> GetForRequestContext( | ||||
|   static CefRefPtr<CefRequestContextImpl> GetOrCreateForRequestContext( | ||||
|       CefRefPtr<CefRequestContext> request_context); | ||||
|  | ||||
|   // Returns a CefRequestContextImpl for the specified |browser_context|. | ||||
|   // |browser_context| must be non-NULL. | ||||
|   static CefRefPtr<CefRequestContextImpl> GetForBrowserContext( | ||||
|       scoped_refptr<CefBrowserContext> browser_context); | ||||
|   static CefRefPtr<CefRequestContextImpl> CreateForBrowserContext( | ||||
|       CefBrowserContext* browser_context); | ||||
|  | ||||
|   // 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 | ||||
|   // context object when it's available. If |task_runner| is NULL the callback | ||||
|   // will be executed on the originating thread. The resulting context object | ||||
|   // can only be accessed on the UI thread. | ||||
|   typedef base::Callback<void(scoped_refptr<CefBrowserContext>)> | ||||
|       BrowserContextCallback; | ||||
|   typedef base::Callback<void(CefBrowserContext*)> BrowserContextCallback; | ||||
|   void GetBrowserContext( | ||||
|       scoped_refptr<base::SingleThreadTaskRunner> task_runner, | ||||
|       const BrowserContextCallback& callback); | ||||
| @@ -79,17 +82,36 @@ class CefRequestContextImpl : public CefRequestContext { | ||||
|       const CefString& origin, | ||||
|       std::vector<CefString>& resolved_ips) override; | ||||
|  | ||||
|   const CefRequestContextSettings& settings() const { return settings_; } | ||||
|   const CefRequestContextSettings& settings() const { return config_.settings; } | ||||
|  | ||||
|  private: | ||||
|   friend class CefRequestContext; | ||||
|  | ||||
|   explicit CefRequestContextImpl( | ||||
|       scoped_refptr<CefBrowserContext> browser_context); | ||||
|   CefRequestContextImpl(const CefRequestContextSettings& settings, | ||||
|                         CefRefPtr<CefRequestContextHandler> handler); | ||||
|   CefRequestContextImpl(CefRefPtr<CefRequestContextImpl> other, | ||||
|                         CefRefPtr<CefRequestContextHandler> handler); | ||||
|   struct Config { | ||||
|     // True if wrapping the global context. | ||||
|     bool is_global = false; | ||||
|  | ||||
|     // |settings| or |other| will be set when creating a new CefRequestContext | ||||
|     // 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. | ||||
|   void EnsureBrowserContext(); | ||||
| @@ -100,7 +122,7 @@ class CefRequestContextImpl : public CefRequestContext { | ||||
|   void GetRequestContextImplOnIOThread( | ||||
|       scoped_refptr<base::SingleThreadTaskRunner> task_runner, | ||||
|       const RequestContextCallback& callback, | ||||
|       scoped_refptr<CefBrowserContext> browser_context); | ||||
|       CefBrowserContext* browser_context); | ||||
|  | ||||
|   void RegisterSchemeHandlerFactoryInternal( | ||||
|       const CefString& scheme_name, | ||||
| @@ -111,10 +133,10 @@ class CefRequestContextImpl : public CefRequestContext { | ||||
|       scoped_refptr<CefURLRequestContextGetterImpl> request_context); | ||||
|   void PurgePluginListCacheInternal( | ||||
|       bool reload_pages, | ||||
|       scoped_refptr<CefBrowserContext> browser_context); | ||||
|       CefBrowserContext* browser_context); | ||||
|   void ClearCertificateExceptionsInternal( | ||||
|       CefRefPtr<CefCompletionCallback> callback, | ||||
|       scoped_refptr<CefBrowserContext> browser_context); | ||||
|       CefBrowserContext* browser_context); | ||||
|   void CloseAllConnectionsInternal( | ||||
|       CefRefPtr<CefCompletionCallback> callback, | ||||
|       scoped_refptr<CefURLRequestContextGetterImpl> request_context); | ||||
| @@ -123,19 +145,19 @@ class CefRequestContextImpl : public CefRequestContext { | ||||
|       CefRefPtr<CefResolveCallback> callback, | ||||
|       scoped_refptr<CefURLRequestContextGetterImpl> request_context); | ||||
|  | ||||
|   scoped_refptr<CefBrowserContext> browser_context_; | ||||
|   CefRequestContextSettings settings_; | ||||
|   CefRefPtr<CefRequestContextImpl> other_; | ||||
|   CefRefPtr<CefRequestContextHandler> handler_; | ||||
|   CefBrowserContext* browser_context() const; | ||||
|  | ||||
|   // Used to uniquely identify CefRequestContext objects before an associated | ||||
|   // CefBrowserContext has been created. | ||||
|   int unique_id_; | ||||
|   // If *Impl then we must disassociate from it on destruction. | ||||
|   CefBrowserContextImpl* browser_context_impl_ = nullptr; | ||||
|   // If *Proxy then we own it. | ||||
|   std::unique_ptr<CefBrowserContextProxy> browser_context_proxy_; | ||||
|  | ||||
|   Config config_; | ||||
|  | ||||
|   // 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); | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -671,8 +671,6 @@ class MethodTestHandler : public TestHandler { | ||||
|     } | ||||
|  | ||||
|     ~CompletionCallback() override { | ||||
|       EXPECT_UI_THREAD(); | ||||
|  | ||||
|       // OnComplete should be executed. | ||||
|       EXPECT_FALSE(test_handler_); | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user