123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- // 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 "atom/browser/atom_browser_main_parts.h"
- #include "atom/browser/api/trackable_object.h"
- #include "atom/browser/atom_browser_client.h"
- #include "atom/browser/atom_browser_context.h"
- #include "atom/browser/bridge_task_runner.h"
- #include "atom/browser/browser.h"
- #include "atom/browser/javascript_environment.h"
- #include "atom/browser/node_debugger.h"
- #include "atom/common/api/atom_bindings.h"
- #include "atom/common/node_bindings.h"
- #include "atom/common/node_includes.h"
- #include "base/command_line.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "chrome/browser/browser_process.h"
- #include "content/public/browser/child_process_security_policy.h"
- #include "v8/include/v8-debug.h"
- #if defined(USE_X11)
- #include "chrome/browser/ui/libgtk2ui/gtk2_util.h"
- #include "ui/events/devices/x11/touch_factory_x11.h"
- #endif
- namespace atom {
- template<typename T>
- void Erase(T* container, typename T::iterator iter) {
- container->erase(iter);
- }
- // static
- AtomBrowserMainParts* AtomBrowserMainParts::self_ = nullptr;
- AtomBrowserMainParts::AtomBrowserMainParts()
- : fake_browser_process_(new BrowserProcess),
- exit_code_(nullptr),
- browser_(new Browser),
- node_bindings_(NodeBindings::Create(true)),
- atom_bindings_(new AtomBindings),
- gc_timer_(true, true) {
- DCHECK(!self_) << "Cannot have two AtomBrowserMainParts";
- self_ = this;
- // Register extension scheme as web safe scheme.
- content::ChildProcessSecurityPolicy::GetInstance()->
- RegisterWebSafeScheme("chrome-extension");
- }
- AtomBrowserMainParts::~AtomBrowserMainParts() {
- // Leak the JavascriptEnvironment on exit.
- // This is to work around the bug that V8 would be waiting for background
- // tasks to finish on exit, while somehow it waits forever in Electron, more
- // about this can be found at https://github.com/electron/electron/issues/4767.
- // On the other handle there is actually no need to gracefully shutdown V8
- // on exit in the main process, we already ensured all necessary resources get
- // cleaned up, and it would make quitting faster.
- ignore_result(js_env_.release());
- }
- // static
- AtomBrowserMainParts* AtomBrowserMainParts::Get() {
- DCHECK(self_);
- return self_;
- }
- bool AtomBrowserMainParts::SetExitCode(int code) {
- if (!exit_code_)
- return false;
- *exit_code_ = code;
- return true;
- }
- int AtomBrowserMainParts::GetExitCode() {
- return exit_code_ != nullptr ? *exit_code_ : 0;
- }
- base::Closure AtomBrowserMainParts::RegisterDestructionCallback(
- const base::Closure& callback) {
- auto iter = destructors_.insert(destructors_.end(), callback);
- return base::Bind(&Erase<std::list<base::Closure>>, &destructors_, iter);
- }
- void AtomBrowserMainParts::PreEarlyInitialization() {
- brightray::BrowserMainParts::PreEarlyInitialization();
- #if defined(OS_POSIX)
- HandleSIGCHLD();
- #endif
- }
- void AtomBrowserMainParts::PostEarlyInitialization() {
- brightray::BrowserMainParts::PostEarlyInitialization();
- // Temporary set the bridge_task_runner_ as current thread's task runner,
- // so we can fool gin::PerIsolateData to use it as its task runner, instead
- // of getting current message loop's task runner, which is null for now.
- bridge_task_runner_ = new BridgeTaskRunner;
- base::ThreadTaskRunnerHandle handle(bridge_task_runner_);
- // The ProxyResolverV8 has setup a complete V8 environment, in order to
- // avoid conflicts we only initialize our V8 environment after that.
- js_env_.reset(new JavascriptEnvironment);
- node_bindings_->Initialize();
- // Support the "--debug" switch.
- node_debugger_.reset(new NodeDebugger(js_env_->isolate()));
- // Create the global environment.
- node::Environment* env =
- node_bindings_->CreateEnvironment(js_env_->context());
- // Make sure node can get correct environment when debugging.
- if (node_debugger_->IsRunning())
- env->AssignToContext(v8::Debug::GetDebugContext());
- // Add Electron extended APIs.
- atom_bindings_->BindTo(js_env_->isolate(), env->process_object());
- // Load everything.
- node_bindings_->LoadEnvironment(env);
- // Wrap the uv loop with global env.
- node_bindings_->set_uv_env(env);
- }
- void AtomBrowserMainParts::PreMainMessageLoopRun() {
- js_env_->OnMessageLoopCreated();
- // Run user's main script before most things get initialized, so we can have
- // a chance to setup everything.
- node_bindings_->PrepareMessageLoop();
- node_bindings_->RunMessageLoop();
- #if defined(USE_X11)
- ui::TouchFactory::SetTouchDeviceListFromCommandLine();
- #endif
- // Start idle gc.
- gc_timer_.Start(
- FROM_HERE, base::TimeDelta::FromMinutes(1),
- base::Bind(&v8::Isolate::LowMemoryNotification,
- base::Unretained(js_env_->isolate())));
- brightray::BrowserMainParts::PreMainMessageLoopRun();
- bridge_task_runner_->MessageLoopIsReady();
- bridge_task_runner_ = nullptr;
- #if defined(USE_X11)
- libgtk2ui::GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess());
- #endif
- #if !defined(OS_MACOSX)
- // The corresponding call in macOS is in AtomApplicationDelegate.
- Browser::Get()->WillFinishLaunching();
- std::unique_ptr<base::DictionaryValue> empty_info(new base::DictionaryValue);
- Browser::Get()->DidFinishLaunching(*empty_info);
- #endif
- }
- bool AtomBrowserMainParts::MainMessageLoopRun(int* result_code) {
- exit_code_ = result_code;
- return brightray::BrowserMainParts::MainMessageLoopRun(result_code);
- }
- void AtomBrowserMainParts::PostMainMessageLoopStart() {
- brightray::BrowserMainParts::PostMainMessageLoopStart();
- #if defined(OS_POSIX)
- HandleShutdownSignals();
- #endif
- }
- void AtomBrowserMainParts::PostMainMessageLoopRun() {
- brightray::BrowserMainParts::PostMainMessageLoopRun();
- js_env_->OnMessageLoopDestroying();
- #if defined(OS_MACOSX)
- FreeAppDelegate();
- #endif
- // Make sure destruction callbacks are called before message loop is
- // destroyed, otherwise some objects that need to be deleted on IO thread
- // won't be freed.
- // We don't use ranged for loop because iterators are getting invalided when
- // the callback runs.
- for (auto iter = destructors_.begin(); iter != destructors_.end();) {
- base::Closure& callback = *iter;
- ++iter;
- callback.Run();
- }
- }
- } // namespace atom
|