atom_browser_main_parts.cc 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // Copyright (c) 2013 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "atom/browser/atom_browser_main_parts.h"
  5. #include "atom/browser/api/atom_api_app.h"
  6. #include "atom/browser/api/trackable_object.h"
  7. #include "atom/browser/atom_access_token_store.h"
  8. #include "atom/browser/atom_browser_client.h"
  9. #include "atom/browser/atom_browser_context.h"
  10. #include "atom/browser/bridge_task_runner.h"
  11. #include "atom/browser/browser.h"
  12. #include "atom/browser/javascript_environment.h"
  13. #include "atom/browser/node_debugger.h"
  14. #include "atom/common/api/atom_bindings.h"
  15. #include "atom/common/asar/asar_util.h"
  16. #include "atom/common/node_bindings.h"
  17. #include "base/command_line.h"
  18. #include "base/threading/thread_task_runner_handle.h"
  19. #include "chrome/browser/browser_process.h"
  20. #include "content/public/browser/child_process_security_policy.h"
  21. #include "device/geolocation/geolocation_delegate.h"
  22. #include "device/geolocation/geolocation_provider.h"
  23. #include "ui/base/idle/idle.h"
  24. #include "ui/base/l10n/l10n_util.h"
  25. #include "v8/include/v8-debug.h"
  26. #if defined(USE_X11)
  27. #include "chrome/browser/ui/libgtkui/gtk_util.h"
  28. #include "ui/events/devices/x11/touch_factory_x11.h"
  29. #endif
  30. #if defined(ENABLE_PDF_VIEWER)
  31. #include "atom/browser/atom_web_ui_controller_factory.h"
  32. #endif // defined(ENABLE_PDF_VIEWER)
  33. #if defined(OS_MACOSX)
  34. #include "atom/browser/ui/cocoa/views_delegate_mac.h"
  35. #else
  36. #include "brightray/browser/views/views_delegate.h"
  37. #endif
  38. // Must be included after all other headers.
  39. #include "atom/common/node_includes.h"
  40. namespace atom {
  41. namespace {
  42. // A provider of Geolocation services to override AccessTokenStore.
  43. class AtomGeolocationDelegate : public device::GeolocationDelegate {
  44. public:
  45. AtomGeolocationDelegate() {
  46. device::GeolocationProvider::GetInstance()
  47. ->UserDidOptIntoLocationServices();
  48. }
  49. scoped_refptr<device::AccessTokenStore> CreateAccessTokenStore() final {
  50. return new AtomAccessTokenStore();
  51. }
  52. private:
  53. DISALLOW_COPY_AND_ASSIGN(AtomGeolocationDelegate);
  54. };
  55. template <typename T>
  56. void Erase(T* container, typename T::iterator iter) {
  57. container->erase(iter);
  58. }
  59. } // namespace
  60. // static
  61. AtomBrowserMainParts* AtomBrowserMainParts::self_ = nullptr;
  62. AtomBrowserMainParts::AtomBrowserMainParts()
  63. : fake_browser_process_(new BrowserProcess),
  64. browser_(new Browser),
  65. node_bindings_(NodeBindings::Create(NodeBindings::BROWSER)),
  66. atom_bindings_(new AtomBindings(uv_default_loop())),
  67. gc_timer_(true, true) {
  68. DCHECK(!self_) << "Cannot have two AtomBrowserMainParts";
  69. self_ = this;
  70. // Register extension scheme as web safe scheme.
  71. content::ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme(
  72. "chrome-extension");
  73. }
  74. AtomBrowserMainParts::~AtomBrowserMainParts() {
  75. asar::ClearArchives();
  76. // Leak the JavascriptEnvironment on exit.
  77. // This is to work around the bug that V8 would be waiting for background
  78. // tasks to finish on exit, while somehow it waits forever in Electron, more
  79. // about this can be found at
  80. // https://github.com/electron/electron/issues/4767. On the other handle there
  81. // is actually no need to gracefully shutdown V8 on exit in the main process,
  82. // we already ensured all necessary resources get cleaned up, and it would
  83. // make quitting faster.
  84. ignore_result(js_env_.release());
  85. }
  86. // static
  87. AtomBrowserMainParts* AtomBrowserMainParts::Get() {
  88. DCHECK(self_);
  89. return self_;
  90. }
  91. bool AtomBrowserMainParts::SetExitCode(int code) {
  92. if (!exit_code_)
  93. return false;
  94. *exit_code_ = code;
  95. return true;
  96. }
  97. int AtomBrowserMainParts::GetExitCode() {
  98. return exit_code_ != nullptr ? *exit_code_ : 0;
  99. }
  100. void AtomBrowserMainParts::RegisterDestructionCallback(
  101. base::OnceClosure callback) {
  102. // The destructors should be called in reversed order, so dependencies between
  103. // JavaScript objects can be correctly resolved.
  104. // For example WebContentsView => WebContents => Session.
  105. destructors_.insert(destructors_.begin(), std::move(callback));
  106. }
  107. void AtomBrowserMainParts::PreEarlyInitialization() {
  108. brightray::BrowserMainParts::PreEarlyInitialization();
  109. #if defined(OS_POSIX)
  110. HandleSIGCHLD();
  111. #endif
  112. }
  113. void AtomBrowserMainParts::PostEarlyInitialization() {
  114. brightray::BrowserMainParts::PostEarlyInitialization();
  115. // Temporary set the bridge_task_runner_ as current thread's task runner,
  116. // so we can fool gin::PerIsolateData to use it as its task runner, instead
  117. // of getting current message loop's task runner, which is null for now.
  118. bridge_task_runner_ = new BridgeTaskRunner;
  119. base::ThreadTaskRunnerHandle handle(bridge_task_runner_);
  120. // The ProxyResolverV8 has setup a complete V8 environment, in order to
  121. // avoid conflicts we only initialize our V8 environment after that.
  122. js_env_.reset(new JavascriptEnvironment);
  123. node_bindings_->Initialize();
  124. // Create the global environment.
  125. node::Environment* env = node_bindings_->CreateEnvironment(
  126. js_env_->context(), js_env_->platform());
  127. node_env_.reset(new NodeEnvironment(env));
  128. // Enable support for v8 inspector
  129. node_debugger_.reset(new NodeDebugger(env));
  130. node_debugger_->Start(js_env_->platform());
  131. // Add Electron extended APIs.
  132. atom_bindings_->BindTo(js_env_->isolate(), env->process_object());
  133. // Load everything.
  134. node_bindings_->LoadEnvironment(env);
  135. // Wrap the uv loop with global env.
  136. node_bindings_->set_uv_env(env);
  137. }
  138. int AtomBrowserMainParts::PreCreateThreads() {
  139. const int result = brightray::BrowserMainParts::PreCreateThreads();
  140. if (!result) {
  141. fake_browser_process_->SetApplicationLocale(
  142. brightray::BrowserClient::Get()->GetApplicationLocale());
  143. }
  144. #if defined(OS_MACOSX)
  145. ui::InitIdleMonitor();
  146. #endif
  147. return result;
  148. }
  149. void AtomBrowserMainParts::ToolkitInitialized() {
  150. brightray::BrowserMainParts::ToolkitInitialized();
  151. #if defined(OS_MACOSX)
  152. views_delegate_.reset(new ViewsDelegateMac);
  153. #else
  154. views_delegate_.reset(new brightray::ViewsDelegate);
  155. #endif
  156. }
  157. void AtomBrowserMainParts::PreMainMessageLoopRun() {
  158. js_env_->OnMessageLoopCreated();
  159. // Run user's main script before most things get initialized, so we can have
  160. // a chance to setup everything.
  161. node_bindings_->PrepareMessageLoop();
  162. node_bindings_->RunMessageLoop();
  163. #if defined(USE_X11)
  164. ui::TouchFactory::SetTouchDeviceListFromCommandLine();
  165. #endif
  166. // Start idle gc.
  167. gc_timer_.Start(FROM_HERE, base::TimeDelta::FromMinutes(1),
  168. base::Bind(&v8::Isolate::LowMemoryNotification,
  169. base::Unretained(js_env_->isolate())));
  170. #if defined(ENABLE_PDF_VIEWER)
  171. content::WebUIControllerFactory::RegisterFactory(
  172. AtomWebUIControllerFactory::GetInstance());
  173. #endif // defined(ENABLE_PDF_VIEWER)
  174. brightray::BrowserMainParts::PreMainMessageLoopRun();
  175. bridge_task_runner_->MessageLoopIsReady();
  176. bridge_task_runner_ = nullptr;
  177. #if defined(USE_X11)
  178. libgtkui::GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess());
  179. #endif
  180. #if !defined(OS_MACOSX)
  181. // The corresponding call in macOS is in AtomApplicationDelegate.
  182. Browser::Get()->WillFinishLaunching();
  183. std::unique_ptr<base::DictionaryValue> empty_info(new base::DictionaryValue);
  184. Browser::Get()->DidFinishLaunching(*empty_info);
  185. #endif
  186. // Notify observers that main thread message loop was initialized.
  187. Browser::Get()->PreMainMessageLoopRun();
  188. }
  189. bool AtomBrowserMainParts::MainMessageLoopRun(int* result_code) {
  190. exit_code_ = result_code;
  191. return brightray::BrowserMainParts::MainMessageLoopRun(result_code);
  192. }
  193. void AtomBrowserMainParts::PostMainMessageLoopStart() {
  194. brightray::BrowserMainParts::PostMainMessageLoopStart();
  195. #if defined(OS_POSIX)
  196. HandleShutdownSignals();
  197. #endif
  198. device::GeolocationProvider::SetGeolocationDelegate(
  199. new AtomGeolocationDelegate());
  200. }
  201. void AtomBrowserMainParts::PostMainMessageLoopRun() {
  202. brightray::BrowserMainParts::PostMainMessageLoopRun();
  203. js_env_->OnMessageLoopDestroying();
  204. #if defined(OS_MACOSX)
  205. FreeAppDelegate();
  206. #endif
  207. // Make sure destruction callbacks are called before message loop is
  208. // destroyed, otherwise some objects that need to be deleted on IO thread
  209. // won't be freed.
  210. // We don't use ranged for loop because iterators are getting invalided when
  211. // the callback runs.
  212. for (auto iter = destructors_.begin(); iter != destructors_.end();) {
  213. base::OnceClosure callback = std::move(*iter);
  214. if (!callback.is_null())
  215. std::move(callback).Run();
  216. ++iter;
  217. }
  218. }
  219. } // namespace atom