123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689 |
- // 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/nix/xdg_util.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 "base/task/single_thread_task_runner.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/sync/key_storage_config_linux.h"
- #include "components/os_crypt/sync/key_storage_util_linux.h"
- #include "components/os_crypt/sync/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"
- #include "ui/color/color_provider_manager.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 "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/gfx/system_fonts_win.h"
- #include "ui/strings/grit/app_locale_settings.h"
- #endif
- #if BUILDFLAG(IS_MAC)
- #include "components/os_crypt/sync/keychain_password_mac.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)
- 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>()),
- node_bindings_{
- NodeBindings::Create(NodeBindings::BrowserEnvironment::kBrowser)},
- electron_bindings_{
- std::make_unique<ElectronBindings>(node_bindings_->uv_loop())},
- browser_{std::make_unique<Browser>()} {
- 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::SingleThreadTaskRunner::HasCurrentDefault());
- // 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(js_env_->isolate()->GetCurrentContext());
- // Create the global environment.
- node_env_ = node_bindings_->CreateEnvironment(
- js_env_->isolate()->GetCurrentContext(), js_env_->platform());
- node_env_->set_trace_sync_io(node_env_->options()->trace_sync_io);
- // We do not want to crash the main process on unhandled rejections.
- node_env_->options()->unhandled_rejections = "warn-with-error-code";
- // Add Electron extended APIs.
- electron_bindings_->BindTo(js_env_->isolate(), node_env_->process_object());
- // Create explicit microtasks runner.
- js_env_->CreateMicrotasksRunner();
- // Wrap the uv loop with global env.
- node_bindings_->set_uv_env(node_env_.get());
- // Load everything.
- node_bindings_->LoadEnvironment(node_env_.get());
- // Wait for app
- node_bindings_->JoinAppCode();
- // 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();
- Browser::Get()->ApplyForcedRTL();
- #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(&l10n_util::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();
- fake_browser_process_->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;
- // c.f.
- // https://source.chromium.org/chromium/chromium/src/+/main: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);
- bool use_backend = !config->should_use_preference ||
- os_crypt::GetBackendUse(config->user_data_path);
- std::unique_ptr<base::Environment> env(base::Environment::Create());
- base::nix::DesktopEnvironment desktop_env =
- base::nix::GetDesktopEnvironment(env.get());
- os_crypt::SelectedLinuxBackend selected_backend =
- os_crypt::SelectBackend(config->store, use_backend, desktop_env);
- fake_browser_process_->SetLinuxStorageBackend(selected_backend);
- 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_->set_trace_sync_io(false);
- js_env_->DestroyMicrotasksRunner();
- node::Stop(node_env_.get(), node::StopFlags::kDoNotTerminateIsolate);
- 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();
- }
- 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
|