refactor: Add ElectronBrowserContext::BrowserContexts()
(35-x-y backport) (#46161)
refactor: Add `ElectronBrowserContext::BrowserContexts()` * refactor: add ElectronBrowserContext::BrowserContexts() * refactor: use ElectronBrowserContext::BrowserContexts() in ElectronBrowserMainParts::PostMainMessageLoopRun() * refactor: use ElectronBrowserContext::BrowserContexts() in ElectronExtensionsBrowserClient::IsValidContext() * refactor: use ElectronBrowserContext::BrowserContexts() in ElectronExtensionsBrowserClient::BroadcastEventToRenderers() * refactor: move PartitionKey, BrowserContextMap private * refactor: add ElectronBrowserContext::IsValidContext() decouple ElectronExtensionsBrowserClient from the internals of ElectronBrowserContext
This commit is contained in:
parent
e3d95bb8a4
commit
998de7aa6c
4 changed files with 58 additions and 51 deletions
|
@ -12,6 +12,7 @@
|
||||||
#include "base/barrier_closure.h"
|
#include "base/barrier_closure.h"
|
||||||
#include "base/base_paths.h"
|
#include "base/base_paths.h"
|
||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
|
#include "base/containers/to_vector.h"
|
||||||
#include "base/files/file_path.h"
|
#include "base/files/file_path.h"
|
||||||
#include "base/no_destructor.h"
|
#include "base/no_destructor.h"
|
||||||
#include "base/path_service.h"
|
#include "base/path_service.h"
|
||||||
|
@ -308,14 +309,53 @@ bool DoesDeviceMatch(const base::Value& device,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// partition_id => browser_context
|
||||||
|
struct PartitionKey {
|
||||||
|
PartitionKey(const std::string_view partition, bool in_memory)
|
||||||
|
: type_{Type::Partition}, location_{partition}, in_memory_{in_memory} {}
|
||||||
|
|
||||||
|
explicit PartitionKey(const base::FilePath& file_path)
|
||||||
|
: type_{Type::Path},
|
||||||
|
location_{file_path.AsUTF8Unsafe()},
|
||||||
|
in_memory_{false} {}
|
||||||
|
|
||||||
|
friend auto operator<=>(const PartitionKey&, const PartitionKey&) = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class Type { Partition, Path };
|
||||||
|
|
||||||
|
Type type_;
|
||||||
|
std::string location_;
|
||||||
|
bool in_memory_;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] auto& ContextMap() {
|
||||||
|
static base::NoDestructor<
|
||||||
|
std::map<PartitionKey, std::unique_ptr<ElectronBrowserContext>>>
|
||||||
|
map;
|
||||||
|
return *map;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// static
|
// static
|
||||||
ElectronBrowserContext::BrowserContextMap&
|
std::vector<ElectronBrowserContext*> ElectronBrowserContext::BrowserContexts() {
|
||||||
ElectronBrowserContext::browser_context_map() {
|
return base::ToVector(ContextMap(),
|
||||||
static base::NoDestructor<ElectronBrowserContext::BrowserContextMap>
|
[](auto& iter) { return iter.second.get(); });
|
||||||
browser_context_map;
|
}
|
||||||
return *browser_context_map;
|
|
||||||
|
bool ElectronBrowserContext::IsValidContext(const void* context) {
|
||||||
|
return std::ranges::any_of(ContextMap(), [context](const auto& iter) {
|
||||||
|
return iter.second.get() == context;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void ElectronBrowserContext::DestroyAllContexts() {
|
||||||
|
auto& map = ContextMap();
|
||||||
|
// Avoid UAF by destroying the default context last. See ba629e3 for info.
|
||||||
|
const auto extracted = map.extract(PartitionKey{"", false});
|
||||||
|
map.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
ElectronBrowserContext::ElectronBrowserContext(
|
ElectronBrowserContext::ElectronBrowserContext(
|
||||||
|
@ -833,7 +873,7 @@ ElectronBrowserContext* ElectronBrowserContext::From(
|
||||||
const std::string& partition,
|
const std::string& partition,
|
||||||
bool in_memory,
|
bool in_memory,
|
||||||
base::Value::Dict options) {
|
base::Value::Dict options) {
|
||||||
auto& context = browser_context_map()[PartitionKey(partition, in_memory)];
|
auto& context = ContextMap()[PartitionKey(partition, in_memory)];
|
||||||
if (!context) {
|
if (!context) {
|
||||||
context.reset(new ElectronBrowserContext{std::cref(partition), in_memory,
|
context.reset(new ElectronBrowserContext{std::cref(partition), in_memory,
|
||||||
std::move(options)});
|
std::move(options)});
|
||||||
|
@ -844,7 +884,7 @@ ElectronBrowserContext* ElectronBrowserContext::From(
|
||||||
ElectronBrowserContext* ElectronBrowserContext::FromPath(
|
ElectronBrowserContext* ElectronBrowserContext::FromPath(
|
||||||
const base::FilePath& path,
|
const base::FilePath& path,
|
||||||
base::Value::Dict options) {
|
base::Value::Dict options) {
|
||||||
auto& context = browser_context_map()[PartitionKey(path)];
|
auto& context = ContextMap()[PartitionKey(path)];
|
||||||
if (!context) {
|
if (!context) {
|
||||||
context.reset(
|
context.reset(
|
||||||
new ElectronBrowserContext{std::cref(path), false, std::move(options)});
|
new ElectronBrowserContext{std::cref(path), false, std::move(options)});
|
||||||
|
|
|
@ -61,28 +61,9 @@ class ElectronBrowserContext : public content::BrowserContext {
|
||||||
ElectronBrowserContext(const ElectronBrowserContext&) = delete;
|
ElectronBrowserContext(const ElectronBrowserContext&) = delete;
|
||||||
ElectronBrowserContext& operator=(const ElectronBrowserContext&) = delete;
|
ElectronBrowserContext& operator=(const ElectronBrowserContext&) = delete;
|
||||||
|
|
||||||
// partition_id => browser_context
|
[[nodiscard]] static std::vector<ElectronBrowserContext*> BrowserContexts();
|
||||||
struct PartitionKey {
|
|
||||||
PartitionKey(const std::string_view partition, bool in_memory)
|
|
||||||
: type_{Type::Partition}, location_{partition}, in_memory_{in_memory} {}
|
|
||||||
|
|
||||||
explicit PartitionKey(const base::FilePath& file_path)
|
[[nodiscard]] static bool IsValidContext(const void* context);
|
||||||
: type_{Type::Path},
|
|
||||||
location_{file_path.AsUTF8Unsafe()},
|
|
||||||
in_memory_{false} {}
|
|
||||||
|
|
||||||
friend auto operator<=>(const PartitionKey&, const PartitionKey&) = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum class Type { Partition, Path };
|
|
||||||
|
|
||||||
Type type_;
|
|
||||||
std::string location_;
|
|
||||||
bool in_memory_;
|
|
||||||
};
|
|
||||||
|
|
||||||
using BrowserContextMap =
|
|
||||||
std::map<PartitionKey, std::unique_ptr<ElectronBrowserContext>>;
|
|
||||||
|
|
||||||
// Get or create the BrowserContext according to its |partition| and
|
// Get or create the BrowserContext according to its |partition| and
|
||||||
// |in_memory|. The |options| will be passed to constructor when there is no
|
// |in_memory|. The |options| will be passed to constructor when there is no
|
||||||
|
@ -97,7 +78,7 @@ class ElectronBrowserContext : public content::BrowserContext {
|
||||||
static ElectronBrowserContext* FromPath(const base::FilePath& path,
|
static ElectronBrowserContext* FromPath(const base::FilePath& path,
|
||||||
base::Value::Dict options = {});
|
base::Value::Dict options = {});
|
||||||
|
|
||||||
static BrowserContextMap& browser_context_map();
|
static void DestroyAllContexts();
|
||||||
|
|
||||||
void SetUserAgent(const std::string& user_agent);
|
void SetUserAgent(const std::string& user_agent);
|
||||||
std::string GetUserAgent() const;
|
std::string GetUserAgent() const;
|
||||||
|
|
|
@ -554,11 +554,9 @@ void ElectronBrowserMainParts::PostMainMessageLoopRun() {
|
||||||
|
|
||||||
// Shutdown the DownloadManager before destroying Node to prevent
|
// Shutdown the DownloadManager before destroying Node to prevent
|
||||||
// DownloadItem callbacks from crashing.
|
// DownloadItem callbacks from crashing.
|
||||||
for (auto& iter : ElectronBrowserContext::browser_context_map()) {
|
for (auto* browser_context : ElectronBrowserContext::BrowserContexts()) {
|
||||||
auto* download_manager = iter.second.get()->GetDownloadManager();
|
if (auto* download_manager = browser_context->GetDownloadManager())
|
||||||
if (download_manager) {
|
|
||||||
download_manager->Shutdown();
|
download_manager->Shutdown();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown utility process created with Electron API before
|
// Shutdown utility process created with Electron API before
|
||||||
|
@ -598,11 +596,7 @@ void ElectronBrowserMainParts::PostMainMessageLoopRun() {
|
||||||
node_bindings_->set_uv_env(nullptr);
|
node_bindings_->set_uv_env(nullptr);
|
||||||
node_env_.reset();
|
node_env_.reset();
|
||||||
|
|
||||||
auto default_context_key = ElectronBrowserContext::PartitionKey("", false);
|
ElectronBrowserContext::DestroyAllContexts();
|
||||||
std::unique_ptr<ElectronBrowserContext> default_context = std::move(
|
|
||||||
ElectronBrowserContext::browser_context_map()[default_context_key]);
|
|
||||||
ElectronBrowserContext::browser_context_map().clear();
|
|
||||||
default_context.reset();
|
|
||||||
|
|
||||||
fake_browser_process_->PostMainMessageLoopRun();
|
fake_browser_process_->PostMainMessageLoopRun();
|
||||||
content::DevToolsAgentHost::StopRemoteDebuggingPipeHandler();
|
content::DevToolsAgentHost::StopRemoteDebuggingPipeHandler();
|
||||||
|
|
|
@ -85,12 +85,7 @@ bool ElectronExtensionsBrowserClient::AreExtensionsDisabled(
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ElectronExtensionsBrowserClient::IsValidContext(void* context) {
|
bool ElectronExtensionsBrowserClient::IsValidContext(void* context) {
|
||||||
auto& context_map = ElectronBrowserContext::browser_context_map();
|
return ElectronBrowserContext::IsValidContext(context);
|
||||||
for (auto const& entry : context_map) {
|
|
||||||
if (entry.second && entry.second.get() == context)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ElectronExtensionsBrowserClient::IsSameContext(BrowserContext* first,
|
bool ElectronExtensionsBrowserClient::IsSameContext(BrowserContext* first,
|
||||||
|
@ -341,13 +336,10 @@ void ElectronExtensionsBrowserClient::BroadcastEventToRenderers(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const& [key, browser_context] :
|
for (auto* browser_context : ElectronBrowserContext::BrowserContexts()) {
|
||||||
ElectronBrowserContext::browser_context_map()) {
|
extensions::EventRouter::Get(browser_context)
|
||||||
if (browser_context) {
|
->BroadcastEvent(std::make_unique<extensions::Event>(
|
||||||
extensions::EventRouter::Get(browser_context.get())
|
histogram_value, event_name, args.Clone()));
|
||||||
->BroadcastEvent(std::make_unique<extensions::Event>(
|
|
||||||
histogram_value, event_name, args.Clone()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue