diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index 6d227bf9300d9..c80e21c9163bb 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -6,6 +6,11 @@ #include +#if defined(OS_LINUX) +#include // for g_setenv() +#endif + +#include "atom/app/atom_main_delegate.h" #include "atom/browser/api/atom_api_app.h" #include "atom/browser/api/trackable_object.h" #include "atom/browser/atom_browser_client.h" @@ -20,28 +25,61 @@ #include "atom/common/api/atom_bindings.h" #include "atom/common/asar/asar_util.h" #include "atom/common/node_bindings.h" +#include "base/base_switches.h" #include "base/command_line.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/feature_list.h" +#include "base/message_loop/message_loop.h" +#include "base/path_service.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "brightray/browser/brightray_paths.h" +#include "brightray/common/application_info.h" #include "chrome/browser/browser_process_impl.h" #include "chrome/browser/icon_manager.h" #include "chrome/browser/net/chrome_net_log_helper.h" #include "components/net_log/chrome_net_log.h" #include "components/net_log/net_export_file_writer.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.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/result_codes.h" #include "content/public/common/service_manager_connection.h" #include "electron/buildflags/buildflags.h" +#include "media/base/localized_strings.h" #include "services/device/public/mojom/constants.mojom.h" #include "services/network/public/cpp/network_switches.h" #include "services/service_manager/public/cpp/connector.h" #include "ui/base/idle/idle.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/material_design/material_design_controller.h" +#include "ui/base/resource/resource_bundle.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 defined(USE_X11) +#include "base/environment.h" +#include "base/nix/xdg_util.h" +#include "base/threading/thread_task_runner_handle.h" +#include "chrome/browser/ui/libgtkui/gtk_ui.h" #include "chrome/browser/ui/libgtkui/gtk_util.h" +#include "ui/base/x/x11_util.h" +#include "ui/base/x/x11_util_internal.h" #include "ui/events/devices/x11/touch_factory_x11.h" +#include "ui/views/linux_ui/linux_ui.h" +#endif + +#if defined(OS_WIN) +#include "ui/base/cursor/cursor_loader_win.h" +#include "ui/base/l10n/l10n_util_win.h" +#include "ui/gfx/platform_font_win.h" #endif #if defined(OS_MACOSX) @@ -50,6 +88,11 @@ #include "atom/browser/ui/views/atom_views_delegate.h" #endif +#if defined(OS_LINUX) +#include "device/bluetooth/bluetooth_adapter_factory.h" +#include "device/bluetooth/dbus/dbus_bluez_manager_wrapper_linux.h" +#endif + // Must be included after all other headers. #include "atom/common/node_includes.h" @@ -62,8 +105,134 @@ void Erase(T* container, typename T::iterator iter) { container->erase(iter); } +#if defined(OS_WIN) +// gfx::Font callbacks +void AdjustUIFont(LOGFONT* logfont) { + l10n_util::AdjustUIFont(logfont); +} + +int GetMinimumFontSize() { + return 10; +} +#endif + +base::string16 MediaStringProvider(media::MessageId id) { + switch (id) { + case media::DEFAULT_AUDIO_DEVICE_NAME: + return base::ASCIIToUTF16("Default"); +#if defined(OS_WIN) + case media::COMMUNICATIONS_AUDIO_DEVICE_NAME: + return base::ASCIIToUTF16("Communications"); +#endif + default: + return base::string16(); + } +} + +#if defined(USE_X11) +// Indicates that we're currently responding to an IO error (by shutting down). +bool g_in_x11_io_error_handler = false; + +// Number of seconds to wait for UI thread to get an IO error if we get it on +// the background thread. +const int kWaitForUIThreadSeconds = 10; + +void OverrideLinuxAppDataPath() { + base::FilePath path; + if (base::PathService::Get(brightray::DIR_APP_DATA, &path)) + return; + std::unique_ptr env(base::Environment::Create()); + path = base::nix::GetXDGDirectory(env.get(), base::nix::kXdgConfigHomeEnvVar, + base::nix::kDotConfigDir); + base::PathService::Override(brightray::DIR_APP_DATA, path); +} + +int BrowserX11ErrorHandler(Display* d, XErrorEvent* error) { + if (!g_in_x11_io_error_handler && base::ThreadTaskRunnerHandle::IsSet()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&ui::LogErrorEventDescription, d, *error)); + } + return 0; +} + +// This function is used to help us diagnose crash dumps that happen +// during the shutdown process. +NOINLINE void WaitingForUIThreadToHandleIOError() { + // Ensure function isn't optimized away. + asm(""); + sleep(kWaitForUIThreadSeconds); +} + +int BrowserX11IOErrorHandler(Display* d) { + if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { + // Wait for the UI thread (which has a different connection to the X server) + // to get the error. We can't call shutdown from this thread without + // tripping an error. Doing it through a function so that we'll be able + // to see it in any crash dumps. + WaitingForUIThreadToHandleIOError(); + return 0; + } + + // If there's an IO error it likely means the X server has gone away. + // If this DCHECK fails, then that means SessionEnding() below triggered some + // code that tried to talk to the X server, resulting in yet another error. + DCHECK(!g_in_x11_io_error_handler); + + g_in_x11_io_error_handler = true; + LOG(ERROR) << "X IO error received (X server probably went away)"; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()); + + return 0; +} + +int X11EmptyErrorHandler(Display* d, XErrorEvent* error) { + return 0; +} + +int X11EmptyIOErrorHandler(Display* d) { + return 0; +} +#endif + } // namespace +void AtomBrowserMainParts::InitializeFeatureList() { + auto* cmd_line = base::CommandLine::ForCurrentProcess(); + auto enable_features = + cmd_line->GetSwitchValueASCII(::switches::kEnableFeatures); + // Node depends on SharedArrayBuffer support, which was temporarily disabled + // by https://chromium-review.googlesource.com/c/chromium/src/+/849429 (in + // M64) and reenabled by + // https://chromium-review.googlesource.com/c/chromium/src/+/1159358 (in + // M70). Once Electron upgrades to M70, we can remove this. + enable_features += std::string(",") + features::kSharedArrayBuffer.name; + auto disable_features = + cmd_line->GetSwitchValueASCII(::switches::kDisableFeatures); +#if defined(OS_MACOSX) + // Disable the V2 sandbox on macOS. + // Chromium is going to use the system sandbox API of macOS for the sandbox + // implmentation, we may have to deprecate --mixed-sandbox for macOS once + // Chromium drops support for the old sandbox implmentation. + disable_features += std::string(",") + features::kMacV2Sandbox.name; +#endif + auto feature_list = std::make_unique(); + feature_list->InitializeFromCommandLine(enable_features, disable_features); + base::FeatureList::SetInstance(std::move(feature_list)); +} + +#if !defined(OS_MACOSX) +void AtomBrowserMainParts::OverrideAppLogsPath() { + base::FilePath path; + if (base::PathService::Get(brightray::DIR_APP_DATA, &path)) { + path = path.Append( + base::FilePath::FromUTF8Unsafe(brightray::GetApplicationName())); + path = path.Append(base::FilePath::FromUTF8Unsafe("logs")); + base::PathService::Override(brightray::DIR_APP_LOGS, path); + } +} +#endif + // static AtomBrowserMainParts* AtomBrowserMainParts::self_ = nullptr; @@ -120,10 +289,22 @@ void AtomBrowserMainParts::RegisterDestructionCallback( destructors_.insert(destructors_.begin(), std::move(callback)); } +bool AtomBrowserMainParts::ShouldContentCreateFeatureList() { + return false; +} + int AtomBrowserMainParts::PreEarlyInitialization() { - const int result = brightray::BrowserMainParts::PreEarlyInitialization(); - if (result != service_manager::RESULT_CODE_NORMAL_EXIT) - return result; + InitializeFeatureList(); + OverrideAppLogsPath(); +#if defined(USE_X11) + views::LinuxUI::SetInstance(BuildGtkUi()); + OverrideLinuxAppDataPath(); + + // Installs the X11 error handlers for the browser process used during + // startup. They simply print error messages and exit because + // we can't shutdown properly while creating and initializing services. + ui::SetX11ErrorHandlers(nullptr, nullptr); +#endif #if defined(OS_POSIX) HandleSIGCHLD(); @@ -133,8 +314,6 @@ int AtomBrowserMainParts::PreEarlyInitialization() { } void AtomBrowserMainParts::PostEarlyInitialization() { - brightray::BrowserMainParts::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()); @@ -162,26 +341,35 @@ void AtomBrowserMainParts::PostEarlyInitialization() { // Wrap the uv loop with global env. node_bindings_->set_uv_env(env); - // We already initialized the feature list in - // brightray::BrowserMainParts::PreEarlyInitialization(), but + // 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(); - brightray::BrowserMainParts::InitializeFeatureList(); + InitializeFeatureList(); } int AtomBrowserMainParts::PreCreateThreads() { - const int result = brightray::BrowserMainParts::PreCreateThreads(); +#if defined(USE_AURA) + display::Screen* screen = views::CreateDesktopScreen(); + display::Screen::SetScreenInstance(screen); +#if defined(USE_X11) + views::LinuxUI::instance()->UpdateDeviceScaleFactor(); +#endif +#endif + + if (!views::LayoutProvider::Get()) + layout_provider_.reset(new views::LayoutProvider()); // Initialize the app locale. AtomBrowserClient::SetApplicationLocale( l10n_util::GetApplicationLocale(custom_locale_)); - if (!result) { - fake_browser_process_->SetApplicationLocale( - AtomBrowserClient::Get()->GetApplicationLocale()); - } + fake_browser_process_->SetApplicationLocale( + AtomBrowserClient::Get()->GetApplicationLocale()); + + // Force MediaCaptureDevicesDispatcher to be created on UI thread. + MediaCaptureDevicesDispatcher::GetInstance(); // Force MediaCaptureDevicesDispatcher to be created on UI thread. MediaCaptureDevicesDispatcher::GetInstance(); @@ -208,16 +396,37 @@ int AtomBrowserMainParts::PreCreateThreads() { // Manage global state of net and other IO thread related. io_thread_ = std::make_unique(net_log_.get()); - return result; + return 0; } void AtomBrowserMainParts::PostDestroyThreads() { - brightray::BrowserMainParts::PostDestroyThreads(); +#if defined(OS_LINUX) + device::BluetoothAdapterFactory::Shutdown(); + bluez::DBusBluezManagerWrapperLinux::Shutdown(); +#endif io_thread_.reset(); } void AtomBrowserMainParts::ToolkitInitialized() { - brightray::BrowserMainParts::ToolkitInitialized(); + ui::MaterialDesignController::Initialize(); + +#if defined(USE_AURA) && defined(USE_X11) + views::LinuxUI::instance()->Initialize(); +#endif + +#if defined(USE_AURA) + wm_state_.reset(new wm::WMState); +#endif + +#if defined(OS_WIN) + gfx::PlatformFontWin::adjust_font_callback = &AdjustUIFont; + gfx::PlatformFontWin::get_minimum_font_size_callback = &GetMinimumFontSize; + + wchar_t module_name[MAX_PATH] = {0}; + if (GetModuleFileName(NULL, module_name, MAX_PATH)) + ui::CursorLoaderWin::SetCursorResourceModule(module_name); +#endif + #if defined(OS_MACOSX) views_delegate_.reset(new ViewsDelegateMac); #else @@ -265,7 +474,7 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() { bool AtomBrowserMainParts::MainMessageLoopRun(int* result_code) { js_env_->OnMessageLoopCreated(); exit_code_ = result_code; - return brightray::BrowserMainParts::MainMessageLoopRun(result_code); + return content::BrowserMainParts::MainMessageLoopRun(result_code); } void AtomBrowserMainParts::PreDefaultMainMessageLoopRun( @@ -274,14 +483,27 @@ void AtomBrowserMainParts::PreDefaultMainMessageLoopRun( } void AtomBrowserMainParts::PostMainMessageLoopStart() { - brightray::BrowserMainParts::PostMainMessageLoopStart(); +#if defined(USE_X11) + // Installs the X11 error handlers for the browser process after the + // main message loop has started. This will allow us to exit cleanly + // if X exits before us. + ui::SetX11ErrorHandlers(BrowserX11ErrorHandler, BrowserX11IOErrorHandler); +#endif +#if defined(OS_LINUX) + bluez::DBusBluezManagerWrapperLinux::Initialize(); +#endif #if defined(OS_POSIX) HandleShutdownSignals(); #endif } void AtomBrowserMainParts::PostMainMessageLoopRun() { - brightray::BrowserMainParts::PostMainMessageLoopRun(); +#if defined(USE_X11) + // Unset the X11 error handlers. The X11 error handlers log the errors using a + // |PostTask()| on the message-loop. But since the message-loop is in the + // process of terminating, this can cause errors. + ui::SetX11ErrorHandlers(X11EmptyErrorHandler, X11EmptyIOErrorHandler); +#endif js_env_->OnMessageLoopDestroying(); @@ -302,6 +524,42 @@ void AtomBrowserMainParts::PostMainMessageLoopRun() { } } +#if !defined(OS_MACOSX) +void AtomBrowserMainParts::PreMainMessageLoopStart() { + PreMainMessageLoopStartCommon(); +} +#endif + +void AtomBrowserMainParts::PreMainMessageLoopStartCommon() { + // Initialize ui::ResourceBundle. + ui::ResourceBundle::InitSharedInstanceWithLocale( + "", nullptr, ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES); + auto* cmd_line = base::CommandLine::ForCurrentProcess(); + if (cmd_line->HasSwitch(switches::kLang)) { + const std::string locale = cmd_line->GetSwitchValueASCII(switches::kLang); + const base::FilePath locale_file_path = + ui::ResourceBundle::GetSharedInstance().GetLocaleFilePath(locale, true); + if (!locale_file_path.empty()) { + custom_locale_ = locale; +#if defined(OS_LINUX) + /* When built with USE_GLIB, libcc's GetApplicationLocaleInternal() uses + * glib's g_get_language_names(), which keys off of getenv("LC_ALL") */ + g_setenv("LC_ALL", custom_locale_.c_str(), TRUE); +#endif + } + } + +#if defined(OS_MACOSX) + if (custom_locale_.empty()) + l10n_util::OverrideLocaleWithCocoaLocale(); +#endif + LoadResourceBundle(custom_locale_); +#if defined(OS_MACOSX) + InitializeMainNib(); +#endif + media::SetLocalizedStringProvider(MediaStringProvider); +} + device::mojom::GeolocationControl* AtomBrowserMainParts::GetGeolocationControl() { if (geolocation_control_) diff --git a/atom/browser/atom_browser_main_parts.h b/atom/browser/atom_browser_main_parts.h index 28b31661f60a9..1653227c708e9 100644 --- a/atom/browser/atom_browser_main_parts.h +++ b/atom/browser/atom_browser_main_parts.h @@ -11,10 +11,11 @@ #include "base/callback.h" #include "base/timer/timer.h" -#include "brightray/browser/browser_main_parts.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_main_parts.h" #include "content/public/common/main_function_params.h" #include "services/device/public/mojom/geolocation_control.mojom.h" +#include "ui/views/layout/layout_provider.h" class BrowserProcess; class IconManager; @@ -23,6 +24,12 @@ namespace net_log { class ChromeNetLog; } +#if defined(USE_AURA) +namespace wm { +class WMState; +} +#endif + namespace atom { class AtomBindings; @@ -42,7 +49,7 @@ class ViewsDelegate; class ViewsDelegateMac; #endif -class AtomBrowserMainParts : public brightray::BrowserMainParts { +class AtomBrowserMainParts : public content::BrowserMainParts { public: explicit AtomBrowserMainParts(const content::MainFunctionParams& params); ~AtomBrowserMainParts() override; @@ -73,6 +80,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { protected: // content::BrowserMainParts: + bool ShouldContentCreateFeatureList() override; int PreEarlyInitialization() override; void PostEarlyInitialization() override; int PreCreateThreads() override; @@ -82,12 +90,14 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { void PreDefaultMainMessageLoopRun(base::OnceClosure quit_closure) override; void PostMainMessageLoopStart() override; void PostMainMessageLoopRun() override; -#if defined(OS_MACOSX) void PreMainMessageLoopStart() override; -#endif void PostDestroyThreads() override; private: + void InitializeFeatureList(); + void OverrideAppLogsPath(); + void PreMainMessageLoopStartCommon(); + #if defined(OS_POSIX) // Set signal handlers. void HandleSIGCHLD(); @@ -96,6 +106,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { #if defined(OS_MACOSX) void FreeAppDelegate(); + void InitializeMainNib(); #endif #if defined(OS_MACOSX) @@ -104,6 +115,13 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { std::unique_ptr views_delegate_; #endif +#if defined(USE_AURA) + std::unique_ptr wm_state_; +#endif + + std::unique_ptr layout_provider_; + std::string custom_locale_; + // A fake BrowserProcess object that used to feed the source code from chrome. std::unique_ptr fake_browser_process_; diff --git a/atom/browser/atom_browser_main_parts_mac.mm b/atom/browser/atom_browser_main_parts_mac.mm index 92af70cf3830a..1ab1bb9fa7029 100644 --- a/atom/browser/atom_browser_main_parts_mac.mm +++ b/atom/browser/atom_browser_main_parts_mac.mm @@ -7,6 +7,8 @@ #include "atom/browser/mac/atom_application_delegate.h" #include "base/mac/bundle_locations.h" #include "base/mac/foundation_util.h" +#include "base/path_service.h" +#include "brightray/browser/brightray_paths.h" #include "ui/base/l10n/l10n_util_mac.h" namespace atom { @@ -16,7 +18,7 @@ AtomApplicationDelegate* delegate = [[AtomApplicationDelegate alloc] init]; [NSApp setDelegate:delegate]; - brightray::BrowserMainParts::PreMainMessageLoopStart(); + PreMainMessageLoopStartCommon(); // Prevent Cocoa from turning command-line arguments into // |-application:openFiles:|, since we already handle them directly. @@ -30,4 +32,32 @@ [NSApp setDelegate:nil]; } +void AtomBrowserMainParts::OverrideAppLogsPath() { + base::FilePath path; + NSString* bundleName = + [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; + NSString* logsPath = + [NSString stringWithFormat:@"Library/Logs/%@", bundleName]; + NSString* libraryPath = + [NSHomeDirectory() stringByAppendingPathComponent:logsPath]; + + base::PathService::Override(brightray::DIR_APP_LOGS, + base::FilePath([libraryPath UTF8String])); +} + +// Replicates NSApplicationMain, but doesn't start a run loop. +void AtomBrowserMainParts::InitializeMainNib() { + auto infoDictionary = base::mac::OuterBundle().infoDictionary; + + auto principalClass = + NSClassFromString([infoDictionary objectForKey:@"NSPrincipalClass"]); + auto application = [principalClass sharedApplication]; + + NSString* mainNibName = [infoDictionary objectForKey:@"NSMainNibFile"]; + auto mainNib = [[NSNib alloc] initWithNibNamed:mainNibName + bundle:base::mac::FrameworkBundle()]; + [mainNib instantiateWithOwner:application topLevelObjects:nil]; + [mainNib release]; +} + } // namespace atom diff --git a/brightray/BUILD.gn b/brightray/BUILD.gn index 57778f3e85057..53a3447b1c77a 100644 --- a/brightray/BUILD.gn +++ b/brightray/BUILD.gn @@ -19,9 +19,6 @@ static_library("brightray") { sources = [ "browser/brightray_paths.h", - "browser/browser_main_parts.cc", - "browser/browser_main_parts.h", - "browser/browser_main_parts_mac.mm", "browser/win/scoped_hstring.cc", "browser/win/scoped_hstring.h", "common/application_info.cc", diff --git a/brightray/browser/browser_main_parts.cc b/brightray/browser/browser_main_parts.cc deleted file mode 100644 index dcc84b9420f28..0000000000000 --- a/brightray/browser/browser_main_parts.cc +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-CHROMIUM file. - -#include "brightray/browser/browser_main_parts.h" - -#if defined(OS_POSIX) -#include -#endif - -#include -#include -#include - -#if defined(OS_LINUX) -#include // for g_setenv() -#endif - -#include "atom/app/atom_main_delegate.h" -#include "base/base_switches.h" -#include "base/command_line.h" -#include "base/feature_list.h" -#include "base/message_loop/message_loop.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "brightray/common/application_info.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/common/content_features.h" -#include "content/public/common/content_switches.h" -#include "content/public/common/result_codes.h" -#include "media/base/localized_strings.h" -#include "net/proxy_resolution/proxy_resolver_v8.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" -#include "ui/base/resource/resource_bundle.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 defined(USE_X11) -#include "base/environment.h" -#include "base/nix/xdg_util.h" -#include "base/path_service.h" -#include "base/threading/thread_task_runner_handle.h" -#include "brightray/browser/brightray_paths.h" -#include "chrome/browser/ui/libgtkui/gtk_ui.h" -#include "ui/base/x/x11_util.h" -#include "ui/base/x/x11_util_internal.h" -#include "ui/views/linux_ui/linux_ui.h" -#endif - -#if defined(OS_WIN) -#include "ui/base/cursor/cursor_loader_win.h" -#include "ui/base/l10n/l10n_util_win.h" -#include "ui/gfx/platform_font_win.h" -#endif - -#if defined(OS_LINUX) -#include "device/bluetooth/bluetooth_adapter_factory.h" -#include "device/bluetooth/dbus/dbus_bluez_manager_wrapper_linux.h" -#endif - -namespace brightray { - -namespace { - -#if defined(OS_WIN) -// gfx::Font callbacks -void AdjustUIFont(LOGFONT* logfont) { - l10n_util::AdjustUIFont(logfont); -} - -int GetMinimumFontSize() { - return 10; -} -#endif - -#if defined(USE_X11) -// Indicates that we're currently responding to an IO error (by shutting down). -bool g_in_x11_io_error_handler = false; - -// Number of seconds to wait for UI thread to get an IO error if we get it on -// the background thread. -const int kWaitForUIThreadSeconds = 10; - -void OverrideLinuxAppDataPath() { - base::FilePath path; - if (base::PathService::Get(DIR_APP_DATA, &path)) - return; - std::unique_ptr env(base::Environment::Create()); - path = base::nix::GetXDGDirectory(env.get(), base::nix::kXdgConfigHomeEnvVar, - base::nix::kDotConfigDir); - base::PathService::Override(DIR_APP_DATA, path); -} - -int BrowserX11ErrorHandler(Display* d, XErrorEvent* error) { - if (!g_in_x11_io_error_handler && base::ThreadTaskRunnerHandle::IsSet()) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&ui::LogErrorEventDescription, d, *error)); - } - return 0; -} - -// This function is used to help us diagnose crash dumps that happen -// during the shutdown process. -NOINLINE void WaitingForUIThreadToHandleIOError() { - // Ensure function isn't optimized away. - asm(""); - sleep(kWaitForUIThreadSeconds); -} - -int BrowserX11IOErrorHandler(Display* d) { - if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { - // Wait for the UI thread (which has a different connection to the X server) - // to get the error. We can't call shutdown from this thread without - // tripping an error. Doing it through a function so that we'll be able - // to see it in any crash dumps. - WaitingForUIThreadToHandleIOError(); - return 0; - } - - // If there's an IO error it likely means the X server has gone away. - // If this CHECK fails, then that means SessionEnding() below triggered some - // code that tried to talk to the X server, resulting in yet another error. - CHECK(!g_in_x11_io_error_handler); - - g_in_x11_io_error_handler = true; - LOG(ERROR) << "X IO error received (X server probably went away)"; - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()); - - return 0; -} - -int X11EmptyErrorHandler(Display* d, XErrorEvent* error) { - return 0; -} - -int X11EmptyIOErrorHandler(Display* d) { - return 0; -} -#endif - -base::string16 MediaStringProvider(media::MessageId id) { - switch (id) { - case media::DEFAULT_AUDIO_DEVICE_NAME: - return base::ASCIIToUTF16("Default"); -#if defined(OS_WIN) - case media::COMMUNICATIONS_AUDIO_DEVICE_NAME: - return base::ASCIIToUTF16("Communications"); -#endif - default: - return base::string16(); - } -} - -} // namespace - -BrowserMainParts::BrowserMainParts() {} - -BrowserMainParts::~BrowserMainParts() {} - -#if defined(OS_WIN) || defined(OS_LINUX) -void OverrideAppLogsPath() { - base::FilePath path; - if (base::PathService::Get(brightray::DIR_APP_DATA, &path)) { - path = path.Append(base::FilePath::FromUTF8Unsafe(GetApplicationName())); - path = path.Append(base::FilePath::FromUTF8Unsafe("logs")); - base::PathService::Override(DIR_APP_LOGS, path); - } -} -#endif - -void BrowserMainParts::InitializeFeatureList() { - auto* cmd_line = base::CommandLine::ForCurrentProcess(); - auto enable_features = - cmd_line->GetSwitchValueASCII(switches::kEnableFeatures); - // Node depends on SharedArrayBuffer support, which was temporarily disabled - // by https://chromium-review.googlesource.com/c/chromium/src/+/849429 (in - // M64) and reenabled by - // https://chromium-review.googlesource.com/c/chromium/src/+/1159358 (in - // M70). Once Electron upgrades to M70, we can remove this. - enable_features += std::string(",") + features::kSharedArrayBuffer.name; - auto disable_features = - cmd_line->GetSwitchValueASCII(switches::kDisableFeatures); -#if defined(OS_MACOSX) - // Disable the V2 sandbox on macOS. - // Chromium is going to use the system sandbox API of macOS for the sandbox - // implmentation, we may have to deprecate --mixed-sandbox for macOS once - // Chromium drops support for the old sandbox implmentation. - disable_features += std::string(",") + features::kMacV2Sandbox.name; -#endif - auto feature_list = std::make_unique(); - feature_list->InitializeFromCommandLine(enable_features, disable_features); - base::FeatureList::SetInstance(std::move(feature_list)); -} - -bool BrowserMainParts::ShouldContentCreateFeatureList() { - return false; -} - -int BrowserMainParts::PreEarlyInitialization() { - InitializeFeatureList(); - OverrideAppLogsPath(); -#if defined(USE_X11) - views::LinuxUI::SetInstance(BuildGtkUi()); - OverrideLinuxAppDataPath(); - - // Installs the X11 error handlers for the browser process used during - // startup. They simply print error messages and exit because - // we can't shutdown properly while creating and initializing services. - ui::SetX11ErrorHandlers(nullptr, nullptr); -#endif - - return service_manager::RESULT_CODE_NORMAL_EXIT; -} - -void BrowserMainParts::ToolkitInitialized() { - ui::MaterialDesignController::Initialize(); - -#if defined(USE_AURA) && defined(USE_X11) - views::LinuxUI::instance()->Initialize(); -#endif - -#if defined(USE_AURA) - wm_state_.reset(new wm::WMState); -#endif - -#if defined(OS_WIN) - gfx::PlatformFontWin::adjust_font_callback = &AdjustUIFont; - gfx::PlatformFontWin::get_minimum_font_size_callback = &GetMinimumFontSize; - - wchar_t module_name[MAX_PATH] = {0}; - if (GetModuleFileName(NULL, module_name, MAX_PATH)) - ui::CursorLoaderWin::SetCursorResourceModule(module_name); -#endif -} - -void BrowserMainParts::PreMainMessageLoopStart() { - // Initialize ui::ResourceBundle. - ui::ResourceBundle::InitSharedInstanceWithLocale( - "", nullptr, ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES); - auto* cmd_line = base::CommandLine::ForCurrentProcess(); - if (cmd_line->HasSwitch(switches::kLang)) { - const std::string locale = cmd_line->GetSwitchValueASCII(switches::kLang); - const base::FilePath locale_file_path = - ui::ResourceBundle::GetSharedInstance().GetLocaleFilePath(locale, true); - if (!locale_file_path.empty()) { - custom_locale_ = locale; -#if defined(OS_LINUX) - /* When built with USE_GLIB, libcc's GetApplicationLocaleInternal() uses - * glib's g_get_language_names(), which keys off of getenv("LC_ALL") */ - g_setenv("LC_ALL", custom_locale_.c_str(), TRUE); -#endif - } - } - -#if defined(OS_MACOSX) - if (custom_locale_.empty()) - l10n_util::OverrideLocaleWithCocoaLocale(); -#endif - atom::LoadResourceBundle(custom_locale_); -#if defined(OS_MACOSX) - InitializeMainNib(); -#endif - media::SetLocalizedStringProvider(MediaStringProvider); -} - -void BrowserMainParts::PostMainMessageLoopStart() { -#if defined(USE_X11) - // Installs the X11 error handlers for the browser process after the - // main message loop has started. This will allow us to exit cleanly - // if X exits before us. - ui::SetX11ErrorHandlers(BrowserX11ErrorHandler, BrowserX11IOErrorHandler); -#endif -#if defined(OS_LINUX) - bluez::DBusBluezManagerWrapperLinux::Initialize(); -#endif -} - -void BrowserMainParts::PostMainMessageLoopRun() { -#if defined(USE_X11) - // Unset the X11 error handlers. The X11 error handlers log the errors using a - // |PostTask()| on the message-loop. But since the message-loop is in the - // process of terminating, this can cause errors. - ui::SetX11ErrorHandlers(X11EmptyErrorHandler, X11EmptyIOErrorHandler); -#endif -} - -int BrowserMainParts::PreCreateThreads() { -#if defined(USE_AURA) - display::Screen* screen = views::CreateDesktopScreen(); - display::Screen::SetScreenInstance(screen); -#if defined(USE_X11) - views::LinuxUI::instance()->UpdateDeviceScaleFactor(); -#endif -#endif - - if (!views::LayoutProvider::Get()) - layout_provider_.reset(new views::LayoutProvider()); - - return 0; -} - -void BrowserMainParts::PostDestroyThreads() { -#if defined(OS_LINUX) - device::BluetoothAdapterFactory::Shutdown(); - bluez::DBusBluezManagerWrapperLinux::Shutdown(); -#endif -} - -} // namespace brightray diff --git a/brightray/browser/browser_main_parts.h b/brightray/browser/browser_main_parts.h deleted file mode 100644 index 9c39fed898f0e..0000000000000 --- a/brightray/browser/browser_main_parts.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-CHROMIUM file. - -#ifndef BRIGHTRAY_BROWSER_BROWSER_MAIN_PARTS_H_ -#define BRIGHTRAY_BROWSER_BROWSER_MAIN_PARTS_H_ - -#include -#include - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/path_service.h" -#include "brightray/browser/brightray_paths.h" -#include "content/public/browser/browser_main_parts.h" -#include "ui/views/layout/layout_provider.h" - -#if defined(USE_AURA) -namespace wm { -class WMState; -} -#endif - -namespace brightray { - -class BrowserMainParts : public content::BrowserMainParts { - public: - BrowserMainParts(); - ~BrowserMainParts() override; - - protected: - // content::BrowserMainParts: - bool ShouldContentCreateFeatureList() override; - int PreEarlyInitialization() override; - void ToolkitInitialized() override; - void PreMainMessageLoopStart() override; - void PostMainMessageLoopStart() override; - void PostMainMessageLoopRun() override; - int PreCreateThreads() override; - void PostDestroyThreads() override; - - void InitializeFeatureList(); - - std::string custom_locale_; - - private: -#if defined(OS_MACOSX) - void InitializeMainNib(); - void OverrideAppLogsPath(); -#endif - -#if defined(USE_AURA) - std::unique_ptr wm_state_; -#endif - - std::unique_ptr layout_provider_; - - DISALLOW_COPY_AND_ASSIGN(BrowserMainParts); -}; - -} // namespace brightray - -#endif // BRIGHTRAY_BROWSER_BROWSER_MAIN_PARTS_H_ diff --git a/brightray/browser/browser_main_parts_mac.mm b/brightray/browser/browser_main_parts_mac.mm deleted file mode 100644 index b0deae60828c9..0000000000000 --- a/brightray/browser/browser_main_parts_mac.mm +++ /dev/null @@ -1,37 +0,0 @@ -#import "brightray/browser/browser_main_parts.h" - -#import -#import "base/logging.h" -#import "base/mac/bundle_locations.h" - -namespace brightray { - -void BrowserMainParts::OverrideAppLogsPath() { - base::FilePath path; - NSString* bundleName = - [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; - NSString* logsPath = - [NSString stringWithFormat:@"Library/Logs/%@", bundleName]; - NSString* libraryPath = - [NSHomeDirectory() stringByAppendingPathComponent:logsPath]; - - base::PathService::Override(DIR_APP_LOGS, - base::FilePath([libraryPath UTF8String])); -} - -// Replicates NSApplicationMain, but doesn't start a run loop. -void BrowserMainParts::InitializeMainNib() { - auto infoDictionary = base::mac::OuterBundle().infoDictionary; - - auto principalClass = - NSClassFromString([infoDictionary objectForKey:@"NSPrincipalClass"]); - auto application = [principalClass sharedApplication]; - - NSString* mainNibName = [infoDictionary objectForKey:@"NSMainNibFile"]; - auto mainNib = [[NSNib alloc] initWithNibNamed:mainNibName - bundle:base::mac::FrameworkBundle()]; - [mainNib instantiateWithOwner:application topLevelObjects:nil]; - [mainNib release]; -} - -} // namespace brightray