diff --git chrome/browser/extensions/api/streams_private/streams_private_api.cc chrome/browser/extensions/api/streams_private/streams_private_api.cc index 53c7404ef1f9..ac33df7cfe0e 100644 --- chrome/browser/extensions/api/streams_private/streams_private_api.cc +++ chrome/browser/extensions/api/streams_private/streams_private_api.cc @@ -9,6 +9,7 @@ #include "base/lazy_instance.h" #include "base/values.h" +#include "cef/libcef/features/features.h" #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/common/extensions/api/streams_private.h" @@ -79,6 +80,7 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent( if (!web_contents) return; +#if !BUILDFLAG(ENABLE_CEF) // If the request was for a prerender, abort the prerender and do not // continue. This is because plugins cancel prerender, see // http://crbug.com/343590. @@ -88,6 +90,7 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent( prerender_contents->Destroy(prerender::FINAL_STATUS_DOWNLOAD); return; } +#endif // !BUILDFLAG(ENABLE_CEF) auto* browser_context = web_contents->GetBrowserContext(); StreamsPrivateAPI* streams_private = GetStreamsPrivateAPI(browser_context); diff --git content/browser/frame_host/render_frame_host_manager.cc content/browser/frame_host/render_frame_host_manager.cc index b6fb23189522..ccbf05206387 100644 --- content/browser/frame_host/render_frame_host_manager.cc +++ content/browser/frame_host/render_frame_host_manager.cc @@ -903,10 +903,11 @@ bool RenderFrameHostManager::ShouldSwapBrowsingInstancesForNavigation( // TODO(alexmos): This check should've been enforced earlier in the // navigation, in chrome::Navigate(). Verify this, and then convert this to // a CHECK and remove the fallback. - DCHECK_EQ(browser_context, - render_frame_host_->GetSiteInstance()->GetBrowserContext()); - if (browser_context != - render_frame_host_->GetSiteInstance()->GetBrowserContext()) { + const bool is_same = GetContentClient()->browser()->IsSameBrowserContext( + browser_context, + render_frame_host_->GetSiteInstance()->GetBrowserContext()); + DCHECK(is_same); + if (!is_same) { return true; } @@ -1046,7 +1047,8 @@ RenderFrameHostManager::GetSiteInstanceForNavigation( // Double-check that the new SiteInstance is associated with the right // BrowserContext. - DCHECK_EQ(new_instance->GetBrowserContext(), browser_context); + DCHECK(GetContentClient()->browser()->IsSameBrowserContext( + new_instance->GetBrowserContext(), browser_context)); // If |new_instance| is a new SiteInstance for a subframe that requires a // dedicated process, set its process reuse policy so that such subframes are diff --git content/public/browser/content_browser_client.h content/public/browser/content_browser_client.h index c8dcbf0f6daa..19c162f0c76a 100644 --- content/public/browser/content_browser_client.h +++ content/public/browser/content_browser_client.h @@ -366,6 +366,13 @@ class CONTENT_EXPORT ContentBrowserClient { const GURL& current_url, const GURL& new_url); + // Returns true if two browser contexts should be considered the same. CEF + // uses this to treat *Impl and *Proxy contexts as the same. + virtual bool IsSameBrowserContext(BrowserContext* context1, + BrowserContext* context2) { + return context1 == context2; + } + // Returns true if the passed in URL should be assigned as the site of the // current SiteInstance, if it does not yet have a site. virtual bool ShouldAssignSiteForURL(const GURL& url); diff --git extensions/browser/extension_host.cc extensions/browser/extension_host.cc index a5a821840124..a2a8a0d63272 100644 --- extensions/browser/extension_host.cc +++ extensions/browser/extension_host.cc @@ -68,11 +68,12 @@ ExtensionHost::ExtensionHost(const Extension* extension, DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE || host_type == VIEW_TYPE_EXTENSION_DIALOG || host_type == VIEW_TYPE_EXTENSION_POPUP); - host_contents_.reset(WebContents::Create( - WebContents::CreateParams(browser_context_, site_instance))), - content::WebContentsObserver::Observe(host_contents_.get()); + host_contents_owned_.reset(WebContents::Create( + WebContents::CreateParams(browser_context_, site_instance))); + host_contents_ = host_contents_owned_.get(); + content::WebContentsObserver::Observe(host_contents_); host_contents_->SetDelegate(this); - SetViewType(host_contents_.get(), host_type); + SetViewType(host_contents_, host_type); render_view_host_ = host_contents_->GetRenderViewHost(); @@ -87,6 +88,48 @@ ExtensionHost::ExtensionHost(const Extension* extension, dispatcher()->set_delegate(this); } +ExtensionHost::ExtensionHost(ExtensionHostDelegate* delegate, + const Extension* extension, + content::BrowserContext* browser_context, + content::WebContents* host_contents, + const GURL& url, + ViewType host_type) + : delegate_(delegate), + extension_(extension), + extension_id_(extension->id()), + browser_context_(browser_context), + host_contents_(host_contents), + render_view_host_(nullptr), + is_render_view_creation_pending_(false), + has_loaded_once_(false), + document_element_available_(false), + initial_url_(url), + extension_host_type_(host_type) { + DCHECK(delegate); + DCHECK(browser_context); + DCHECK(host_contents); + + // Not used for panels, see PanelHost. + DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE || + host_type == VIEW_TYPE_EXTENSION_DIALOG || + host_type == VIEW_TYPE_EXTENSION_POPUP); + + content::WebContentsObserver::Observe(host_contents_); + SetViewType(host_contents_, host_type); + + render_view_host_ = host_contents_->GetRenderViewHost(); + + // Listen for when an extension is unloaded from the same profile, as it may + // be the same extension that this points to. + ExtensionRegistry::Get(browser_context_)->AddObserver(this); + + // Set up web contents observers and pref observers. + delegate_->OnExtensionHostCreated(host_contents_); + + ExtensionWebContentsObserver::GetForWebContents(host_contents_)-> + dispatcher()->set_delegate(this); +} + ExtensionHost::~ExtensionHost() { ExtensionRegistry::Get(browser_context_)->RemoveObserver(this); diff --git extensions/browser/extension_host.h extensions/browser/extension_host.h index c93e3a48c7ee..ff6e2dbbca56 100644 --- extensions/browser/extension_host.h +++ extensions/browser/extension_host.h @@ -51,13 +51,19 @@ class ExtensionHost : public DeferredStartRenderHost, ExtensionHost(const Extension* extension, content::SiteInstance* site_instance, const GURL& url, ViewType host_type); + ExtensionHost(ExtensionHostDelegate* delegate, + const Extension* extension, + content::BrowserContext* browser_context, + content::WebContents* host_contents, + const GURL& url, + ViewType host_type); ~ExtensionHost() override; // This may be null if the extension has been or is being unloaded. const Extension* extension() const { return extension_; } const std::string& extension_id() const { return extension_id_; } - content::WebContents* host_contents() const { return host_contents_.get(); } + content::WebContents* host_contents() const { return host_contents_; } content::RenderViewHost* render_view_host() const; content::RenderProcessHost* render_process_host() const; bool has_loaded_once() const { return has_loaded_once_; } @@ -175,7 +181,8 @@ class ExtensionHost : public DeferredStartRenderHost, content::BrowserContext* browser_context_; // The host for our HTML content. - std::unique_ptr host_contents_; + std::unique_ptr host_contents_owned_; + content::WebContents* host_contents_; // A weak pointer to the current or pending RenderViewHost. We don't access // this through the host_contents because we want to deal with the pending diff --git extensions/browser/extensions_browser_client.h extensions/browser/extensions_browser_client.h index 9e8ebb1a4d59..b42e88b11f6a 100644 --- extensions/browser/extensions_browser_client.h +++ extensions/browser/extensions_browser_client.h @@ -54,6 +54,7 @@ class ComponentExtensionResourceManager; class Extension; class ExtensionCache; class ExtensionError; +class ExtensionHost; class ExtensionHostDelegate; class ExtensionPrefsObserver; class ExtensionApiFrameIdMap; @@ -109,6 +110,11 @@ class ExtensionsBrowserClient { virtual content::BrowserContext* GetOriginalContext( content::BrowserContext* context) = 0; + // Returns the CEF *Impl context. Used in cases where we want special CEF + // handling without interfering with the side-by-side Chrome build. + virtual content::BrowserContext* GetCefImplContext( + content::BrowserContext* context) { return nullptr; } + #if defined(OS_CHROMEOS) // Returns a user id hash from |context| or an empty string if no hash could // be extracted. @@ -191,6 +197,14 @@ class ExtensionsBrowserClient { virtual std::unique_ptr CreateExtensionHostDelegate() = 0; + // CEF creates a custom ExtensionHost for background pages. If the return + // value is true and |host| is NULL then fail the background host creation. + virtual bool CreateBackgroundExtensionHost( + const Extension* extension, + content::BrowserContext* browser_context, + const GURL& url, + ExtensionHost** host) { return false; } + // Returns true if the client version has updated since the last run. Called // once each time the extensions system is loaded per browser_context. The // implementation may wish to use the BrowserContext to record the current diff --git extensions/browser/process_manager.cc extensions/browser/process_manager.cc index fec28715c0fe..74564954904f 100644 --- extensions/browser/process_manager.cc +++ extensions/browser/process_manager.cc @@ -351,9 +351,16 @@ bool ProcessManager::CreateBackgroundHost(const Extension* extension, return true; // TODO(kalman): return false here? It might break things... DVLOG(1) << "CreateBackgroundHost " << extension->id(); - ExtensionHost* host = - new ExtensionHost(extension, GetSiteInstanceForURL(url).get(), url, - VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); + ExtensionHost* host = nullptr; + if (ExtensionsBrowserClient::Get()->CreateBackgroundExtensionHost( + extension, browser_context_, url, &host) && !host) { + // Explicitly fail if the client can't create the host. + return false; + } + if (!host) { + host = new ExtensionHost(extension, GetSiteInstanceForURL(url).get(), url, + VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); + } host->CreateRenderViewSoon(); OnBackgroundHostCreated(host); return true; diff --git extensions/browser/process_manager_factory.cc extensions/browser/process_manager_factory.cc index e8929c5da255..5ae43b4361a4 100644 --- extensions/browser/process_manager_factory.cc +++ extensions/browser/process_manager_factory.cc @@ -5,6 +5,7 @@ #include "extensions/browser/process_manager_factory.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/extension_registry_factory.h" #include "extensions/browser/lazy_background_task_queue_factory.h" #include "extensions/browser/process_manager.h" @@ -50,6 +51,12 @@ KeyedService* ProcessManagerFactory::BuildServiceInstanceFor( BrowserContext* ProcessManagerFactory::GetBrowserContextToUse( BrowserContext* context) const { + // CEF wants all extension state routed to the *Impl context. + content::BrowserContext* cef_context = + ExtensionsBrowserClient::Get()->GetCefImplContext(context); + if (cef_context) + return cef_context; + // ProcessManager::Create handles guest and incognito profiles, returning an // IncognitoProcessManager in incognito mode. return context;