1diff --git chrome/browser/extensions/api/streams_private/streams_private_api.cc chrome/browser/extensions/api/streams_private/streams_private_api.cc 2index 5c903a13a14e..c85964a7bab1 100644 3--- chrome/browser/extensions/api/streams_private/streams_private_api.cc 4+++ chrome/browser/extensions/api/streams_private/streams_private_api.cc 5@@ -6,6 +6,7 @@ 6 7 #include <utility> 8 9+#include "cef/libcef/features/runtime.h" 10 #include "chrome/browser/extensions/extension_tab_util.h" 11 #include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h" 12 #include "components/no_state_prefetch/browser/no_state_prefetch_contents.h" 13@@ -18,6 +19,10 @@ 14 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" 15 #include "extensions/common/manifest_handlers/mime_types_handler.h" 16 17+#if BUILDFLAG(ENABLE_CEF) 18+#include "cef/libcef/browser/extensions/alloy_extensions_util.h" 19+#endif 20+ 21 namespace extensions { 22 23 void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent( 24@@ -42,6 +47,7 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent( 25 if (!web_contents) 26 return; 27 28+ if (!cef::IsAlloyRuntimeEnabled()) { 29 // If the request was for NoStatePrefetch, abort the prefetcher and do not 30 // continue. This is because plugins cancel NoStatePrefetch, see 31 // http://crbug.com/343590. 32@@ -52,6 +58,7 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent( 33 no_state_prefetch_contents->Destroy(prerender::FINAL_STATUS_DOWNLOAD); 34 return; 35 } 36+ } 37 38 auto* browser_context = web_contents->GetBrowserContext(); 39 40@@ -78,9 +85,18 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent( 41 // forms of zooming won't work). 42 // TODO(1042323): Present a coherent representation of a tab id for portal 43 // contents. 44- int tab_id = web_contents->GetOuterWebContents() 45- ? SessionID::InvalidValue().id() 46- : ExtensionTabUtil::GetTabId(web_contents); 47+ int tab_id; 48+ if (web_contents->GetOuterWebContents()) { 49+ tab_id = SessionID::InvalidValue().id(); 50+ } else 51+#if BUILDFLAG(ENABLE_CEF) 52+ if (cef::IsAlloyRuntimeEnabled()) { 53+ tab_id = alloy::GetTabIdForWebContents(web_contents); 54+ } else 55+#endif // BUILDFLAG(ENABLE_CEF) 56+ { 57+ tab_id = ExtensionTabUtil::GetTabId(web_contents); 58+ } 59 60 std::unique_ptr<StreamContainer> stream_container( 61 new StreamContainer(tab_id, embedded, handler_url, extension_id, 62diff --git extensions/browser/extension_host.cc extensions/browser/extension_host.cc 63index 231a3b6c8ce1..14776d981f50 100644 64--- extensions/browser/extension_host.cc 65+++ extensions/browser/extension_host.cc 66@@ -63,11 +63,12 @@ ExtensionHost::ExtensionHost(const Extension* extension, 67 DCHECK(host_type == mojom::ViewType::kExtensionBackgroundPage || 68 host_type == mojom::ViewType::kExtensionDialog || 69 host_type == mojom::ViewType::kExtensionPopup); 70- host_contents_ = WebContents::Create( 71+ host_contents_owned_ = WebContents::Create( 72 WebContents::CreateParams(browser_context_, site_instance)), 73- content::WebContentsObserver::Observe(host_contents_.get()); 74+ host_contents_ = host_contents_owned_.get(); 75+ content::WebContentsObserver::Observe(host_contents_); 76 host_contents_->SetDelegate(this); 77- SetViewType(host_contents_.get(), host_type); 78+ SetViewType(host_contents_, host_type); 79 main_frame_host_ = host_contents_->GetMainFrame(); 80 81 // Listen for when an extension is unloaded from the same profile, as it may 82@@ -81,6 +82,44 @@ ExtensionHost::ExtensionHost(const Extension* extension, 83 dispatcher()->set_delegate(this); 84 } 85 86+ExtensionHost::ExtensionHost(ExtensionHostDelegate* delegate, 87+ const Extension* extension, 88+ content::BrowserContext* browser_context, 89+ content::WebContents* host_contents, 90+ const GURL& url, 91+ mojom::ViewType host_type) 92+ : delegate_(delegate), 93+ extension_(extension), 94+ extension_id_(extension->id()), 95+ browser_context_(browser_context), 96+ host_contents_(host_contents), 97+ initial_url_(url), 98+ extension_host_type_(host_type) { 99+ DCHECK(delegate); 100+ DCHECK(browser_context); 101+ DCHECK(host_contents); 102+ 103+ // Not used for panels, see PanelHost. 104+ DCHECK(host_type == mojom::ViewType::kExtensionBackgroundPage || 105+ host_type == mojom::ViewType::kExtensionDialog || 106+ host_type == mojom::ViewType::kExtensionPopup); 107+ 108+ content::WebContentsObserver::Observe(host_contents_); 109+ SetViewType(host_contents_, host_type); 110+ 111+ main_frame_host_ = host_contents_->GetMainFrame(); 112+ 113+ // Listen for when an extension is unloaded from the same profile, as it may 114+ // be the same extension that this points to. 115+ ExtensionRegistry::Get(browser_context_)->AddObserver(this); 116+ 117+ // Set up web contents observers and pref observers. 118+ delegate_->OnExtensionHostCreated(host_contents_); 119+ 120+ ExtensionWebContentsObserver::GetForWebContents(host_contents_)-> 121+ dispatcher()->set_delegate(this); 122+} 123+ 124 ExtensionHost::~ExtensionHost() { 125 ExtensionRegistry::Get(browser_context_)->RemoveObserver(this); 126 127diff --git extensions/browser/extension_host.h extensions/browser/extension_host.h 128index 305726557f2e..caa4b798a013 100644 129--- extensions/browser/extension_host.h 130+++ extensions/browser/extension_host.h 131@@ -53,13 +53,19 @@ class ExtensionHost : public DeferredStartRenderHost, 132 content::SiteInstance* site_instance, 133 const GURL& url, 134 mojom::ViewType host_type); 135+ ExtensionHost(ExtensionHostDelegate* delegate, 136+ const Extension* extension, 137+ content::BrowserContext* browser_context, 138+ content::WebContents* host_contents, 139+ const GURL& url, 140+ mojom::ViewType host_type); 141 ~ExtensionHost() override; 142 143 // This may be null if the extension has been or is being unloaded. 144 const Extension* extension() const { return extension_; } 145 146 const std::string& extension_id() const { return extension_id_; } 147- content::WebContents* host_contents() const { return host_contents_.get(); } 148+ content::WebContents* host_contents() const { return host_contents_; } 149 content::RenderFrameHost* main_frame_host() const { return main_frame_host_; } 150 content::RenderProcessHost* render_process_host() const; 151 bool has_loaded_once() const { return has_loaded_once_; } 152@@ -182,7 +188,8 @@ class ExtensionHost : public DeferredStartRenderHost, 153 content::BrowserContext* browser_context_; 154 155 // The host for our HTML content. 156- std::unique_ptr<content::WebContents> host_contents_; 157+ std::unique_ptr<content::WebContents> host_contents_owned_; 158+ content::WebContents* host_contents_; 159 160 // A pointer to the current or speculative main frame in `host_contents_`. We 161 // can't access this frame through the `host_contents_` directly as it does 162diff --git extensions/browser/extensions_browser_client.h extensions/browser/extensions_browser_client.h 163index 7eb3d073c7b7..3844a9c6033a 100644 164--- extensions/browser/extensions_browser_client.h 165+++ extensions/browser/extensions_browser_client.h 166@@ -27,6 +27,7 @@ 167 #include "ui/base/page_transition_types.h" 168 169 class ExtensionFunctionRegistry; 170+class GURL; 171 class PrefService; 172 173 namespace base { 174@@ -62,6 +63,7 @@ class ComponentExtensionResourceManager; 175 class Extension; 176 class ExtensionCache; 177 class ExtensionError; 178+class ExtensionHost; 179 class ExtensionHostDelegate; 180 class ExtensionSet; 181 class ExtensionSystem; 182@@ -204,6 +206,14 @@ class ExtensionsBrowserClient { 183 virtual std::unique_ptr<ExtensionHostDelegate> 184 CreateExtensionHostDelegate() = 0; 185 186+ // CEF creates a custom ExtensionHost for background pages. If the return 187+ // value is true and |host| is NULL then fail the background host creation. 188+ virtual bool CreateBackgroundExtensionHost( 189+ const Extension* extension, 190+ content::BrowserContext* browser_context, 191+ const GURL& url, 192+ ExtensionHost** host) { return false; } 193+ 194 // Returns true if the client version has updated since the last run. Called 195 // once each time the extensions system is loaded per browser_context. The 196 // implementation may wish to use the BrowserContext to record the current 197diff --git extensions/browser/process_manager.cc extensions/browser/process_manager.cc 198index 26bff09c646b..830ff12c5fc9 100644 199--- extensions/browser/process_manager.cc 200+++ extensions/browser/process_manager.cc 201@@ -392,9 +392,17 @@ bool ProcessManager::CreateBackgroundHost(const Extension* extension, 202 return true; // TODO(kalman): return false here? It might break things... 203 204 DVLOG(1) << "CreateBackgroundHost " << extension->id(); 205- ExtensionHost* host = 206+ ExtensionHost* host = nullptr; 207+ if (ExtensionsBrowserClient::Get()->CreateBackgroundExtensionHost( 208+ extension, browser_context_, url, &host) && !host) { 209+ // Explicitly fail if the client can't create the host. 210+ return false; 211+ } 212+ if (!host) { 213+ host = 214 new ExtensionHost(extension, GetSiteInstanceForURL(url).get(), url, 215 mojom::ViewType::kExtensionBackgroundPage); 216+ } 217 host->CreateRendererSoon(); 218 OnBackgroundHostCreated(host); 219 return true; 220