87c183df6a
* chore: bump chromium in DEPS to 109.0.5386.0 * chore: bump chromium in DEPS to 109.0.5388.0 * chore: bump chromium in DEPS to 109.0.5390.0 * chore: bump chromium in DEPS to 109.0.5392.0 * chore: bump chromium in DEPS to 109.0.5394.0 * chore: bump chromium in DEPS to 109.0.5396.0 * chore: bump chromium in DEPS to 109.0.5398.0 * chore: bump chromium in DEPS to 109.0.5400.0 * chore: update galactus * chore: bump chromium in DEPS to 109.0.5402.0 * chore: bump chromium in DEPS to 109.0.5403.0 * chore: bump chromium in DEPS to 109.0.5406.0 * chore: update patches * 4004247: Delete unused DocumentWebContentsDelegate Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4004247 * chore: bump chromium in DEPS to 109.0.5408.1 * chore: update patches * 3949284: Support pkey debug mode without pkey 0 access Ref: https://chromium-review.googlesource.com/c/chromium/src/+/3949284 * chore: bump chromium in DEPS to 109.0.5410.0 * chore: update patches * 4000944: [Extensions] Create an API directory in //chrome/renderer/extensions Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4000944 * 3988524: Remove DocumentOverlayWindowViews | https://chromium-review.googlesource.com/c/chromium/src/+/3988524 Co-authored-by: George Xu <33054982+georgexu99@users.noreply.github.com> * chore: bump chromium in DEPS to 109.0.5412.0 * chore: update patches * 3984022: Add AddChildWindowToBrowser to DisplayClient mojo interface Ref: https://chromium-review.googlesource.com/c/chromium/src/+/3984022 * 3957079: Delete the CryptoToken component extension and internal API Ref: https://chromium-review.googlesource.com/c/chromium/src/+/3957079 * 4004421: Migreate ScopedAllowIO to ScopedAllowBlocking Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4004421 Co-authored-by: George Xu <georgexu99@users.noreply.github.com> * chore: bump chromium in DEPS to 109.0.5414.0 * chore: update patches * 4016180: Split PPAPI Mojo interfaces out of RenderFrameHostImpl. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4016180 * 3970838: [MPArch] Convert HostZoomMap and ZoomController off of RenderViewHost ids Ref: https://chromium-review.googlesource.com/c/chromium/src/+/3970838 * 3997795: Don't add Chromium as a login item Ref: https://chromium-review.googlesource.com/c/chromium/src/+/3997795 * 3993482: Remove RefCountedString::TakeString Ref: https://chromium-review.googlesource.com/c/chromium/src/+/3993482 * 3990749: Allow forward-declared sources in base::ScopedObservation<> Ref: https://chromium-review.googlesource.com/c/chromium/src/+/3990749 * fixup! 3957079: Delete the CryptoToken component extension and internal API * chore: bump chromium in DEPS to 110.0.5415.0 * 3883790: Move devtools_frame_token to the RenderFrameHost, to preserve RFH identity across MPArch activations. https://chromium-review.googlesource.com/c/chromium/src/+/3883790 * 4022205: Move license tooling into //tools/licenses https://chromium-review.googlesource.com/c/chromium/src/+/4022205 * chore: fixup patch indices * fixup! 3957079: Delete the CryptoToken component extension and internal API * 4008687: Finish ScopedAllowIO migration https://chromium-review.googlesource.com/c/chromium/src/+/4008687 * 3991548: Move WindowButtonOrderObserver and WindowFrameAction to LinuxUi https://chromium-review.googlesource.com/c/chromium/src/+/3991548 * fixup! 3984022: Add AddChildWindowToBrowser to DisplayClient mojo interface * 4016595: Migrate non-default ScopedObservation<> instantiations to ScopedObservationTraits<> in chrome/browser/ https://chromium-review.googlesource.com/c/chromium/src/+/4016595 * 4000481: Rename :chromedriver to :chromedriver_server Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4000481 * 4008687: Finish ScopedAllowIO migration https://chromium-review.googlesource.com/c/chromium/src/+/4008687 * 3988524: Remove DocumentOverlayWindowViews https://chromium-review.googlesource.com/c/chromium/src/+/3988524 * fixup! 3997795: Don't add Chromium as a login item * chore: fixup patches * 3996872: Plumb input event task runner to EventFactoryEvdev https://chromium-review.googlesource.com/c/chromium/src/+/3996872 * 4014994: Enable SiteIsolationForGuests by default. https://chromium-review.googlesource.com/c/chromium/src/+/4014994 * chore: adopt new thread restrictions api for //electron (#36357) chore: add thread blocking api * fixup! 4014994: Enable SiteIsolationForGuests by default. * pull parent HWND for dialogs on ui thread * chore: set parent_window in MessageBoxSettings * chore: remove redundant patch * chore: revert accidental deletion * chore: update patches Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: Samuel Attard <sattard@salesforce.com> Co-authored-by: Keeley Hammond <khammond@slack-corp.com> Co-authored-by: VerteDinde <vertedinde@electronjs.org> Co-authored-by: George Xu <33054982+georgexu99@users.noreply.github.com> Co-authored-by: George Xu <georgexu99@users.noreply.github.com> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> Co-authored-by: Robo <hop2deep@gmail.com> Co-authored-by: Jeremy Rose <jeremya@chromium.org> Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
688 lines
24 KiB
C++
688 lines
24 KiB
C++
// Copyright (c) 2013 GitHub, Inc.
|
|
// Use of this source code is governed by the MIT license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "shell/browser/electron_browser_main_parts.h"
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "base/base_switches.h"
|
|
#include "base/command_line.h"
|
|
#include "base/feature_list.h"
|
|
#include "base/i18n/rtl.h"
|
|
#include "base/metrics/field_trial.h"
|
|
#include "base/path_service.h"
|
|
#include "base/run_loop.h"
|
|
#include "base/strings/string_number_conversions.h"
|
|
#include "base/strings/utf_string_conversions.h"
|
|
#include "chrome/browser/icon_manager.h"
|
|
#include "chrome/browser/ui/color/chrome_color_mixers.h"
|
|
#include "chrome/common/chrome_paths.h"
|
|
#include "chrome/common/chrome_switches.h"
|
|
#include "components/os_crypt/key_storage_config_linux.h"
|
|
#include "components/os_crypt/os_crypt.h"
|
|
#include "content/browser/browser_main_loop.h" // nogncheck
|
|
#include "content/public/browser/browser_child_process_host_delegate.h"
|
|
#include "content/public/browser/browser_child_process_host_iterator.h"
|
|
#include "content/public/browser/browser_thread.h"
|
|
#include "content/public/browser/child_process_data.h"
|
|
#include "content/public/browser/child_process_security_policy.h"
|
|
#include "content/public/browser/device_service.h"
|
|
#include "content/public/browser/first_party_sets_handler.h"
|
|
#include "content/public/browser/web_ui_controller_factory.h"
|
|
#include "content/public/common/content_features.h"
|
|
#include "content/public/common/content_switches.h"
|
|
#include "content/public/common/process_type.h"
|
|
#include "content/public/common/result_codes.h"
|
|
#include "electron/buildflags/buildflags.h"
|
|
#include "electron/fuses.h"
|
|
#include "media/base/localized_strings.h"
|
|
#include "services/network/public/cpp/features.h"
|
|
#include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
|
|
#include "shell/app/electron_main_delegate.h"
|
|
#include "shell/browser/api/electron_api_app.h"
|
|
#include "shell/browser/api/electron_api_utility_process.h"
|
|
#include "shell/browser/browser.h"
|
|
#include "shell/browser/browser_process_impl.h"
|
|
#include "shell/browser/electron_browser_client.h"
|
|
#include "shell/browser/electron_browser_context.h"
|
|
#include "shell/browser/electron_web_ui_controller_factory.h"
|
|
#include "shell/browser/feature_list.h"
|
|
#include "shell/browser/javascript_environment.h"
|
|
#include "shell/browser/media/media_capture_devices_dispatcher.h"
|
|
#include "shell/browser/ui/devtools_manager_delegate.h"
|
|
#include "shell/common/api/electron_bindings.h"
|
|
#include "shell/common/application_info.h"
|
|
#include "shell/common/electron_paths.h"
|
|
#include "shell/common/gin_helper/trackable_object.h"
|
|
#include "shell/common/logging.h"
|
|
#include "shell/common/node_bindings.h"
|
|
#include "shell/common/node_includes.h"
|
|
#include "third_party/abseil-cpp/absl/types/optional.h"
|
|
#include "ui/base/idle/idle.h"
|
|
#include "ui/base/l10n/l10n_util.h"
|
|
#include "ui/base/ui_base_switches.h"
|
|
|
|
#if defined(USE_AURA)
|
|
#include "ui/display/display.h"
|
|
#include "ui/display/screen.h"
|
|
#include "ui/views/widget/desktop_aura/desktop_screen.h"
|
|
#include "ui/wm/core/wm_state.h"
|
|
#endif
|
|
|
|
#if BUILDFLAG(IS_LINUX)
|
|
#include "base/environment.h"
|
|
#include "base/threading/thread_task_runner_handle.h"
|
|
#include "device/bluetooth/bluetooth_adapter_factory.h"
|
|
#include "device/bluetooth/dbus/dbus_bluez_manager_wrapper_linux.h"
|
|
#include "electron/electron_gtk_stubs.h"
|
|
#include "ui/base/cursor/cursor_factory.h"
|
|
#include "ui/base/ime/linux/linux_input_method_context_factory.h"
|
|
#include "ui/gfx/color_utils.h"
|
|
#include "ui/gtk/gtk_compat.h" // nogncheck
|
|
#include "ui/gtk/gtk_util.h" // nogncheck
|
|
#include "ui/linux/linux_ui.h"
|
|
#include "ui/linux/linux_ui_factory.h"
|
|
#include "ui/linux/linux_ui_getter.h"
|
|
#include "ui/ozone/public/ozone_platform.h"
|
|
#endif
|
|
|
|
#if BUILDFLAG(IS_WIN)
|
|
#include "ui/base/l10n/l10n_util_win.h"
|
|
#include "ui/display/win/dpi.h"
|
|
#include "ui/gfx/system_fonts_win.h"
|
|
#include "ui/strings/grit/app_locale_settings.h"
|
|
#endif
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
|
#include "components/os_crypt/keychain_password_mac.h"
|
|
#include "services/device/public/cpp/geolocation/geolocation_manager.h"
|
|
#include "shell/browser/ui/cocoa/views_delegate_mac.h"
|
|
#else
|
|
#include "shell/browser/ui/views/electron_views_delegate.h"
|
|
#endif
|
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
|
#include "components/keyed_service/content/browser_context_dependency_manager.h"
|
|
#include "extensions/browser/browser_context_keyed_service_factories.h"
|
|
#include "extensions/common/extension_api.h"
|
|
#include "shell/browser/extensions/electron_browser_context_keyed_service_factories.h"
|
|
#include "shell/browser/extensions/electron_extensions_browser_client.h"
|
|
#include "shell/common/extensions/electron_extensions_client.h"
|
|
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
|
|
|
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
|
#include "chrome/browser/spellchecker/spellcheck_factory.h" // nogncheck
|
|
#endif
|
|
|
|
#if BUILDFLAG(ENABLE_PLUGINS)
|
|
#include "content/public/browser/plugin_service.h"
|
|
#include "shell/common/plugin_info.h"
|
|
#endif // BUILDFLAG(ENABLE_PLUGINS)
|
|
|
|
namespace electron {
|
|
|
|
namespace {
|
|
|
|
#if BUILDFLAG(IS_LINUX)
|
|
class LinuxUiGetterImpl : public ui::LinuxUiGetter {
|
|
public:
|
|
LinuxUiGetterImpl() = default;
|
|
~LinuxUiGetterImpl() override = default;
|
|
ui::LinuxUiTheme* GetForWindow(aura::Window* window) override {
|
|
return GetForProfile(nullptr);
|
|
}
|
|
ui::LinuxUiTheme* GetForProfile(Profile* profile) override {
|
|
return ui::GetLinuxUiTheme(ui::SystemTheme::kGtk);
|
|
}
|
|
};
|
|
#endif
|
|
|
|
template <typename T>
|
|
void Erase(T* container, typename T::iterator iter) {
|
|
container->erase(iter);
|
|
}
|
|
|
|
#if BUILDFLAG(IS_WIN)
|
|
// gfx::Font callbacks
|
|
void AdjustUIFont(gfx::win::FontAdjustment* font_adjustment) {
|
|
l10n_util::NeedOverrideDefaultUIFont(&font_adjustment->font_family_override,
|
|
&font_adjustment->font_scale);
|
|
font_adjustment->font_scale *= display::win::GetAccessibilityFontScale();
|
|
}
|
|
|
|
int GetMinimumFontSize() {
|
|
int min_font_size;
|
|
base::StringToInt(l10n_util::GetStringUTF16(IDS_MINIMUM_UI_FONT_SIZE),
|
|
&min_font_size);
|
|
return min_font_size;
|
|
}
|
|
#endif
|
|
|
|
std::u16string MediaStringProvider(media::MessageId id) {
|
|
switch (id) {
|
|
case media::DEFAULT_AUDIO_DEVICE_NAME:
|
|
return u"Default";
|
|
#if BUILDFLAG(IS_WIN)
|
|
case media::COMMUNICATIONS_AUDIO_DEVICE_NAME:
|
|
return u"Communications";
|
|
#endif
|
|
default:
|
|
return std::u16string();
|
|
}
|
|
}
|
|
|
|
#if BUILDFLAG(IS_LINUX)
|
|
// GTK does not provide a way to check if current theme is dark, so we compare
|
|
// the text and background luminosity to get a result.
|
|
// This trick comes from FireFox.
|
|
void UpdateDarkThemeSetting() {
|
|
float bg = color_utils::GetRelativeLuminance(gtk::GetBgColor("GtkLabel"));
|
|
float fg = color_utils::GetRelativeLuminance(gtk::GetFgColor("GtkLabel"));
|
|
bool is_dark = fg > bg;
|
|
// Pass it to NativeUi theme, which is used by the nativeTheme module and most
|
|
// places in Electron.
|
|
ui::NativeTheme::GetInstanceForNativeUi()->set_use_dark_colors(is_dark);
|
|
// Pass it to Web Theme, to make "prefers-color-scheme" media query work.
|
|
ui::NativeTheme::GetInstanceForWeb()->set_use_dark_colors(is_dark);
|
|
}
|
|
#endif
|
|
|
|
} // namespace
|
|
|
|
#if BUILDFLAG(IS_LINUX)
|
|
class DarkThemeObserver : public ui::NativeThemeObserver {
|
|
public:
|
|
DarkThemeObserver() = default;
|
|
|
|
// ui::NativeThemeObserver:
|
|
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override {
|
|
UpdateDarkThemeSetting();
|
|
}
|
|
};
|
|
#endif
|
|
|
|
// static
|
|
ElectronBrowserMainParts* ElectronBrowserMainParts::self_ = nullptr;
|
|
|
|
ElectronBrowserMainParts::ElectronBrowserMainParts()
|
|
: fake_browser_process_(std::make_unique<BrowserProcessImpl>()),
|
|
browser_(std::make_unique<Browser>()),
|
|
node_bindings_(
|
|
NodeBindings::Create(NodeBindings::BrowserEnvironment::kBrowser)),
|
|
electron_bindings_(
|
|
std::make_unique<ElectronBindings>(node_bindings_->uv_loop())) {
|
|
DCHECK(!self_) << "Cannot have two ElectronBrowserMainParts";
|
|
self_ = this;
|
|
}
|
|
|
|
ElectronBrowserMainParts::~ElectronBrowserMainParts() = default;
|
|
|
|
// static
|
|
ElectronBrowserMainParts* ElectronBrowserMainParts::Get() {
|
|
DCHECK(self_);
|
|
return self_;
|
|
}
|
|
|
|
bool ElectronBrowserMainParts::SetExitCode(int code) {
|
|
if (!exit_code_)
|
|
return false;
|
|
|
|
content::BrowserMainLoop::GetInstance()->SetResultCode(code);
|
|
*exit_code_ = code;
|
|
return true;
|
|
}
|
|
|
|
int ElectronBrowserMainParts::GetExitCode() const {
|
|
return exit_code_.value_or(content::RESULT_CODE_NORMAL_EXIT);
|
|
}
|
|
|
|
int ElectronBrowserMainParts::PreEarlyInitialization() {
|
|
field_trial_list_ = std::make_unique<base::FieldTrialList>();
|
|
#if BUILDFLAG(IS_POSIX)
|
|
HandleSIGCHLD();
|
|
#endif
|
|
#if BUILDFLAG(IS_LINUX)
|
|
DetectOzonePlatform();
|
|
ui::OzonePlatform::PreEarlyInitialization();
|
|
#endif
|
|
#if BUILDFLAG(IS_MAC)
|
|
screen_ = std::make_unique<display::ScopedNativeScreen>();
|
|
#endif
|
|
|
|
ui::ColorProviderManager::Get().AppendColorProviderInitializer(
|
|
base::BindRepeating(AddChromeColorMixers));
|
|
|
|
return GetExitCode();
|
|
}
|
|
|
|
void ElectronBrowserMainParts::PostEarlyInitialization() {
|
|
// A workaround was previously needed because there was no ThreadTaskRunner
|
|
// set. If this check is failing we may need to re-add that workaround
|
|
DCHECK(base::ThreadTaskRunnerHandle::IsSet());
|
|
|
|
// The ProxyResolverV8 has setup a complete V8 environment, in order to
|
|
// avoid conflicts we only initialize our V8 environment after that.
|
|
js_env_ = std::make_unique<JavascriptEnvironment>(node_bindings_->uv_loop());
|
|
|
|
v8::HandleScope scope(js_env_->isolate());
|
|
|
|
node_bindings_->Initialize();
|
|
// Create the global environment.
|
|
node::Environment* env = node_bindings_->CreateEnvironment(
|
|
js_env_->context(), js_env_->platform());
|
|
node_env_ = std::make_unique<NodeEnvironment>(env);
|
|
|
|
env->set_trace_sync_io(env->options()->trace_sync_io);
|
|
|
|
// We do not want to crash the main process on unhandled rejections.
|
|
env->options()->unhandled_rejections = "warn";
|
|
|
|
// Add Electron extended APIs.
|
|
electron_bindings_->BindTo(js_env_->isolate(), env->process_object());
|
|
|
|
// Create explicit microtasks runner.
|
|
js_env_->CreateMicrotasksRunner();
|
|
|
|
// Wrap the uv loop with global env.
|
|
node_bindings_->set_uv_env(env);
|
|
|
|
// Load everything.
|
|
node_bindings_->LoadEnvironment(env);
|
|
|
|
// We already initialized the feature list in PreEarlyInitialization(), but
|
|
// the user JS script would not have had a chance to alter the command-line
|
|
// switches at that point. Lets reinitialize it here to pick up the
|
|
// command-line changes.
|
|
base::FeatureList::ClearInstanceForTesting();
|
|
InitializeFeatureList();
|
|
|
|
// Initialize field trials.
|
|
InitializeFieldTrials();
|
|
|
|
// Reinitialize logging now that the app has had a chance to set the app name
|
|
// and/or user data directory.
|
|
logging::InitElectronLogging(*base::CommandLine::ForCurrentProcess(),
|
|
/* is_preinit = */ false);
|
|
|
|
// Initialize after user script environment creation.
|
|
fake_browser_process_->PostEarlyInitialization();
|
|
}
|
|
|
|
int ElectronBrowserMainParts::PreCreateThreads() {
|
|
if (!views::LayoutProvider::Get()) {
|
|
layout_provider_ = std::make_unique<views::LayoutProvider>();
|
|
}
|
|
|
|
// Fetch the system locale for Electron.
|
|
#if BUILDFLAG(IS_MAC)
|
|
fake_browser_process_->SetSystemLocale(GetCurrentSystemLocale());
|
|
#else
|
|
fake_browser_process_->SetSystemLocale(base::i18n::GetConfiguredLocale());
|
|
#endif
|
|
|
|
auto* command_line = base::CommandLine::ForCurrentProcess();
|
|
std::string locale = command_line->GetSwitchValueASCII(::switches::kLang);
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
|
// The browser process only wants to support the language Cocoa will use,
|
|
// so force the app locale to be overridden with that value. This must
|
|
// happen before the ResourceBundle is loaded
|
|
if (locale.empty())
|
|
l10n_util::OverrideLocaleWithCocoaLocale();
|
|
#elif BUILDFLAG(IS_LINUX)
|
|
// l10n_util::GetApplicationLocaleInternal uses g_get_language_names(),
|
|
// which keys off of getenv("LC_ALL").
|
|
// We must set this env first to make ui::ResourceBundle accept the custom
|
|
// locale.
|
|
auto env = base::Environment::Create();
|
|
absl::optional<std::string> lc_all;
|
|
if (!locale.empty()) {
|
|
std::string str;
|
|
if (env->GetVar("LC_ALL", &str))
|
|
lc_all.emplace(std::move(str));
|
|
env->SetVar("LC_ALL", locale.c_str());
|
|
}
|
|
#endif
|
|
|
|
// Load resources bundle according to locale.
|
|
std::string loaded_locale = LoadResourceBundle(locale);
|
|
|
|
#if defined(USE_AURA)
|
|
// NB: must be called _after_ locale resource bundle is loaded,
|
|
// because ui lib makes use of it in X11
|
|
if (!display::Screen::GetScreen()) {
|
|
screen_ = views::CreateDesktopScreen();
|
|
}
|
|
#endif
|
|
|
|
// Initialize the app locale for Electron and Chromium.
|
|
std::string app_locale = l10n_util::GetApplicationLocale(loaded_locale);
|
|
ElectronBrowserClient::SetApplicationLocale(app_locale);
|
|
fake_browser_process_->SetApplicationLocale(app_locale);
|
|
|
|
#if BUILDFLAG(IS_LINUX)
|
|
// Reset to the original LC_ALL since we should not be changing it.
|
|
if (!locale.empty()) {
|
|
if (lc_all)
|
|
env->SetVar("LC_ALL", *lc_all);
|
|
else
|
|
env->UnSetVar("LC_ALL");
|
|
}
|
|
#endif
|
|
|
|
// Force MediaCaptureDevicesDispatcher to be created on UI thread.
|
|
MediaCaptureDevicesDispatcher::GetInstance();
|
|
|
|
// Force MediaCaptureDevicesDispatcher to be created on UI thread.
|
|
MediaCaptureDevicesDispatcher::GetInstance();
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
|
ui::InitIdleMonitor();
|
|
#endif
|
|
|
|
fake_browser_process_->PreCreateThreads();
|
|
|
|
// Notify observers.
|
|
Browser::Get()->PreCreateThreads();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ElectronBrowserMainParts::PostCreateThreads() {
|
|
content::GetIOThreadTaskRunner({})->PostTask(
|
|
FROM_HERE,
|
|
base::BindOnce(&tracing::TracingSamplerProfiler::CreateOnChildThread));
|
|
#if BUILDFLAG(ENABLE_PLUGINS)
|
|
// PluginService can only be used on the UI thread
|
|
// and ContentClient::AddPlugins gets called for both browser and render
|
|
// process where the latter will not have UI thread which leads to DCHECK.
|
|
// Separate the WebPluginInfo registration for these processes.
|
|
std::vector<content::WebPluginInfo> plugins;
|
|
auto* plugin_service = content::PluginService::GetInstance();
|
|
plugin_service->RefreshPlugins();
|
|
GetInternalPlugins(&plugins);
|
|
for (const auto& plugin : plugins)
|
|
plugin_service->RegisterInternalPlugin(plugin, true);
|
|
#endif
|
|
}
|
|
|
|
void ElectronBrowserMainParts::PostDestroyThreads() {
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
|
extensions_browser_client_.reset();
|
|
extensions::ExtensionsBrowserClient::Set(nullptr);
|
|
#endif
|
|
#if BUILDFLAG(IS_LINUX)
|
|
device::BluetoothAdapterFactory::Shutdown();
|
|
bluez::DBusBluezManagerWrapperLinux::Shutdown();
|
|
#endif
|
|
fake_browser_process_->PostDestroyThreads();
|
|
}
|
|
|
|
void ElectronBrowserMainParts::ToolkitInitialized() {
|
|
#if BUILDFLAG(IS_LINUX)
|
|
auto* linux_ui = ui::GetDefaultLinuxUi();
|
|
CHECK(linux_ui);
|
|
linux_ui_getter_ = std::make_unique<LinuxUiGetterImpl>();
|
|
|
|
// Try loading gtk symbols used by Electron.
|
|
electron::InitializeElectron_gtk(gtk::GetLibGtk());
|
|
if (!electron::IsElectron_gtkInitialized()) {
|
|
electron::UninitializeElectron_gtk();
|
|
}
|
|
|
|
electron::InitializeElectron_gdk_pixbuf(gtk::GetLibGdkPixbuf());
|
|
CHECK(electron::IsElectron_gdk_pixbufInitialized())
|
|
<< "Failed to initialize libgdk_pixbuf-2.0.so.0";
|
|
|
|
// Chromium does not respect GTK dark theme setting, but they may change
|
|
// in future and this code might be no longer needed. Check the Chromium
|
|
// issue to keep updated:
|
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=998903
|
|
UpdateDarkThemeSetting();
|
|
// Update the native theme when GTK theme changes. The GetNativeTheme
|
|
// here returns a NativeThemeGtk, which monitors GTK settings.
|
|
dark_theme_observer_ = std::make_unique<DarkThemeObserver>();
|
|
auto* linux_ui_theme = ui::LinuxUiTheme::GetForProfile(nullptr);
|
|
CHECK(linux_ui_theme);
|
|
linux_ui_theme->GetNativeTheme()->AddObserver(dark_theme_observer_.get());
|
|
ui::LinuxUi::SetInstance(linux_ui);
|
|
|
|
// Cursor theme changes are tracked by LinuxUI (via a CursorThemeManager
|
|
// implementation). Start observing them once it's initialized.
|
|
ui::CursorFactory::GetInstance()->ObserveThemeChanges();
|
|
#endif
|
|
|
|
#if defined(USE_AURA)
|
|
wm_state_ = std::make_unique<wm::WMState>();
|
|
#endif
|
|
|
|
#if BUILDFLAG(IS_WIN)
|
|
gfx::win::SetAdjustFontCallback(&AdjustUIFont);
|
|
gfx::win::SetGetMinimumFontSizeCallback(&GetMinimumFontSize);
|
|
#endif
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
|
views_delegate_ = std::make_unique<ViewsDelegateMac>();
|
|
#else
|
|
views_delegate_ = std::make_unique<ViewsDelegate>();
|
|
#endif
|
|
}
|
|
|
|
int ElectronBrowserMainParts::PreMainMessageLoopRun() {
|
|
// Run user's main script before most things get initialized, so we can have
|
|
// a chance to setup everything.
|
|
node_bindings_->PrepareEmbedThread();
|
|
node_bindings_->StartPolling();
|
|
|
|
// url::Add*Scheme are not threadsafe, this helps prevent data races.
|
|
url::LockSchemeRegistries();
|
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
|
extensions_client_ = std::make_unique<ElectronExtensionsClient>();
|
|
extensions::ExtensionsClient::Set(extensions_client_.get());
|
|
|
|
// BrowserContextKeyedAPIServiceFactories require an ExtensionsBrowserClient.
|
|
extensions_browser_client_ =
|
|
std::make_unique<ElectronExtensionsBrowserClient>();
|
|
extensions::ExtensionsBrowserClient::Set(extensions_browser_client_.get());
|
|
|
|
extensions::EnsureBrowserContextKeyedServiceFactoriesBuilt();
|
|
extensions::electron::EnsureBrowserContextKeyedServiceFactoriesBuilt();
|
|
#endif
|
|
|
|
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
|
SpellcheckServiceFactory::GetInstance();
|
|
#endif
|
|
|
|
content::WebUIControllerFactory::RegisterFactory(
|
|
ElectronWebUIControllerFactory::GetInstance());
|
|
|
|
auto* command_line = base::CommandLine::ForCurrentProcess();
|
|
if (command_line->HasSwitch(switches::kRemoteDebuggingPipe)) {
|
|
// --remote-debugging-pipe
|
|
auto on_disconnect = base::BindOnce([]() {
|
|
content::GetUIThreadTaskRunner({})->PostTask(
|
|
FROM_HERE, base::BindOnce([]() { Browser::Get()->Quit(); }));
|
|
});
|
|
content::DevToolsAgentHost::StartRemoteDebuggingPipeHandler(
|
|
std::move(on_disconnect));
|
|
} else if (command_line->HasSwitch(switches::kRemoteDebuggingPort)) {
|
|
// --remote-debugging-port
|
|
DevToolsManagerDelegate::StartHttpHandler();
|
|
}
|
|
|
|
#if !BUILDFLAG(IS_MAC)
|
|
// The corresponding call in macOS is in ElectronApplicationDelegate.
|
|
Browser::Get()->WillFinishLaunching();
|
|
Browser::Get()->DidFinishLaunching(base::Value::Dict());
|
|
#endif
|
|
|
|
// Notify observers that main thread message loop was initialized.
|
|
Browser::Get()->PreMainMessageLoopRun();
|
|
|
|
return GetExitCode();
|
|
}
|
|
|
|
void ElectronBrowserMainParts::WillRunMainMessageLoop(
|
|
std::unique_ptr<base::RunLoop>& run_loop) {
|
|
exit_code_ = content::RESULT_CODE_NORMAL_EXIT;
|
|
Browser::Get()->SetMainMessageLoopQuitClosure(
|
|
run_loop->QuitWhenIdleClosure());
|
|
}
|
|
|
|
void ElectronBrowserMainParts::PostCreateMainMessageLoop() {
|
|
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
|
|
std::string app_name = electron::Browser::Get()->GetName();
|
|
#endif
|
|
#if BUILDFLAG(IS_LINUX)
|
|
auto shutdown_cb =
|
|
base::BindOnce(base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
|
|
ui::OzonePlatform::GetInstance()->PostCreateMainMessageLoop(
|
|
std::move(shutdown_cb),
|
|
content::GetUIThreadTaskRunner({content::BrowserTaskType::kUserInput}));
|
|
bluez::DBusBluezManagerWrapperLinux::Initialize();
|
|
|
|
// Set up crypt config. This needs to be done before anything starts the
|
|
// network service, as the raw encryption key needs to be shared with the
|
|
// network service for encrypted cookie storage.
|
|
const base::CommandLine& command_line =
|
|
*base::CommandLine::ForCurrentProcess();
|
|
std::unique_ptr<os_crypt::Config> config =
|
|
std::make_unique<os_crypt::Config>();
|
|
// Forward to os_crypt the flag to use a specific password store.
|
|
config->store = command_line.GetSwitchValueASCII(::switches::kPasswordStore);
|
|
config->product_name = app_name;
|
|
config->application_name = app_name;
|
|
config->main_thread_runner = base::ThreadTaskRunnerHandle::Get();
|
|
// c.f.
|
|
// https://source.chromium.org/chromium/chromium/src/+/master:chrome/common/chrome_switches.cc;l=689;drc=9d82515060b9b75fa941986f5db7390299669ef1
|
|
config->should_use_preference =
|
|
command_line.HasSwitch(::switches::kEnableEncryptionSelection);
|
|
base::PathService::Get(DIR_SESSION_DATA, &config->user_data_path);
|
|
OSCrypt::SetConfig(std::move(config));
|
|
#endif
|
|
#if BUILDFLAG(IS_MAC)
|
|
KeychainPassword::GetServiceName() = app_name + " Safe Storage";
|
|
KeychainPassword::GetAccountName() = app_name;
|
|
#endif
|
|
#if BUILDFLAG(IS_POSIX)
|
|
// Exit in response to SIGINT, SIGTERM, etc.
|
|
InstallShutdownSignalHandlers(
|
|
base::BindOnce(&Browser::Quit, base::Unretained(Browser::Get())),
|
|
content::GetUIThreadTaskRunner({}));
|
|
#endif
|
|
}
|
|
|
|
void ElectronBrowserMainParts::PostMainMessageLoopRun() {
|
|
#if BUILDFLAG(IS_MAC)
|
|
FreeAppDelegate();
|
|
#endif
|
|
|
|
// Shutdown the DownloadManager before destroying Node to prevent
|
|
// DownloadItem callbacks from crashing.
|
|
for (auto& iter : ElectronBrowserContext::browser_context_map()) {
|
|
auto* download_manager = iter.second.get()->GetDownloadManager();
|
|
if (download_manager) {
|
|
download_manager->Shutdown();
|
|
}
|
|
}
|
|
|
|
// Shutdown utility process created with Electron API before
|
|
// stopping Node.js so that exit events can be emitted. We don't let
|
|
// content layer perform this action since it destroys
|
|
// child process only after this step (PostMainMessageLoopRun) via
|
|
// BrowserProcessIOThread::ProcessHostCleanUp() which is too late for our
|
|
// use case.
|
|
// https://source.chromium.org/chromium/chromium/src/+/main:content/browser/browser_main_loop.cc;l=1086-1108
|
|
//
|
|
// The following logic is based on
|
|
// https://source.chromium.org/chromium/chromium/src/+/main:content/browser/browser_process_io_thread.cc;l=127-159
|
|
//
|
|
// Although content::BrowserChildProcessHostIterator is only to be called from
|
|
// IO thread, it is safe to call from PostMainMessageLoopRun because thread
|
|
// restrictions have been lifted.
|
|
// https://source.chromium.org/chromium/chromium/src/+/main:content/browser/browser_main_loop.cc;l=1062-1078
|
|
for (content::BrowserChildProcessHostIterator it(
|
|
content::PROCESS_TYPE_UTILITY);
|
|
!it.Done(); ++it) {
|
|
if (it.GetDelegate()->GetServiceName() == node::mojom::NodeService::Name_) {
|
|
auto& process = it.GetData().GetProcess();
|
|
if (!process.IsValid())
|
|
continue;
|
|
auto utility_process_wrapper =
|
|
api::UtilityProcessWrapper::FromProcessId(process.Pid());
|
|
if (utility_process_wrapper)
|
|
utility_process_wrapper->Shutdown(0 /* exit_code */);
|
|
}
|
|
}
|
|
|
|
// Destroy node platform after all destructors_ are executed, as they may
|
|
// invoke Node/V8 APIs inside them.
|
|
node_env_->env()->set_trace_sync_io(false);
|
|
js_env_->DestroyMicrotasksRunner();
|
|
node::Stop(node_env_->env());
|
|
node_env_.reset();
|
|
|
|
auto default_context_key = ElectronBrowserContext::PartitionKey("", false);
|
|
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();
|
|
content::DevToolsAgentHost::StopRemoteDebuggingPipeHandler();
|
|
|
|
#if BUILDFLAG(IS_LINUX)
|
|
ui::OzonePlatform::GetInstance()->PostMainMessageLoopRun();
|
|
#endif
|
|
}
|
|
|
|
#if !BUILDFLAG(IS_MAC)
|
|
void ElectronBrowserMainParts::PreCreateMainMessageLoop() {
|
|
PreCreateMainMessageLoopCommon();
|
|
}
|
|
#endif
|
|
|
|
void ElectronBrowserMainParts::PreCreateMainMessageLoopCommon() {
|
|
#if BUILDFLAG(IS_MAC)
|
|
InitializeMainNib();
|
|
RegisterURLHandler();
|
|
#endif
|
|
media::SetLocalizedStringProvider(MediaStringProvider);
|
|
|
|
#if BUILDFLAG(IS_WIN)
|
|
auto* local_state = g_browser_process->local_state();
|
|
DCHECK(local_state);
|
|
|
|
bool os_crypt_init = OSCrypt::Init(local_state);
|
|
DCHECK(os_crypt_init);
|
|
#endif
|
|
}
|
|
|
|
device::mojom::GeolocationControl*
|
|
ElectronBrowserMainParts::GetGeolocationControl() {
|
|
if (!geolocation_control_) {
|
|
content::GetDeviceService().BindGeolocationControl(
|
|
geolocation_control_.BindNewPipeAndPassReceiver());
|
|
}
|
|
return geolocation_control_.get();
|
|
}
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
|
device::GeolocationManager* ElectronBrowserMainParts::GetGeolocationManager() {
|
|
return geolocation_manager_.get();
|
|
}
|
|
#endif
|
|
|
|
IconManager* ElectronBrowserMainParts::GetIconManager() {
|
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
|
if (!icon_manager_.get())
|
|
icon_manager_ = std::make_unique<IconManager>();
|
|
return icon_manager_.get();
|
|
}
|
|
|
|
} // namespace electron
|