BuildRequires: pkgconfig(pkgmgr-info)
BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(uuid)
+BuildRequires: pkgconfig(launchpad)
+
+Requires: /usr/bin/systemctl
%description
Crosswalk Runtime and AppShell for Tizen 3.0 and later
# xwalk_runtime
install -p -m 755 out/Default/xwalk_runtime %{buildroot}%{_bindir}
ln -s %{_bindir}/xwalk_runtime %{buildroot}%{_bindir}/wrt
+ln -s %{_bindir}/xwalk_runtime %{buildroot}%{_bindir}/wrt-loader
# xwalk_runtime_resources
for file in $(find out/Default/gen/locales -type f -name *.mo); do
%attr(644,root,root) %{extension_path}/splash_screen.json
%attr(755,root,root) %{_bindir}/xwalk_runtime
%attr(755,root,root) %{_bindir}/wrt
+%attr(755,root,root) %{_bindir}/wrt-loader
+%caps(cap_mac_admin,cap_mac_override,cap_setgid=ei) %{_bindir}/xwalk_runtime
}
void NativeWindow::Initialize() {
+ if (initialized_) {
+ LOGGER(DEBUG) << "already initialized";
+ return;
+ }
// window
window_ = CreateWindowInternal();
elm_win_conformant_set(window_, EINA_TRUE);
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "runtime/browser/prelauncher.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <launchpad.h>
+
+#include <csignal>
+#include <memory>
+
+#include "common/logger.h"
+#include "common/profiler.h"
+
+namespace runtime {
+
+namespace {
+std::string g_smacklabel;
+
+int SmackLabelSetForTask(const std::string& label) {
+ int ret;
+ int fd;
+ char path[1024] = {0};
+ int tid = static_cast<int>(syscall(__NR_gettid));
+ snprintf(path, sizeof(path), "/proc/%d/attr/current", tid);
+ fd = open(path, O_WRONLY);
+ if (fd < 0)
+ return -1;
+ ret = write(fd, label.c_str(), label.length());
+ close(fd);
+ return (ret < 0) ? -1 : 0;
+}
+
+void ChangePrivilegeForThreads(const std::string& appid) {
+ SCOPE_PROFILE();
+ g_smacklabel = "User::App::" + appid;
+ auto oldhandler = std::signal(SIGUSR1, [](int signo){
+ SmackLabelSetForTask(g_smacklabel);
+ });
+
+ int current_tid = static_cast<int>(syscall(__NR_gettid));
+
+ DIR* dir;
+ struct dirent entry;
+ struct dirent* result;
+
+ if ((dir = opendir("/proc/self/task")) != NULL) {
+ while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
+ if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0)
+ continue;
+ int tid = atoi(entry.d_name);
+ if (tid == current_tid)
+ continue;
+ syscall(__NR_tkill, tid, SIGUSR1);
+
+ // It is workaround code
+ // Delete Me, If does not crashed on Note4
+ // I don't know why crashed in Kernel with below log
+ // unhandled level 2 translation fault (11) at 0x00000080, esr 0x92000006
+ LOGGER(DEBUG) << "Send signal " << tid;
+ }
+ closedir(dir);
+ }
+ signal(SIGUSR1, oldhandler);
+}
+
+} // namespace
+
+
+PreLauncher::PreLauncher() {
+ ecore_init();
+}
+
+PreLauncher::~PreLauncher() {
+ ecore_shutdown();
+}
+
+void PreLauncher::StartMainLoop() {
+ ecore_main_loop_begin();
+}
+
+void PreLauncher::StopMainLoop() {
+ ecore_main_loop_quit();
+}
+
+void PreLauncher::Watch(int fd, std::function<void(int)> readable) {
+ auto callback = [](void *user_data, Ecore_Fd_Handler *fd_handler) {
+ PreLauncher* launcher = static_cast<PreLauncher*>(user_data);
+ if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) {
+ int fd = ecore_main_fd_handler_fd_get(fd_handler);
+ auto handler = launcher->handlers_[fd_handler];
+ if (handler)
+ handler(fd);
+ }
+ return ECORE_CALLBACK_RENEW;
+ };
+ Ecore_Fd_Handler* handler =
+ ecore_main_fd_handler_add(fd,
+ static_cast<Ecore_Fd_Handler_Flags>(ECORE_FD_READ),
+ callback, this, NULL, NULL);
+ handlers_[handler] = readable;
+ fd_map_[fd] = handler;
+}
+void PreLauncher::Unwatch(int fd) {
+ auto found = fd_map_.find(fd);
+ if (found == fd_map_.end())
+ return;
+ auto handle = found->second;
+ ecore_main_fd_handler_del(handle);
+ fd_map_.erase(found);
+ handlers_.erase(handle);
+}
+
+
+int PreLauncher::Prelaunch(int argc, char* argv[],
+ Preload preload, DidStart didstart, RealMain realmain) {
+ std::unique_ptr<PreLauncher> launcher(new PreLauncher());
+ launcher->preload_ = preload;
+ launcher->didstart_ = didstart;
+ launcher->realmain_ = realmain;
+
+ auto create = [](bundle* extra, int type, void *user_data) {
+ PreLauncher* launcher = static_cast<PreLauncher*>(user_data);
+ launcher->preload_();
+ };
+
+ auto launch = [](int argc, char **argv, const char *app_path,
+ const char *appid, const char *pkgid,
+ const char *pkg_type, void *user_data) {
+ PreLauncher* launcher = static_cast<PreLauncher*>(user_data);
+ ChangePrivilegeForThreads(appid);
+ launcher->didstart_(app_path);
+ return 0;
+ };
+
+ auto terminate = [](int argc, char **argv, void *user_data) {
+ PreLauncher* launcher = static_cast<PreLauncher*>(user_data);
+ return launcher->realmain_(argc, argv);
+ };
+
+ auto start_loop = [](void *user_data) {
+ PreLauncher* launcher = static_cast<PreLauncher*>(user_data);
+ launcher->StartMainLoop();
+ };
+ auto stop_loop = [](void *user_data) {
+ PreLauncher* launcher = static_cast<PreLauncher*>(user_data);
+ launcher->StopMainLoop();
+ };
+ auto add_fd = [](void *user_data, int fd, loader_receiver_cb receiver) {
+ PreLauncher* launcher = static_cast<PreLauncher*>(user_data);
+ launcher->Watch(fd, receiver);
+ };
+ auto remove_fd = [](void *user_data, int fd) {
+ PreLauncher* launcher = static_cast<PreLauncher*>(user_data);
+ launcher->Unwatch(fd);
+ };
+
+ loader_lifecycle_callback_s callbacks = {
+ create,
+ launch,
+ terminate
+ };
+
+ loader_adapter_s loop_methods = {
+ start_loop,
+ stop_loop,
+ add_fd,
+ remove_fd
+ };
+
+ return launchpad_loader_main(argc, argv,
+ &callbacks,
+ &loop_methods,
+ launcher.get());
+}
+
+} // namespace runtime
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <Ecore.h>
+
+#include <string>
+#include <functional>
+#include <map>
+
+namespace runtime {
+
+class PreLauncher {
+ public:
+ using Preload = std::function<void(void)>;
+ using DidStart = std::function<void(const std::string& app_path)>;
+ using RealMain = std::function<int(int, char**)>;
+ static int Prelaunch(int argc, char* argv[], Preload, DidStart, RealMain);
+
+ PreLauncher();
+ ~PreLauncher();
+
+ private:
+ void StartMainLoop();
+ void StopMainLoop();
+
+ void Watch(int fd, std::function<void(int)> readable);
+ void Unwatch(int fd);
+
+ Preload preload_;
+ DidStart didstart_;
+ RealMain realmain_;
+
+ std::map<Ecore_Fd_Handler*, std::function<void(int)> > handlers_;
+ std::map<int, Ecore_Fd_Handler*> fd_map_;
+};
+
+} // namespace runtime
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "runtime/browser/preload_manager.h"
+
+#include <Elementary.h>
+#include <ewk_chromium.h>
+#include <stdio.h>
+
+#include "runtime/browser/native_app_window.h"
+#include "common/logger.h"
+
+#ifndef INJECTED_BUNDLE_PATH
+#error INJECTED_BUNDLE_PATH is not set.
+#endif
+
+
+namespace runtime {
+
+
+PreloadManager* PreloadManager::GetInstance() {
+ static PreloadManager instance;
+ return &instance;
+}
+
+PreloadManager::PreloadManager() {
+}
+
+void PreloadManager::CreateCacheComponet() {
+ // It was not used. just to fork zygote process
+ auto context =
+ ewk_context_new_with_injected_bundle_path(INJECTED_BUNDLE_PATH);
+ context = context; // To prevent build warning
+ cached_window_.reset(new NativeAppWindow());
+ cached_window_->Initialize();
+}
+
+NativeWindow* PreloadManager::GetCachedNativeWindow() {
+ return cached_window_ ? cached_window_.release() : nullptr;
+}
+
+} // namespace runtime
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+#ifndef XWALK_RUNTIME_BROWSER_PRELOAD_MANAGER_H_
+#define XWALK_RUNTIME_BROWSER_PRELOAD_MANAGER_H_
+
+#include <memory>
+
+
+namespace runtime {
+class NativeWindow;
+class PreloadManager {
+ public:
+ static PreloadManager* GetInstance();
+ void CreateCacheComponet();
+ NativeWindow* GetCachedNativeWindow();
+ private:
+ PreloadManager();
+ std::unique_ptr<NativeWindow> cached_window_;
+};
+
+} // namespace runtime
+
+#endif // XWALK_RUNTIME_BROWSER_PRELOAD_MANAGER_H_
#include "common/profiler.h"
#include "runtime/browser/native_app_window.h"
#include "runtime/common/constants.h"
+#include "runtime/browser/preload_manager.h"
namespace runtime {
static NativeWindow* CreateNativeWindow() {
SCOPE_PROFILE();
// TODO(wy80.choi) : consider other type of native window.
- NativeWindow* window = new NativeAppWindow();
+ auto cached = PreloadManager::GetInstance()->GetCachedNativeWindow();
+ NativeWindow* window = cached != nullptr ? cached : new NativeAppWindow();
window->Initialize();
return window;
}
low_memory,
this);
STEP_PROFILE_START("ui_app_main -> OnCreate");
+
return ui_app_main(argc, argv, &ops, this);
}
#include <ewk_chromium.h>
+#include <Elementary.h>
+
#include "common/command_line.h"
#include "common/logger.h"
#include "common/profiler.h"
#include "runtime/browser/runtime.h"
+#include "runtime/browser/prelauncher.h"
+#include "runtime/browser/preload_manager.h"
-int main(int argc, char* argv[]) {
+bool g_prelaunch = false;
+
+int real_main(int argc, char* argv[]) {
STEP_PROFILE_START("Start -> Launch Completed");
STEP_PROFILE_START("Start -> OnCreate");
// Parse commandline.
// Default behavior, run as runtime.
LOGGER(INFO) << "Runtime process has been created.";
- ewk_init();
- char* chromium_arg_options[] = {
- argv[0],
- const_cast<char*>("--no-sandbox"),
- const_cast<char*>("--enable-file-cookies"),
- const_cast<char*>("--allow-file-access-from-files"),
- const_cast<char*>("--allow-universal-access-from-files")
- };
- const int chromium_arg_cnt =
- sizeof(chromium_arg_options) / sizeof(chromium_arg_options[0]);
- ewk_set_arguments(chromium_arg_cnt, chromium_arg_options);
+ if (!g_prelaunch) {
+ ewk_init();
+ char* chromium_arg_options[] = {
+ argv[0],
+ const_cast<char*>("--no-sandbox"),
+ const_cast<char*>("--enable-file-cookies"),
+ const_cast<char*>("--allow-file-access-from-files"),
+ const_cast<char*>("--allow-universal-access-from-files")
+ };
+ const int chromium_arg_cnt =
+ sizeof(chromium_arg_options) / sizeof(chromium_arg_options[0]);
+ ewk_set_arguments(chromium_arg_cnt, chromium_arg_options);
+ }
int ret = 0;
// Runtime's destructor should be called before ewk_shutdown()
return EXIT_SUCCESS;
}
+
+int main(int argc, char* argv[]) {
+ if (strcmp(argv[0], "/usr/bin/wrt-loader") == 0) {
+ elm_init(argc, argv);
+ auto preload = [argv](void) {
+ g_prelaunch = true;
+ ewk_init();
+ char* chromium_arg_options[] = {
+ argv[0],
+ const_cast<char*>("--no-sandbox"),
+ const_cast<char*>("--enable-file-cookies"),
+ const_cast<char*>("--allow-file-access-from-files"),
+ const_cast<char*>("--allow-universal-access-from-files")
+ };
+ const int chromium_arg_cnt =
+ sizeof(chromium_arg_options) / sizeof(chromium_arg_options[0]);
+ ewk_set_arguments(chromium_arg_cnt, chromium_arg_options);
+ runtime::PreloadManager::GetInstance()->CreateCacheComponet();
+ };
+ auto did_launch = [](const std::string& app_path) {
+ };
+ auto prelaunch = runtime::PreLauncher::Prelaunch;
+ return prelaunch(argc, argv, preload, did_launch, real_main);
+ } else {
+ return real_main(argc, argv);
+ }
+}
}
void WebApplication::Launch(std::unique_ptr<common::AppControl> appcontrol) {
+ // send widget info to injected bundle
+ ewk_context_tizen_app_id_set(ewk_context_, appid_.c_str());
+
// Setup View
WebView* view = new WebView(window_, ewk_context_);
SetupWebView(view);
- // send widget info to injected bundle
- ewk_context_tizen_app_id_set(ewk_context_, appid_.c_str());
-
std::unique_ptr<common::ResourceManager::Resource> res =
resource_manager_->GetStartResource(appcontrol.get());
view->SetDefaultEncoding(res->encoding());
// in Wearable, webkit can render contents before show window
// but Mobile, webkit can't render contents before show window
window_->Show();
+ window_->Active();
launched_ = true;
}
#include <ewk_chromium.h>
#include <unistd.h>
#include <v8.h>
+#include <dlfcn.h>
#include <memory>
#include <string>
#include "extensions/renderer/xwalk_module_system.h"
namespace runtime {
+
+static const char* kPreloadLibs[] = {
+ "/usr/lib/tizen-extensions-crosswalk/libtizen.so",
+ "/usr/lib/tizen-extensions-crosswalk/libtizen_common.so",
+ "/usr/lib/tizen-extensions-crosswalk/libtizen_application.so",
+ "/usr/lib/tizen-extensions-crosswalk/libtizen_utils.so",
+ NULL
+};
+
+static void PreloadLibrary() {
+ for (int i = 0; kPreloadLibs[i]; i++) {
+ LOGGER(DEBUG) << "Preload libs : " << kPreloadLibs[i];
+ void* handle = dlopen(kPreloadLibs[i], RTLD_NOW|RTLD_GLOBAL);
+ if (handle == nullptr) {
+ LOGGER(DEBUG) << "Fail to load libs : " << dlerror();
+ }
+ }
+}
+
class BundleGlobalData {
- public :
+ public:
static BundleGlobalData* GetInstance() {
static BundleGlobalData instance;
return &instance;
}
+ void PreInitialize() {
+ if (preInitialized)
+ return;
+ preInitialized = true;
+ locale_manager_.reset(new common::LocaleManager);
+ }
void Initialize(const std::string& app_id) {
+ PreInitialize();
app_data_.reset(new common::ApplicationData(app_id));
app_data_->LoadManifestData();
- locale_manager_.reset(new common::LocaleManager);
+ // PreInitialized locale_manager_.reset(new common::LocaleManager);
locale_manager_->EnableAutoUpdate(true);
if (app_data_->widget_info() != NULL &&
!app_data_->widget_info()->default_locale().empty()) {
}
private:
- BundleGlobalData() {}
+ BundleGlobalData() : preInitialized(false) {}
~BundleGlobalData() {}
std::unique_ptr<common::ResourceManager> resource_manager_;
std::unique_ptr<common::LocaleManager> locale_manager_;
std::unique_ptr<common::ApplicationData> app_data_;
+ bool preInitialized;
};
+
} // namespace runtime
extern "C" void DynamicSetWidgetInfo(const char* tizen_id) {
LOGGER(DEBUG) << "InjectedBundle::DynamicSetWidgetInfo !!" << tizen_id;
ecore_init();
runtime::BundleGlobalData::GetInstance()->Initialize(tizen_id);
-
- STEP_PROFILE_START("Initialize XWalkExtensionRendererController");
- extensions::XWalkExtensionRendererController& controller =
- extensions::XWalkExtensionRendererController::GetInstance();
- controller.InitializeExtensions();
- STEP_PROFILE_END("Initialize XWalkExtensionRendererController");
}
extern "C" void DynamicPluginStartSession(const char* tizen_id,
}
extern "C" void DynamicPreloading() {
- // LOGGER(DEBUG) << "InjectedBundle::DynamicPreloading !!";
+ LOGGER(DEBUG) << "InjectedBundle::DynamicPreloading !!";
+ runtime::PreloadLibrary();
+ runtime::BundleGlobalData::GetInstance()->PreInitialize();
+
+ STEP_PROFILE_START("Initialize XWalkExtensionRendererController");
+ auto& controller = extensions::XWalkExtensionRendererController::GetInstance();
+ controller.InitializeExtensions();
+ STEP_PROFILE_END("Initialize XWalkExtensionRendererController");
}
'browser/vibration_manager.cc',
'browser/notification_manager.h',
'browser/notification_manager.cc',
+ 'browser/prelauncher.h',
+ 'browser/prelauncher.cc',
+ 'browser/preload_manager.h',
+ 'browser/preload_manager.cc',
],
'variables': {
'packages': [
'manifest-parser',
'wgt-manifest-handlers',
'notification',
+ 'launchpad',
],
},
}, # end of target 'xwalk_runtime'