123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- // 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/browser.h"
- #include <memory>
- #include <string>
- #include <utility>
- #include "base/files/file_util.h"
- #include "base/no_destructor.h"
- #include "base/path_service.h"
- #include "base/run_loop.h"
- #include "base/threading/thread_restrictions.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "chrome/common/chrome_paths.h"
- #include "shell/browser/browser_observer.h"
- #include "shell/browser/electron_browser_main_parts.h"
- #include "shell/browser/login_handler.h"
- #include "shell/browser/native_window.h"
- #include "shell/browser/window_list.h"
- #include "shell/common/application_info.h"
- #include "shell/common/electron_paths.h"
- #include "shell/common/gin_helper/arguments.h"
- namespace electron {
- namespace {
- // Call |quit| after Chromium is fully started.
- //
- // This is important for quitting immediately in the "ready" event, when
- // certain initialization task may still be pending, and quitting at that time
- // could end up with crash on exit.
- void RunQuitClosure(base::OnceClosure quit) {
- // On Linux/Windows the "ready" event is emitted in "PreMainMessageLoopRun",
- // make sure we quit after message loop has run for once.
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(quit));
- }
- } // namespace
- #if BUILDFLAG(IS_WIN)
- Browser::LaunchItem::LaunchItem() = default;
- Browser::LaunchItem::~LaunchItem() = default;
- Browser::LaunchItem::LaunchItem(const LaunchItem& other) = default;
- #endif
- Browser::LoginItemSettings::LoginItemSettings() = default;
- Browser::LoginItemSettings::~LoginItemSettings() = default;
- Browser::LoginItemSettings::LoginItemSettings(const LoginItemSettings& other) =
- default;
- Browser::Browser() {
- WindowList::AddObserver(this);
- }
- Browser::~Browser() {
- WindowList::RemoveObserver(this);
- }
- // static
- Browser* Browser::Get() {
- return ElectronBrowserMainParts::Get()->browser();
- }
- #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
- void Browser::Focus(gin::Arguments* args) {
- // Focus on the first visible window.
- for (auto* const window : WindowList::GetWindows()) {
- if (window->IsVisible()) {
- window->Focus(true);
- break;
- }
- }
- }
- #endif
- void Browser::Quit() {
- if (is_quitting_)
- return;
- is_quitting_ = HandleBeforeQuit();
- if (!is_quitting_)
- return;
- if (electron::WindowList::IsEmpty())
- NotifyAndShutdown();
- else
- electron::WindowList::CloseAllWindows();
- }
- void Browser::Exit(gin::Arguments* args) {
- int code = 0;
- args->GetNext(&code);
- if (!ElectronBrowserMainParts::Get()->SetExitCode(code)) {
- // Message loop is not ready, quit directly.
- exit(code);
- } else {
- // Prepare to quit when all windows have been closed.
- is_quitting_ = true;
- // Remember this caller so that we don't emit unrelated events.
- is_exiting_ = true;
- // Must destroy windows before quitting, otherwise bad things can happen.
- if (electron::WindowList::IsEmpty()) {
- Shutdown();
- } else {
- // Unlike Quit(), we do not ask to close window, but destroy the window
- // without asking.
- electron::WindowList::DestroyAllWindows();
- }
- }
- }
- void Browser::Shutdown() {
- if (is_shutdown_)
- return;
- is_shutdown_ = true;
- is_quitting_ = true;
- for (BrowserObserver& observer : observers_)
- observer.OnQuit();
- if (quit_main_message_loop_) {
- RunQuitClosure(std::move(quit_main_message_loop_));
- } else {
- // There is no message loop available so we are in early stage, wait until
- // the quit_main_message_loop_ is available.
- // Exiting now would leave defunct processes behind.
- }
- }
- std::string Browser::GetVersion() const {
- std::string ret = OverriddenApplicationVersion();
- if (ret.empty())
- ret = GetExecutableFileVersion();
- return ret;
- }
- void Browser::SetVersion(const std::string& version) {
- OverriddenApplicationVersion() = version;
- }
- std::string Browser::GetName() const {
- std::string ret = OverriddenApplicationName();
- if (ret.empty())
- ret = GetExecutableFileProductName();
- return ret;
- }
- void Browser::SetName(const std::string& name) {
- OverriddenApplicationName() = name;
- }
- int Browser::GetBadgeCount() {
- return badge_count_;
- }
- bool Browser::OpenFile(const std::string& file_path) {
- bool prevent_default = false;
- for (BrowserObserver& observer : observers_)
- observer.OnOpenFile(&prevent_default, file_path);
- return prevent_default;
- }
- void Browser::OpenURL(const std::string& url) {
- for (BrowserObserver& observer : observers_)
- observer.OnOpenURL(url);
- }
- void Browser::Activate(bool has_visible_windows) {
- for (BrowserObserver& observer : observers_)
- observer.OnActivate(has_visible_windows);
- }
- void Browser::WillFinishLaunching() {
- for (BrowserObserver& observer : observers_)
- observer.OnWillFinishLaunching();
- }
- void Browser::DidFinishLaunching(base::DictionaryValue launch_info) {
- // Make sure the userData directory is created.
- base::ThreadRestrictions::ScopedAllowIO allow_io;
- base::FilePath user_data;
- if (base::PathService::Get(chrome::DIR_USER_DATA, &user_data))
- base::CreateDirectoryAndGetError(user_data, nullptr);
- is_ready_ = true;
- if (ready_promise_) {
- ready_promise_->Resolve();
- }
- for (BrowserObserver& observer : observers_)
- observer.OnFinishLaunching(launch_info);
- }
- v8::Local<v8::Value> Browser::WhenReady(v8::Isolate* isolate) {
- if (!ready_promise_) {
- ready_promise_ = std::make_unique<gin_helper::Promise<void>>(isolate);
- if (is_ready()) {
- ready_promise_->Resolve();
- }
- }
- return ready_promise_->GetHandle();
- }
- void Browser::OnAccessibilitySupportChanged() {
- for (BrowserObserver& observer : observers_)
- observer.OnAccessibilitySupportChanged();
- }
- void Browser::PreMainMessageLoopRun() {
- for (BrowserObserver& observer : observers_) {
- observer.OnPreMainMessageLoopRun();
- }
- }
- void Browser::PreCreateThreads() {
- for (BrowserObserver& observer : observers_) {
- observer.OnPreCreateThreads();
- }
- }
- void Browser::SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure) {
- if (is_shutdown_)
- RunQuitClosure(std::move(quit_closure));
- else
- quit_main_message_loop_ = std::move(quit_closure);
- }
- void Browser::NotifyAndShutdown() {
- if (is_shutdown_)
- return;
- bool prevent_default = false;
- for (BrowserObserver& observer : observers_)
- observer.OnWillQuit(&prevent_default);
- if (prevent_default) {
- is_quitting_ = false;
- return;
- }
- Shutdown();
- }
- bool Browser::HandleBeforeQuit() {
- bool prevent_default = false;
- for (BrowserObserver& observer : observers_)
- observer.OnBeforeQuit(&prevent_default);
- return !prevent_default;
- }
- void Browser::OnWindowCloseCancelled(NativeWindow* window) {
- if (is_quitting_)
- // Once a beforeunload handler has prevented the closing, we think the quit
- // is cancelled too.
- is_quitting_ = false;
- }
- void Browser::OnWindowAllClosed() {
- if (is_exiting_) {
- Shutdown();
- } else if (is_quitting_) {
- NotifyAndShutdown();
- } else {
- for (BrowserObserver& observer : observers_)
- observer.OnWindowAllClosed();
- }
- }
- #if BUILDFLAG(IS_MAC)
- void Browser::NewWindowForTab() {
- for (BrowserObserver& observer : observers_)
- observer.OnNewWindowForTab();
- }
- void Browser::DidBecomeActive() {
- for (BrowserObserver& observer : observers_)
- observer.OnDidBecomeActive();
- }
- #endif
- } // namespace electron
|