diff --git a/shell/browser/api/electron_api_global_shortcut.cc b/shell/browser/api/electron_api_global_shortcut.cc index b0aedf148bb1..d78314e50ec7 100644 --- a/shell/browser/api/electron_api_global_shortcut.cc +++ b/shell/browser/api/electron_api_global_shortcut.cc @@ -119,7 +119,7 @@ bool GlobalShortcut::Register(const ui::Accelerator& accelerator, } if (instance->IsRegistrationHandledExternally()) { - auto* context = ElectronBrowserContext::From("", false); + auto* context = ElectronBrowserContext::GetDefaultBrowserContext(); PrefService* prefs = context->prefs(); // Need a unique profile id. Set one if not generated yet, otherwise re-use diff --git a/shell/browser/api/electron_api_session.cc b/shell/browser/api/electron_api_session.cc index ffc710b4a026..06664761261a 100644 --- a/shell/browser/api/electron_api_session.cc +++ b/shell/browser/api/electron_api_session.cc @@ -1679,7 +1679,7 @@ gin::Handle Session::FromPartition(v8::Isolate* isolate, ElectronBrowserContext* browser_context; if (partition.empty()) { browser_context = - ElectronBrowserContext::From("", false, std::move(options)); + ElectronBrowserContext::GetDefaultBrowserContext(std::move(options)); } else if (partition.starts_with(kPersistPrefix)) { std::string name = partition.substr(8); browser_context = diff --git a/shell/browser/electron_browser_context.cc b/shell/browser/electron_browser_context.cc index fd89254e23b3..908d23ed5ad2 100644 --- a/shell/browser/electron_browser_context.cc +++ b/shell/browser/electron_browser_context.cc @@ -318,6 +318,14 @@ ElectronBrowserContext::browser_context_map() { return *browser_context_map; } +// static +void ElectronBrowserContext::DestroyAllContexts() { + auto& map = browser_context_map(); + // Avoid UAF by destroying the default context last. See ba629e3 for info. + const auto extracted = map.extract(PartitionKey{"", false}); + map.clear(); +} + ElectronBrowserContext::ElectronBrowserContext( const PartitionOrPath partition_location, bool in_memory, @@ -841,6 +849,12 @@ ElectronBrowserContext* ElectronBrowserContext::From( return context.get(); } +// static +ElectronBrowserContext* ElectronBrowserContext::GetDefaultBrowserContext( + base::Value::Dict options) { + return ElectronBrowserContext::From("", false, std::move(options)); +} + ElectronBrowserContext* ElectronBrowserContext::FromPath( const base::FilePath& path, base::Value::Dict options) { diff --git a/shell/browser/electron_browser_context.h b/shell/browser/electron_browser_context.h index 29c2c119655b..3ae8b2e2f13f 100644 --- a/shell/browser/electron_browser_context.h +++ b/shell/browser/electron_browser_context.h @@ -84,6 +84,10 @@ class ElectronBrowserContext : public content::BrowserContext { using BrowserContextMap = std::map>; + // Get or create the default BrowserContext. + static ElectronBrowserContext* GetDefaultBrowserContext( + base::Value::Dict options = {}); + // Get or create the BrowserContext according to its |partition| and // |in_memory|. The |options| will be passed to constructor when there is no // existing BrowserContext. @@ -99,6 +103,8 @@ class ElectronBrowserContext : public content::BrowserContext { static BrowserContextMap& browser_context_map(); + static void DestroyAllContexts(); + void SetUserAgent(const std::string& user_agent); std::string GetUserAgent() const; bool can_use_http_cache() const { return use_cache_; } diff --git a/shell/browser/electron_browser_main_parts.cc b/shell/browser/electron_browser_main_parts.cc index dfdec38f1609..5e5a8b6ae765 100644 --- a/shell/browser/electron_browser_main_parts.cc +++ b/shell/browser/electron_browser_main_parts.cc @@ -598,11 +598,7 @@ void ElectronBrowserMainParts::PostMainMessageLoopRun() { node_bindings_->set_uv_env(nullptr); node_env_.reset(); - auto default_context_key = ElectronBrowserContext::PartitionKey("", false); - std::unique_ptr default_context = std::move( - ElectronBrowserContext::browser_context_map()[default_context_key]); - ElectronBrowserContext::browser_context_map().clear(); - default_context.reset(); + ElectronBrowserContext::DestroyAllContexts(); fake_browser_process_->PostMainMessageLoopRun(); content::DevToolsAgentHost::StopRemoteDebuggingPipeHandler(); diff --git a/shell/browser/extensions/electron_extensions_browser_client.cc b/shell/browser/extensions/electron_extensions_browser_client.cc index 905414fffb20..f74f1a7e61a3 100644 --- a/shell/browser/extensions/electron_extensions_browser_client.cc +++ b/shell/browser/extensions/electron_extensions_browser_client.cc @@ -112,7 +112,7 @@ BrowserContext* ElectronExtensionsBrowserClient::GetOriginalContext( BrowserContext* context) { DCHECK(context); if (context->IsOffTheRecord()) { - return ElectronBrowserContext::From("", false); + return ElectronBrowserContext::GetDefaultBrowserContext(); } else { return context; } diff --git a/shell/browser/net/electron_url_loader_factory.cc b/shell/browser/net/electron_url_loader_factory.cc index d6925d893f2e..bc8bd61be36f 100644 --- a/shell/browser/net/electron_url_loader_factory.cc +++ b/shell/browser/net/electron_url_loader_factory.cc @@ -544,8 +544,7 @@ void ElectronURLLoaderFactory::StartLoadingHttp( request->method != net::HttpRequestHeaders::kHeadMethod) dict.Get("uploadData", &upload_data); - ElectronBrowserContext* browser_context = - ElectronBrowserContext::From("", false); + auto* browser_context = ElectronBrowserContext::GetDefaultBrowserContext(); v8::Local value; if (dict.Get("session", &value)) { if (value->IsNull()) { diff --git a/shell/browser/ui/devtools_manager_delegate.cc b/shell/browser/ui/devtools_manager_delegate.cc index bdec61a501c3..2825db7e2526 100644 --- a/shell/browser/ui/devtools_manager_delegate.cc +++ b/shell/browser/ui/devtools_manager_delegate.cc @@ -138,7 +138,7 @@ bool DevToolsManagerDelegate::HasBundledFrontendResources() { } content::BrowserContext* DevToolsManagerDelegate::GetDefaultBrowserContext() { - return ElectronBrowserContext::From("", false); + return ElectronBrowserContext::GetDefaultBrowserContext(); } } // namespace electron