From: ws29.jung Date: Tue, 27 Mar 2018 07:41:37 +0000 (+0900) Subject: Initial Implementation of Node prelaunch X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5f0fea7f7d8d9ce15680d45c76614081ece6845b;p=platform%2Fframework%2Fweb%2Fcrosswalk-tizen.git Initial Implementation of Node prelaunch 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 --- diff --git a/atom/app/runtime.h b/atom/app/runtime.h index baf9001b0..a5bcbc245 100644 --- a/atom/app/runtime.h +++ b/atom/app/runtime.h @@ -31,9 +31,11 @@ class Runtime { virtual int Exec() = 0; + virtual void SetParam(content::ContentMainParams *params) = 0; + static std::unique_ptr MakeRuntime(content::ContentMainParams *params); }; } // namespace runtime -#endif // RUNTIME_H_ \ No newline at end of file +#endif // RUNTIME_H_ diff --git a/atom/app/ui_runtime.cc b/atom/app/ui_runtime.cc index c773acaf5..7091bff27 100644 --- a/atom/app/ui_runtime.cc +++ b/atom/app/ui_runtime.cc @@ -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" @@ -29,15 +30,25 @@ #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; diff --git a/atom/app/ui_runtime.h b/atom/app/ui_runtime.h index 1c8ec225b..f32086b94 100644 --- a/atom/app/ui_runtime.h +++ b/atom/app/ui_runtime.h @@ -30,6 +30,7 @@ class UiRuntime : public Runtime { virtual ~UiRuntime(); virtual int Exec(); + virtual void SetParam(content::ContentMainParams *params); protected: virtual bool OnCreate(); diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 115041d00..638a76973 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -491,7 +491,8 @@ void OnIconDataAvailable(v8::Isolate* isolate, } // namespace App::App(v8::Isolate* isolate) { - static_cast(AtomBrowserClient::Get())->set_delegate(this); + if (AtomBrowserClient::Get()) + static_cast(AtomBrowserClient::Get())->set_delegate(this); Browser::Get()->AddObserver(this); content::GpuDataManager::GetInstance()->AddObserver(this); Init(isolate); diff --git a/atom/browser/api/atom_api_pwrt.cc b/atom/browser/api/atom_api_pwrt.cc index e8a75a613..e89b1dd0e 100644 --- a/atom/browser/api/atom_api_pwrt.cc +++ b/atom/browser/api/atom_api_pwrt.cc @@ -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::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 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 exports, v8::Local unused, v8::Local 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 diff --git a/atom/browser/api/trackable_object.cc b/atom/browser/api/trackable_object.cc index 502757aa2..59e43b269 100644 --- a/atom/browser/api/trackable_object.cc +++ b/atom/browser/api/trackable_object.cc @@ -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 diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index c5155be2f..f718f86de 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -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 self_bridge_task_runner; +std::unique_ptr self_browser; +std::unique_ptr self_js_env; +std::unique_ptr self_node_bindings; +std::unique_ptr self_atom_bindings; +std::unique_ptr self_node_env; +std::unique_ptr 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 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 diff --git a/atom/browser/atom_browser_main_parts.h b/atom/browser/atom_browser_main_parts.h index 2ba7d341f..ca505f767 100644 --- a/atom/browser/atom_browser_main_parts.h +++ b/atom/browser/atom_browser_main_parts.h @@ -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: diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 2a36143ee..dea0bf267 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -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() { diff --git a/lib/browser/init.js b/lib/browser/init.js index a220069bf..6c8ac89d1 100644 --- a/lib/browser/init.js +++ b/lib/browser/init.js @@ -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. diff --git a/tizen/common/command_line.cc b/tizen/common/command_line.cc index 6ee518a1e..ecf6d3cb9 100644 --- a/tizen/common/command_line.cc +++ b/tizen/common/command_line.cc @@ -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 diff --git a/tizen/common/command_line.h b/tizen/common/command_line.h index 68548086f..1c7bae0c6 100644 --- a/tizen/common/command_line.h +++ b/tizen/common/command_line.h @@ -30,7 +30,7 @@ class CommandLine { // Arguments which except for option strings typedef std::vector Arguments; - static void Init(int argc, char* argv[]); + static bool Init(int argc, char* argv[]); static CommandLine* ForCurrentProcess(); static void Reset(); diff --git a/tizen/src/wrt_main.cc b/tizen/src/wrt_main.cc index 799621ccf..0bf3635ef 100644 --- a/tizen/src/wrt_main.cc +++ b/tizen/src/wrt_main.cc @@ -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_; + // 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(argv))) - return 1; + if (!g_initialized_) { + if (efl::Initialize(argc, const_cast(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::MakeRuntime(¶ms); - return runtime->Exec(); + if (!g_initialized_) { + runtime_ = runtime::Runtime::MakeRuntime(¶ms); + } else { + runtime_->SetParam(¶ms); + } + 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(argv))) + return 1; + + atom::AtomMainDelegate delegate; + content::ContentMainParams params(&delegate); + params.argc = argc; + params.argv = const_cast(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(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(argv)); } } diff --git a/wrt/src/web_window.js b/wrt/src/web_window.js index 9c552be4f..52582344d 100644 --- a/wrt/src/web_window.js +++ b/wrt/src/web_window.js @@ -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();