Initial Implementation of Node prelaunch 62/173962/9
authorws29.jung <ws29.jung@samsung.com>
Tue, 27 Mar 2018 07:41:37 +0000 (16:41 +0900)
committerjaekuk lee <juku1999@samsung.com>
Thu, 5 Apr 2018 23:44:52 +0000 (23:44 +0000)
This patch is created to reduce WebApp launching time by using
method of Node environment prelaunching.
Prelaunch will load and run electron.asar and app.asar
then it will wait until onCreate event emit.
onCreate event will be triggered when actual WebApp is launched.

Change-Id: I42f198e9755dd8e017691c22edf96eef15cb3eb5
Signed-off-by: ws29.jung <ws29.jung@samsung.com>
14 files changed:
atom/app/runtime.h
atom/app/ui_runtime.cc
atom/app/ui_runtime.h
atom/browser/api/atom_api_app.cc
atom/browser/api/atom_api_pwrt.cc
atom/browser/api/trackable_object.cc
atom/browser/atom_browser_main_parts.cc
atom/browser/atom_browser_main_parts.h
atom/browser/browser.cc
lib/browser/init.js
tizen/common/command_line.cc
tizen/common/command_line.h
tizen/src/wrt_main.cc
wrt/src/web_window.js

index baf9001b09e73cf32f0f1c33ea453d76ee59a96e..a5bcbc2459d566206a0f8784e6b9d1a0dd6a22df 100644 (file)
@@ -31,9 +31,11 @@ class Runtime {
 
   virtual int Exec() = 0;
 
+  virtual void SetParam(content::ContentMainParams *params) = 0;
+
   static std::unique_ptr<Runtime> MakeRuntime(content::ContentMainParams *params);
 };
 
 }  // namespace runtime
 
-#endif  // RUNTIME_H_
\ No newline at end of file
+#endif  // RUNTIME_H_
index c773acaf5aa63733449d7b8c3721c741927f1bfe..7091bff27231c9c3a14324864c38702a6106536d 100644 (file)
@@ -22,6 +22,7 @@
 #include "atom/app/ui_runtime.h"
 #include "atom/browser/browser.h"
 #include "atom/browser/atom_browser_client.h"
+#include "atom/browser/atom_browser_main_parts.h"
 #include "atom/common/atom_command_line.h"
 #include "base/logging.h"
 #include "content/public/app/content_main.h"
 #include "tizen/common/app_control.h"
 #include "tizen/common/constants.h"
 
+#include "gin/v8_initializer.h"
+
 namespace runtime {
 
 UiRuntime::UiRuntime(content::ContentMainParams *params) {
   _params = params;
+
+  atom::AtomBrowserMainParts::SetNodeEnvironment();
 }
 
 UiRuntime::~UiRuntime() {
 }
 
+void UiRuntime::SetParam(content::ContentMainParams *params) {
+  if (_params)
+    LOG(ERROR) << "Use SetParam only when params is null";
+  else
+    _params = params;
+}
 
 bool UiRuntime::OnCreate() {
   return true;
index 1c8ec225bccbd00bc9e8de03409b1abadc843894..f32086b94edc03ad4708b0928d189d2267103b8d 100644 (file)
@@ -30,6 +30,7 @@ class UiRuntime : public Runtime {
   virtual ~UiRuntime();
 
   virtual int Exec();
+  virtual void SetParam(content::ContentMainParams *params);
 
  protected:
   virtual bool OnCreate();
index 115041d0082d09cb30bf944a814f149abe900a17..638a76973408b44f194c5493d6c5504296ef0920 100644 (file)
@@ -491,7 +491,8 @@ void OnIconDataAvailable(v8::Isolate* isolate,
 }  // namespace
 
 App::App(v8::Isolate* isolate) {
-  static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(this);
+  if (AtomBrowserClient::Get())
+    static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(this);
   Browser::Get()->AddObserver(this);
   content::GpuDataManager::GetInstance()->AddObserver(this);
   Init(isolate);
index e8a75a613867aebaec02490fa2331773d0ede660..e89b1dd0e13296783a09744f3a36a4924abf249a 100644 (file)
@@ -14,32 +14,35 @@ namespace atom {
 namespace api {
 
 PWRT::PWRT(v8::Isolate* isolate) {
-  LOG(INFO) << "PWRT::PWRT";
+  LOG(ERROR) << "PWRT::PWRT";
   Init(isolate);
 }
 
 PWRT::~PWRT() {
-  LOG(INFO) << "PWRT::~PWRT";
+  LOG(ERROR) << "PWRT::~PWRT";
 }
 
 std::string PWRT::GetMessage() {
-  LOG(INFO) << "PWRT::GetMessage";
+  LOG(ERROR) << "PWRT::GetMessage";
   return "message from C++";
 }
 
 std::string PWRT::GetPath() {
-  LOG(INFO) << "PWRT::GetPath";
+  LOG(ERROR) << "PWRT::GetPath";
   common::CommandLine* runtime_cmd = common::CommandLine::ForCurrentProcess();
-  std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/electron");
-  auto appdata_manager = common::ApplicationDataManager::GetInstance();
-  common::ApplicationData* app_data = appdata_manager->GetApplicationData(appid);
-  // TODO: Use resource-manager's GetStartResource() for localized urls
-  std::string app_path = "file://" + app_data->application_path() + app_data->content_info()->src();
-  return app_path;
+  if (runtime_cmd) {
+    std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/electron");
+    auto appdata_manager = common::ApplicationDataManager::GetInstance();
+    common::ApplicationData* app_data = appdata_manager->GetApplicationData(appid);
+    // TODO: Use resource-manager's GetStartResource() for localized urls
+    std::string app_path = "file://" + app_data->application_path() + app_data->content_info()->src();
+    return app_path;
+  }
+  return "";
 }
 
 bool PWRT::isTizenWebApp() {
-  LOG(INFO) << "PWRT::isTizenWebApp";
+  LOG(ERROR) << "PWRT::isTizenWebApp";
   common::CommandLine* runtime_cmd = common::CommandLine::ForCurrentProcess();
   std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/electron");
   if (appid != "electron") { // TODO: Any better distinguishing feature?
@@ -56,14 +59,14 @@ void PWRT::Log(const std::string& message) {
 
 // static
 mate::Handle<PWRT> PWRT::Create(v8::Isolate* isolate) {
-  LOG(INFO) << "PWRT::Create";
+  LOG(ERROR) << "PWRT::Create";
   return mate::CreateHandle(isolate, new PWRT(isolate));
 }
 
 // static
 void PWRT::BuildPrototype(
     v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
-  LOG(INFO) << "PWRT::BuildPrototype";
+  LOG(ERROR) << "PWRT::BuildPrototype";
   prototype->SetClassName(mate::StringToV8(isolate, "PWRT"));
   // TODO: Needs adding necessary interface methods
   mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
@@ -82,7 +85,7 @@ namespace {
 
 void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
                 v8::Local<v8::Context> context, void* priv) {
-  LOG(INFO) << "PWRT::Initialize";
+  LOG(ERROR) << "PWRT::Initialize";
   v8::Isolate* isolate = context->GetIsolate();
   mate::Dictionary dict(isolate, exports);
   // TODO: Expose this attribute only for Tizen web apps
index 502757aa237d8d2fc5fe84aec38e150c7a2a567e..59e43b26977a4ac4ad7d48b02dbcfb335b96ec85 100644 (file)
@@ -61,7 +61,8 @@ int32_t TrackableObjectBase::GetIDFromWrappedClass(base::SupportsUserData* w) {
 // static
 base::Closure TrackableObjectBase::RegisterDestructionCallback(
     const base::Closure& c) {
-  return atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(c);
+  if (atom::AtomBrowserMainParts::Get())
+    return atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(c);
 }
 
 }  // namespace mate
index c5155be2fa91f38f4a6ed4ab06957209f3c1b884..f718f86de7f61f5fb8bb5b20a5f1504d40b9a4eb 100644 (file)
@@ -18,6 +18,7 @@
 #include "atom/common/node_bindings.h"
 #include "atom/common/node_includes.h"
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/browser_process.h"
 #include "content/public/browser/child_process_security_policy.h"
@@ -25,6 +26,8 @@
 #include "device/geolocation/geolocation_provider.h"
 #include "v8/include/v8-debug.h"
 
+#include "gin/v8_initializer.h"
+
 #if defined(USE_X11)
 #include "chrome/browser/ui/libgtkui/gtk_util.h"
 #include "ui/events/devices/x11/touch_factory_x11.h"
@@ -61,16 +64,36 @@ void Erase(T* container, typename T::iterator iter) {
 }  // namespace
 
 // static
+bool g_prelaunch = false;
 AtomBrowserMainParts* AtomBrowserMainParts::self_ = nullptr;
+node::Environment* env_ = nullptr;
+scoped_refptr<BridgeTaskRunner> self_bridge_task_runner;
+std::unique_ptr<Browser> self_browser;
+std::unique_ptr<JavascriptEnvironment> self_js_env;
+std::unique_ptr<NodeBindings> self_node_bindings;
+std::unique_ptr<AtomBindings> self_atom_bindings;
+std::unique_ptr<NodeEnvironment> self_node_env;
+std::unique_ptr<NodeDebugger> self_node_debugger;
 
 AtomBrowserMainParts::AtomBrowserMainParts()
     : fake_browser_process_(new BrowserProcess),
       exit_code_(nullptr),
-      browser_(new Browser),
-      node_bindings_(NodeBindings::Create(NodeBindings::BROWSER)),
-      atom_bindings_(new AtomBindings(uv_default_loop())),
       gc_timer_(true, true) {
   DCHECK(!self_) << "Cannot have two AtomBrowserMainParts";
+  if (g_prelaunch) {
+    browser_ = std::move(self_browser);
+    node_bindings_ = std::move(self_node_bindings);
+    atom_bindings_ = std::move(self_atom_bindings);
+
+    js_env_ = std::move(self_js_env);
+    node_debugger_ = std::move(self_node_debugger);
+    bridge_task_runner_ = self_bridge_task_runner;
+    node_env_ = std::move(self_node_env);
+  } else {
+    browser_.reset(new Browser);
+    node_bindings_.reset(NodeBindings::Create(NodeBindings::BROWSER));
+    atom_bindings_.reset(new AtomBindings(uv_default_loop()));
+  }
   self_ = this;
   // Register extension scheme as web safe scheme.
   content::ChildProcessSecurityPolicy::GetInstance()->
@@ -95,6 +118,44 @@ AtomBrowserMainParts* AtomBrowserMainParts::Get() {
   return self_;
 }
 
+Browser* AtomBrowserMainParts::GetStaticBrowser() {
+  return self_browser.get();
+}
+
+void AtomBrowserMainParts::SetNodeEnvironment() {
+  if (g_prelaunch)
+    return;
+
+  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+  feature_list->InitializeFromCommandLine("", "");
+  base::FeatureList::SetInstance(std::move(feature_list));
+
+  gin::V8Initializer::LoadV8Snapshot();
+  gin::V8Initializer::LoadV8Natives();
+
+  self_browser.reset(new atom::Browser);
+  self_bridge_task_runner = new atom::BridgeTaskRunner;
+  base::ThreadTaskRunnerHandle handle(self_bridge_task_runner);
+
+  self_js_env.reset(new atom::JavascriptEnvironment);
+  self_node_bindings.reset(atom::NodeBindings::Create(atom::NodeBindings::BROWSER));
+  self_atom_bindings.reset(new atom::AtomBindings(uv_default_loop()));
+  self_node_bindings->Initialize();
+
+  self_node_debugger.reset(new atom::NodeDebugger(self_js_env->isolate()));
+  env_ = self_node_bindings->CreateEnvironment(self_js_env->context());
+  self_node_env.reset(new atom::NodeEnvironment(env_));
+
+  if (self_node_debugger->IsRunning())
+    env_->AssignToContext(v8::Debug::GetDebugContext(self_js_env->isolate()));
+
+  self_atom_bindings->BindTo(self_js_env->isolate(), env_->process_object());
+
+  self_node_bindings->LoadEnvironment(env_);
+  self_node_bindings->set_uv_env(env_);
+  g_prelaunch = true;
+}
+
 bool AtomBrowserMainParts::SetExitCode(int code) {
   if (!exit_code_)
     return false;
@@ -122,6 +183,8 @@ void AtomBrowserMainParts::PreEarlyInitialization() {
 
 void AtomBrowserMainParts::PostEarlyInitialization() {
   brightray::BrowserMainParts::PostEarlyInitialization();
+  if (g_prelaunch)
+      return;
 
   // 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
index 2ba7d341f430a56d03e34176747c4f540ee6b080..ca505f7670eca4e90d5672f5e64d3e1e5295bc09 100644 (file)
@@ -43,7 +43,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
   // Returns a closure that can be used to remove |callback| from the list.
   base::Closure RegisterDestructionCallback(const base::Closure& callback);
 
+  static void SetNodeEnvironment();
+
   Browser* browser() { return browser_.get(); }
+  static Browser* GetStaticBrowser();
 
  protected:
   // content::BrowserMainParts:
index 2a36143eed4dfea8e78356fe4dd4cdaf41142165..dea0bf267acfe4d4c729ac8893667349d1e7050d 100644 (file)
@@ -35,7 +35,10 @@ Browser::~Browser() {
 
 // static
 Browser* Browser::Get() {
-  return AtomBrowserMainParts::Get()->browser();
+  if (AtomBrowserMainParts::Get())
+    return AtomBrowserMainParts::Get()->browser();
+  else
+    return AtomBrowserMainParts::GetStaticBrowser();
 }
 
 void Browser::Quit() {
index a220069bf96693f179cb340b534c336cc2502482..6c8ac89d1fcd37c75433d0396f91d2af838b93f8 100644 (file)
@@ -169,7 +169,9 @@ app.setPath('userCache', path.join(app.getPath('cache'), app.getName()))
 app.setAppPath(packagePath)
 
 // Load the chrome extension support.
-require('./chrome-extension')
+// FIXME: When prelaunch, initializing electron modules
+//        in chrome-extension cause segmentation fault.
+//require('./chrome-extension')
 
 // Load internal desktop-capturer module.
 // FIXME: This is guard for bringup.
index 6ee518a1eb731f48291f0dd6a8bfbf90dc68a817..ecf6d3cb9806e32d978f1d32b36585411905b97f 100644 (file)
@@ -131,10 +131,12 @@ void CommandLine::Reset() {
 }
 
 // static
-void CommandLine::Init(int argc, char* argv[]) {
+bool CommandLine::Init(int argc, char* argv[]) {
   if (!current_process_commandline_) {
     current_process_commandline_ = new CommandLine(argc, argv);
+    return true;
   }
+  return false;
 }
 
 // static
index 68548086f6d806ac3d9e9364f4078402fdf5a4c1..1c7bae0c6d94d8ca80267905a31f654519cf1e30 100644 (file)
@@ -30,7 +30,7 @@ class CommandLine {
   // Arguments which except for option strings
   typedef std::vector<std::string> Arguments;
 
-  static void Init(int argc, char* argv[]);
+  static bool Init(int argc, char* argv[]);
   static CommandLine* ForCurrentProcess();
   static void Reset();
 
index 799621ccf8ba6721c98dff6fa1eea6baf505437b..0bf3635efb0e86e06edc8b81ee6817f10a8efe49 100644 (file)
@@ -138,6 +138,9 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
 #elif defined(OS_LINUX)  // defined(OS_WIN)
 
 #if defined(OS_TIZEN)
+bool g_initialized_ = false;
+std::unique_ptr<runtime::Runtime> runtime_;
+
 // For debug purpose only.
 // TODO: To be removed later
 bool hasTizenPackageID(int argc, const char* const* argv) {
@@ -153,6 +156,8 @@ int real_main(int argc, char* argv[]) {
 #else
 int main(int argc, char* argv[]) {
 #endif
+  for (int i = 0; i < argc; ++i)
+    LOG(ERROR) << "argv[" << i << "] : " << argv[i];
   if (IsEnvSet(kRunAsNode)) {
     base::i18n::InitializeICU();
     base::AtExitManager atexit_manager;
@@ -160,7 +165,15 @@ int main(int argc, char* argv[]) {
   }
 
 #if defined(USE_EFL)
-  common::CommandLine::Init(argc, argv);
+  if (!common::CommandLine::Init(argc, argv)) {
+    common::CommandLine::Reset();
+    common::CommandLine::Init(argc, argv);
+  }
+
+  if (!base::CommandLine::Init(argc, argv)) {
+    base::CommandLine::Reset();
+    base::CommandLine::Init(argc, argv);
+  }
   common::CommandLine* runtime_cmd = common::CommandLine::ForCurrentProcess();
   std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/wrt");
 
@@ -172,9 +185,10 @@ int main(int argc, char* argv[]) {
       return false;
     }
   }
-
-  if (efl::Initialize(argc, const_cast<const char**>(argv)))
-    return 1;
+  if (!g_initialized_) {
+    if (efl::Initialize(argc, const_cast<const char**>(argv)))
+      return 1;
+  }
 
   // Add params for EFL port
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -193,8 +207,12 @@ int main(int argc, char* argv[]) {
 #if defined(OS_TIZEN)
   if (hasTizenPackageID(argc,argv)) { // TODO: Check to be removed later
     elm_init(argc, argv);
-    std::unique_ptr<runtime::Runtime> runtime = runtime::Runtime::MakeRuntime(&params);
-    return runtime->Exec();
+    if (!g_initialized_) {
+      runtime_ = runtime::Runtime::MakeRuntime(&params);
+    } else {
+      runtime_->SetParam(&params);
+    }
+    return runtime_->Exec();
   }
 #endif
   return content::ContentMain(params);
@@ -203,16 +221,29 @@ int main(int argc, char* argv[]) {
 #if defined(OS_TIZEN)
 __attribute__((visibility("default")))
 int main(int argc, const char* argv[]) {
+  for (int i = 0; i < argc; ++i)
+    LOG(ERROR) << "argv[" << i << "] : " << argv[i];
   if (strcmp(argv[0], "/usr/bin/wrt-loader") == 0) {
-    LOG(INFO) << "run with wrt-loader";
-    auto preload = [argv](void) {
+    LOG(ERROR) << "run with wrt-loader";
+    auto preload = [argc, argv](void) {
+      g_initialized_ = true;
+      if (efl::Initialize(argc, const_cast<const char**>(argv)))
+        return 1;
+
+      atom::AtomMainDelegate delegate;
+      content::ContentMainParams params(&delegate);
+      params.argc = argc;
+      params.argv = const_cast<const char**>(argv);
+      atom::AtomCommandLine::Init(argc, argv);
+      runtime_ = runtime::Runtime::MakeRuntime(nullptr);
+      return 0;
     };
     auto did_launch = [](const std::string& app_path) {
     };
     auto prelaunch = runtime::PreLauncher::Prelaunch;
     return prelaunch(argc, const_cast<char**>(argv), preload, did_launch, real_main);
   } else {
-    LOG(INFO) << "run without wrt-loader";
+    LOG(ERROR) << "run without wrt-loader";
     return real_main(argc, const_cast<char**>(argv));
   }
 }
index 9c552be4fb79494161cb2a50c20ddc07879c4587..52582344d7c1d02a4f5d4c3afa6d581957ebda75 100644 (file)
@@ -212,7 +212,12 @@ class WebWindow {
         });
     }
     setUrl(path) {
-        this.mainWindow.loadURL(path);
+        if (path && (path.trim() != '')) {
+            this.mainWindow.loadURL(path);
+        } else {
+            const {pwrt} = require('electron');
+            this.mainWindow.loadURL(pwrt.getPath());
+        }
     }
     show() {
         this.mainWindow.show();