From 65695065735f30bffc4dd83f8d9d849dd1d8fc5d Mon Sep 17 00:00:00 2001 From: Taejeong Lee Date: Fri, 22 Mar 2013 19:31:45 +0900 Subject: [PATCH] [Release] wrt_0.8.166 for tizen_2.1 branch Change-Id: I93c5298c1fecbabbe2213627ca385f0c6f9efffe --- CMakeLists.txt | 5 +- debian/changelog | 9 + packaging/wrt.spec | 5 +- src/api_new/ewk_context_manager.cpp | 3 + src/view/webkit/bundles/wrt-wk2-bundle.cpp | 34 ++ src/view/webkit/view_logic.cpp | 46 +- src/wrt-client/CMakeLists.txt | 2 + src/wrt-client/window_data.cpp | 11 +- src/wrt-client/window_data.h | 1 + src/wrt-client/wrt-client.cpp | 185 ++++++-- src/wrt-launchpad-daemon/CMakeLists.txt | 1 + .../{launchpad_src => include}/access_control.h | 5 + .../{launchpad_src => include}/config.h | 4 + .../{launchpad_src => include}/gl.h | 7 +- src/wrt-launchpad-daemon/include/launchpad_util.h | 411 ++++++++++++++++ src/wrt-launchpad-daemon/include/menu_db_util.h | 36 +- src/wrt-launchpad-daemon/include/process_pool.h | 44 ++ src/wrt-launchpad-daemon/launchpad_src/launchpad.c | 528 ++++++++++----------- .../legacy/preload_list_wrt.txt | 4 +- src/wrt-launchpad-daemon/src/app_sock.c | 5 +- src/wrt-launchpad-daemon/src/process_pool.c | 272 +++++++++++ wrt_env.sh | 2 + 22 files changed, 1264 insertions(+), 356 deletions(-) mode change 100755 => 100644 src/view/webkit/view_logic.cpp rename src/wrt-launchpad-daemon/{launchpad_src => include}/access_control.h (93%) rename src/wrt-launchpad-daemon/{launchpad_src => include}/config.h (90%) rename src/wrt-launchpad-daemon/{launchpad_src => include}/gl.h (94%) create mode 100644 src/wrt-launchpad-daemon/include/launchpad_util.h create mode 100644 src/wrt-launchpad-daemon/include/process_pool.h create mode 100644 src/wrt-launchpad-daemon/src/process_pool.c create mode 100644 wrt_env.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 2350e23..993f380 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,7 @@ ENDIF(NOT CMAKE_BUILD_TYPE) OPTION(DPL_LOG "DPL logs status" ON) OPTION(WITH_TESTS "Build tests" OFF) #enable csp policy support -OPTION(CSP_SUPPORT "Support for csp policy" ON) +OPTION(CSP_SUPPORT "Support for csp policy" OFF) IF(CSP_SUPPORT) ADD_DEFINITIONS("-DCSP_ENABLED") ENDIF(CSP_SUPPORT) @@ -232,6 +232,9 @@ ADD_CUSTOM_TARGET(generic_popup_horizontal ALL DEPENDS INSTALL(FILES ${PROJECT_SOURCE_DIR}/data/generic_popup_horizontal.edj DESTINATION share/edje/ace/ ) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/wrt_env.sh + DESTINATION /etc/profile.d/ + ) ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(po) diff --git a/debian/changelog b/debian/changelog index dad8a95..b553fe6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +wrt (0.8.16) unstable; urgency=low + + * WRT Process Pool Model + * Source clean up (case of launch browser) + * Changed order of setting CSP policy + * Disable CSP + + -- Tae-Jeong Lee Fri, 22 Mar 2013 19:21:40 +0900 + wrt (0.8.165) unstable; urgency=low * JS Global Context PluginModule starting and stoping bug fix diff --git a/packaging/wrt.spec b/packaging/wrt.spec index 8e8034a..0faba51 100644 --- a/packaging/wrt.spec +++ b/packaging/wrt.spec @@ -1,7 +1,7 @@ -#git:framework/web/wrt wrt_0.8.165 +#git:framework/web/wrt wrt_0.8.166 Name: wrt Summary: web runtime -Version: 0.8.165 +Version: 0.8.166 Release: 1 Group: Development/Libraries License: Apache License, Version 2.0 @@ -163,6 +163,7 @@ systemctl daemon-reload %attr(755,root,root) %{_bindir}/wrt-tests-general /opt/share/widget/tests/general/* %endif +%attr(755,root,root) %{_sysconfdir}/profile.d/wrt_env.sh ## wrt-launchpad-daemon ####################################################### %attr(755,root,root) %{_bindir}/wrt_launchpad_daemon diff --git a/src/api_new/ewk_context_manager.cpp b/src/api_new/ewk_context_manager.cpp index 186173d..7d25150 100755 --- a/src/api_new/ewk_context_manager.cpp +++ b/src/api_new/ewk_context_manager.cpp @@ -125,6 +125,9 @@ bool EwkContextManager::initialize() setAutoFullscreenMode(); setBackgroundSupport(); + // ewk storage_path set + ewk_context_storage_path_reset(m_ewkContext); + m_initialized = true; return true; diff --git a/src/view/webkit/bundles/wrt-wk2-bundle.cpp b/src/view/webkit/bundles/wrt-wk2-bundle.cpp index 8a2bc07..ef9f90e 100644 --- a/src/view/webkit/bundles/wrt-wk2-bundle.cpp +++ b/src/view/webkit/bundles/wrt-wk2-bundle.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +71,10 @@ #include +#include +#include +#include + // URI localization on WebProcess side #include "bundle_uri_handling.h" extern "C" { @@ -94,6 +99,11 @@ const char * const PHP_MIME = "application/x-php"; const char * const VIEWMODE_TYPE_FULLSCREEN = "fullscreen"; const char * const VIEWMODE_TYPE_MAXIMIZED = "maximized"; const std::size_t FILE_BUF_MAX_SIZE = 1024; // bytes +const std::size_t PLAIN_CHUNK_SIZE = 1008; // bytes +const unsigned int UID_ROOT = 0; +const unsigned int DEFAULT_PRIORITY = 0; +const char * const PRIVILEGE_APP_TYPE = "wgt"; + static bool m_initWebApp = false; Tizen::Base::ByteBuffer *DecryptChunkByTrustZone( @@ -412,6 +422,23 @@ void Bundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody) m_widgetTizenId = DPL::FromASCIIString(msgString); WrtDB::WidgetDAOReadOnly dao(m_widgetTizenId); + + // process pool - set app_privilige + if (UID_ROOT == getuid()) + { + using namespace WrtDB::GlobalConfig; + + std::string appPath; + std::string tzAppId = DPL::ToUTF8String(dao.getTzAppId()); + std::string tzPkgId = DPL::ToUTF8String(dao.getTizenPkgId()); + + appPath = appPath + GetUserInstalledWidgetPath() + "/" + + tzPkgId + GetUserWidgetExecPath() + "/" + tzAppId; + + LogDebug("set_app_privilege(" << appPath << ")"); + set_app_privilege(tzPkgId.c_str(), PRIVILEGE_APP_TYPE, appPath.c_str()); + } + /* This type of message is received when widget is restarting * (proably in other situation too). Widget restart can be * called after system language change so language tags have to @@ -797,6 +824,7 @@ WKBundlePagePolicyAction Bundle::pageDecidePolicyForNavigationAction( WKRelease(urlStr); WKRelease(retVal); WKRelease(blockMessage); + return WKBundlePagePolicyActionPassThrough; } // get scheme string @@ -1023,5 +1051,11 @@ void WKBundleInitialize(WKBundleRef bundle, &Bundle::didReceiveMessageCallback }; WKBundleSetClient(bundle, &client); + + // process pool - restore process priority + if (UID_ROOT == getuid()) + { + setpriority(PRIO_PROCESS, 0, DEFAULT_PRIORITY); + } } } diff --git a/src/view/webkit/view_logic.cpp b/src/view/webkit/view_logic.cpp old mode 100755 new mode 100644 index f9a48bf..4c5042e --- a/src/view/webkit/view_logic.cpp +++ b/src/view/webkit/view_logic.cpp @@ -621,27 +621,29 @@ void ViewLogic::prepareEwkView(Evas_Object *wkView) // EWK_ENFORCE_POLICY); //LogInfo("Default policy set"); - DPL::OptionalString policy = m_model->CspPolicy.Get(); + DPL::OptionalString policy = m_model->CspReportOnlyPolicy.Get(); if (!(policy.IsNull())) { - LogDebug("CSP policy present in manifest: " << *policy); + LogDebug("CSP report only policy present in manifest: " << *policy); ewk_view_content_security_policy_set( - wkView, DPL::ToUTF8String(*policy).c_str(), EWK_ENFORCE_POLICY); + wkView, DPL::ToUTF8String(*policy).c_str(), EWK_REPORT_ONLY); } else { - LogDebug("Config CSP policy is not present"); + LogDebug("Config CSP report only policy is not present"); } - policy = m_model->CspReportOnlyPolicy.Get(); + policy = m_model->CspPolicy.Get(); + if (!(policy.IsNull())) { - LogDebug("CSP report only policy present in manifest: " << *policy); + LogDebug("CSP policy present in manifest: " << *policy); ewk_view_content_security_policy_set( - wkView, DPL::ToUTF8String(*policy).c_str(), EWK_REPORT_ONLY); + wkView, DPL::ToUTF8String(*policy).c_str(), EWK_ENFORCE_POLICY); } else { - LogDebug("Config CSP report only policy is not present"); + LogDebug("Config CSP policy is not present"); } + LogInfo("CSP set."); #endif @@ -834,23 +836,6 @@ void ViewLogic::loadFinishedCallback( return; } - // check if this loading is for blocked url - if (This->m_blockedUri == url) { - if (ewk_view_back_possible(This->m_currentEwkView)) { - // go back to previous page - LogDebug("go to previous page"); - ewk_view_back(This->m_currentEwkView); - } else { - // stop current page - LogDebug("remove current page"); - ewk_view_stop(This->m_currentEwkView); - This->m_closedEwkView = This->m_currentEwkView; - ecore_idler_add(windowCloseIdlerCallback, This); - } - This->m_blockedUri = std::string(); - return; - } - DPL::OptionalString jsOptionalString = ViewModule::PasswordSupport::jsForAutoFillData(url); if (jsOptionalString.IsNull()) { @@ -1036,6 +1021,17 @@ void ViewLogic::policyNavigationDecideCallback( Ewk_Policy_Decision* policyDecision = static_cast(eventInfo); + // handle blocked url + const char* url = ewk_policy_decision_url_get(policyDecision); + if (url && strlen(url) != 0) { + if (This->m_blockedUri == url) { + LogDebug("Blocked url = " << url); + This->m_blockedUri = std::string(); + ewk_policy_decision_ignore(policyDecision); + return; + } + } + if (This->m_schemeSupport->filterURIByScheme(policyDecision, false, This->m_model, diff --git a/src/wrt-client/CMakeLists.txt b/src/wrt-client/CMakeLists.txt index 16eecce..eaec1e7 100644 --- a/src/wrt-client/CMakeLists.txt +++ b/src/wrt-client/CMakeLists.txt @@ -19,6 +19,7 @@ SET(WRT_CLIENT_SRCS ${PROJECT_SOURCE_DIR}/src/wrt-client/window_data.cpp ${PROJECT_SOURCE_DIR}/src/wrt-client/splash_screen_support.cpp ${PROJECT_SOURCE_DIR}/src/wrt-client/wrt-client.cpp + ${PROJECT_SOURCE_DIR}/src/wrt-launchpad-daemon/src/process_pool.c ) PKG_CHECK_MODULES(CLIENT_DEP @@ -31,6 +32,7 @@ PKG_CHECK_MODULES(CLIENT_DEP INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/wrt-client ${PROJECT_SOURCE_DIR}/src/api_new + ${PROJECT_SOURCE_DIR}/src/wrt-launchpad-daemon/include ${CLIENT_DEP_INCLUDE_DIRS} ) diff --git a/src/wrt-client/window_data.cpp b/src/wrt-client/window_data.cpp index dd64049..a4a2ead 100644 --- a/src/wrt-client/window_data.cpp +++ b/src/wrt-client/window_data.cpp @@ -46,7 +46,8 @@ const std::string DESKTOP_PROFILE("desktop"); WindowData::WindowData(unsigned long pid, bool manualInit) : m_win(NULL), - m_naviBackButton(NULL) + m_naviBackButton(NULL), + m_initialized(false) { m_win = createWindow(pid); @@ -65,6 +66,12 @@ void WindowData::init() { Assert(m_win != NULL && "m_win is null"); + if (m_initialized == true) + { + LogInfo("Already initilized"); + return; + } + // import button theme elm_theme_overlay_add(NULL, THEME_EDJ_PATH); @@ -76,6 +83,8 @@ void WindowData::init() evas_object_show(m_navigation); m_user_layout = createUserLayout(m_navigation); evas_object_show(m_user_layout); + + m_initialized = true; } void WindowData::setEvasObjectForLayout(Evas_Object* evas_object) diff --git a/src/wrt-client/window_data.h b/src/wrt-client/window_data.h index 8c656e9..8411ac6 100644 --- a/src/wrt-client/window_data.h +++ b/src/wrt-client/window_data.h @@ -111,6 +111,7 @@ class WindowData : private DPL::Noncopyable Evas_Object* m_naviBackButton; Evas_Object* m_floatBackButton; bool m_fullscreen; + bool m_initialized; Evas_Object* createWindow(unsigned long pid); Evas_Object* createPlatformLayout(Evas_Object* parent); diff --git a/src/wrt-client/wrt-client.cpp b/src/wrt-client/wrt-client.cpp index 3ea7ea7..d0c7d8f 100644 --- a/src/wrt-client/wrt-client.cpp +++ b/src/wrt-client/wrt-client.cpp @@ -14,6 +14,9 @@ * limitations under the License. */ #include "wrt-client.h" +#include +#include +#include #include #include #include @@ -31,6 +34,10 @@ #include #include "webkit/bundles/plugin_module_support.h" +#include "process_pool.h" +#include "menu_db_util.h" +#include "launchpad_util.h" + //W3C PACKAGING enviroment variable name #define W3C_DEBUG_ENV_VARIABLE "DEBUG_LOAD_FINISH" @@ -41,7 +48,12 @@ const std::string VIEWMODE_TYPE_MAXIMIZED = "maximized"; char const* const ELM_SWALLOW_CONTENT = "elm.swallow.content"; const char* const BUNDLE_PATH = "/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so"; -static Ewk_Context* s_ewk_context = NULL; +// process pool +const char* const DUMMY_PROCESS_PATH = "/usr/bin/wrt_launchpad_daemon_candidate"; +static Ewk_Context* s_preparedEwkContext = NULL; +static WindowData* s_preparedWindowData = NULL; +static int app_argc = 0; +static char** app_argv = NULL; WrtClient::WrtClient(int argc, char **argv) : Application(argc, argv, "wrt-client", false), @@ -475,8 +487,15 @@ void WrtClient::launchStep() // languageChangedCallback, this); ADD_PROFILING_POINT("CreateWindow", "start"); - m_windowData.reset(new WindowData(static_cast(getpid()), - true)); + if (s_preparedWindowData == NULL) + { + m_windowData.reset(new WindowData(static_cast(getpid()), true)); + } + else + { + m_windowData.reset(s_preparedWindowData); + s_preparedWindowData = NULL; + } ADD_PROFILING_POINT("CreateWindow", "stop"); WRT::UserDelegatesPtr cbs(new WRT::UserDelegates); @@ -493,7 +512,7 @@ void WrtClient::launchStep() ADD_PROFILING_POINT("Create splash screen", "stop"); DPL::OptionalString startUrl = W3CFileLocalization::getStartFile(m_dao); if (!m_widget->PrepareView(DPL::ToUTF8String(*startUrl), - m_windowData->m_win, s_ewk_context)) + m_windowData->m_win, s_preparedEwkContext)) { DPL::Event::ControllerEventHandler::PostEvent( NextStepEvent()); @@ -540,7 +559,9 @@ void WrtClient::launchStep() m_widget->SetUserDelegates(cbs); m_widget->Show(); + m_windowData->emitSignalForUserLayout(EDJE_SHOW_BACKWARD_SIGNAL, ""); + ADD_PROFILING_POINT("launchStep", "stop"); } @@ -656,7 +677,7 @@ void WrtClient::shutdownStep() m_widgetState = WidgetState_Stopped; m_widget->Hide(); m_widget.reset(); - ewk_context_delete(s_ewk_context); + ewk_context_delete(s_preparedEwkContext); WRT::CoreModuleSingleton::Instance().Terminate(); } if (m_initialized) { @@ -700,9 +721,82 @@ void WrtClient::Quit() DPL::Application::Quit(); } +static Eina_Bool proces_pool_fd_handler(void* /*data*/, Ecore_Fd_Handler *handler) +{ + int fd = ecore_main_fd_handler_fd_get(handler); + + if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR)) + { + LogDebug("ECORE_FD_ERROR"); + close(fd); + exit(-1); + return ECORE_CALLBACK_CANCEL; + } + + if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ)) + { + LogDebug("ECORE_FD_READ"); + { + app_pkt_t* pkt = (app_pkt_t*) malloc(sizeof(char) * AUL_SOCK_MAXBUFF); + memset(pkt, 0, AUL_SOCK_MAXBUFF); + + int recv_ret = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0); + + close(fd); + + if (recv_ret == -1) + { + LogDebug("recv error!"); + exit(-1); + } + LogDebug("recv_ret : " << recv_ret << ", pkt->len : " << pkt->len); + + ecore_main_fd_handler_del(handler); + + __wrt_launchpad_main_loop(pkt, app_argv[0], &app_argc, &app_argv); + + free(pkt); + } + + ecore_main_loop_quit(); + return ECORE_CALLBACK_CANCEL; + } + + return ECORE_CALLBACK_CANCEL; +} + + +void set_env() +{ + // set evas backend type + if (!getenv("ELM_ENGINE")) + { + if (!setenv("ELM_ENGINE", "gl", 1)) + { + LogDebug("Enable backend"); + } + } + else + { + LogDebug("ELM_ENGINE : " << getenv("ELM_ENGINE")); + } + +#ifndef TIZEN_PUBLIC + setenv("COREGL_FASTPATH", "1", 1); +#endif + setenv("CAIRO_GL_COMPOSITOR", "msaa", 1); + setenv("CAIRO_GL_LAZY_FLUSHING", "yes", 1); + setenv("ELM_IMAGE_CACHE", "0", 1); +} + + int main(int argc, char *argv[]) { + // process pool - store arg's value + app_argc = argc; + app_argv = argv; + UNHANDLED_EXCEPTION_HANDLER_BEGIN { ADD_PROFILING_POINT("main-entered", "point"); @@ -710,37 +804,68 @@ int main(int argc, // Set log tagging DPL::Log::LogSystemSingleton::Instance().SetTag("WRT"); - // set evas backend type - if (!getenv("ELM_ENGINE")) { - if (!setenv("ELM_ENGINE", "gl", 1)) { - LogDebug("Enable backend"); - } - } else { - LogDebug("ELM_ENGINE : " << getenv("ELM_ENGINE")); - } - - #ifndef TIZEN_PUBLIC - setenv("COREGL_FASTPATH", "1", 1); - #endif - setenv("CAIRO_GL_COMPOSITOR", "msaa", 1); - setenv("CAIRO_GL_LAZY_FLUSHING", "yes", 1); - setenv("ELM_IMAGE_CACHE", "0", 1); + // Set environment variables + set_env(); - // This code is to fork a web process without exec. - std::string tizenId = WrtClient::getTizenIdFromArgument(argc, argv); + if (argc > 1 && argv[1] != NULL && !strcmp(argv[1], "-d")) + { + LogInfo("Entered dummy process mode"); + sprintf(argv[0], "%s ", + DUMMY_PROCESS_PATH); - if (!tizenId.empty()) { - LogDebug("Launching by fork mode"); - // Language env setup + LogInfo("Prepare ewk_context"); appcore_set_i18n("wrt-client", NULL); ewk_init(); ewk_set_arguments(argc, argv); setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1); - s_ewk_context = ewk_context_new_with_injected_bundle_path( - BUNDLE_PATH); + s_preparedEwkContext = ewk_context_new_with_injected_bundle_path(BUNDLE_PATH); + + int client_fd = __connect_process_pool_server(); + + if (client_fd == -1) + { + LogInfo("Connecting process_pool_server was failed!"); + exit(-1); + } + + LogInfo("Prepare window_data"); + LogInfo("elm_init()"); + elm_init(argc, argv); + LogInfo("WindowData()"); + s_preparedWindowData = new WindowData(static_cast(getpid())); - // plugin init - PluginModuleSupport::init(s_ewk_context, tizenId); + ecore_main_fd_handler_add(client_fd, ECORE_FD_READ, proces_pool_fd_handler, NULL, NULL, NULL); + ecore_main_fd_handler_add(client_fd, ECORE_FD_ERROR, proces_pool_fd_handler, NULL, NULL, NULL); + + setpriority(PRIO_PROCESS, 0, 0); + + LogDebug("ecore_main_loop_begin()"); + ecore_main_loop_begin(); + LogDebug("ecore_main_loop_begin()_end"); + + std::string tizenId = WrtClient::getTizenIdFromArgument(argc, argv); + PluginModuleSupport::init(s_preparedEwkContext, tizenId); + + } + else + { + // This code is to fork a web process without exec. + std::string tizenId = WrtClient::getTizenIdFromArgument(argc, argv); + + if (!tizenId.empty()) + { + LogDebug("Launching by fork mode"); + // Language env setup + appcore_set_i18n("wrt-client", NULL); + ewk_init(); + ewk_set_arguments(argc, argv); + setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1); + s_preparedEwkContext = ewk_context_new_with_injected_bundle_path( + BUNDLE_PATH); + + // plugin init + PluginModuleSupport::init(s_preparedEwkContext, tizenId); + } } // Output on stdout will be flushed after every newline character, @@ -751,7 +876,7 @@ int main(int argc, // the output may not be flushed). setlinebuf(stdout); - WrtClient app(argc, argv); + WrtClient app(app_argc, app_argv); ADD_PROFILING_POINT("Before appExec", "point"); int ret = app.Exec(); diff --git a/src/wrt-launchpad-daemon/CMakeLists.txt b/src/wrt-launchpad-daemon/CMakeLists.txt index 33aa5b6..9d78b15 100644 --- a/src/wrt-launchpad-daemon/CMakeLists.txt +++ b/src/wrt-launchpad-daemon/CMakeLists.txt @@ -51,6 +51,7 @@ ADD_EXECUTABLE( ${WRT_LAUNCH_PAD_NAME} src/simple_util.c launchpad_src/launchpad.c launchpad_src/util_x.c + src/process_pool.c ) #link libraries diff --git a/src/wrt-launchpad-daemon/launchpad_src/access_control.h b/src/wrt-launchpad-daemon/include/access_control.h similarity index 93% rename from src/wrt-launchpad-daemon/launchpad_src/access_control.h rename to src/wrt-launchpad-daemon/include/access_control.h index 52045d4..25d849b 100644 --- a/src/wrt-launchpad-daemon/launchpad_src/access_control.h +++ b/src/wrt-launchpad-daemon/include/access_control.h @@ -14,6 +14,9 @@ * limitations under the License. */ +#ifndef __ACCESS_CONTROL_H_ +#define __ACCESS_CONTROL_H_ + #ifdef DAC_ACTIVATE #include @@ -37,3 +40,5 @@ static inline int __set_access(const char* pkg_name, #endif +#endif //__ACCESS_CONTROL_H_ + diff --git a/src/wrt-launchpad-daemon/launchpad_src/config.h b/src/wrt-launchpad-daemon/include/config.h similarity index 90% rename from src/wrt-launchpad-daemon/launchpad_src/config.h rename to src/wrt-launchpad-daemon/include/config.h index a177ff5..dd2b4c5 100644 --- a/src/wrt-launchpad-daemon/launchpad_src/config.h +++ b/src/wrt-launchpad-daemon/include/config.h @@ -14,6 +14,9 @@ * limitations under the License. */ +#ifndef __LAUNCHPAD_CONFIG_H_ +#define __LAUNCHPAD_CONFIG_H_ + #define LAUNCHPAD_LOG #define DAC_ACTIVATE #define PRELOAD_ACTIVATE @@ -22,3 +25,4 @@ /*#define HEAPDGB_ACTIVATE*/ /*#define PERF_ACTIVATE*/ +#endif // __LAUNCHPAD_CONFIG_H_ \ No newline at end of file diff --git a/src/wrt-launchpad-daemon/launchpad_src/gl.h b/src/wrt-launchpad-daemon/include/gl.h similarity index 94% rename from src/wrt-launchpad-daemon/launchpad_src/gl.h rename to src/wrt-launchpad-daemon/include/gl.h index 47ac8e0..0c26111 100644 --- a/src/wrt-launchpad-daemon/launchpad_src/gl.h +++ b/src/wrt-launchpad-daemon/include/gl.h @@ -13,14 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef __GL_H_ +#define __GL_H_ #ifdef GL_ACTIVATE - #define USE_ENGINE(engine) setenv("ELM_ENGINE", engine, 1); - #else - #define USE_ENGINE(engine) - #endif +#endif //__GL_H_ \ No newline at end of file diff --git a/src/wrt-launchpad-daemon/include/launchpad_util.h b/src/wrt-launchpad-daemon/include/launchpad_util.h new file mode 100644 index 0000000..8d61c46 --- /dev/null +++ b/src/wrt-launchpad-daemon/include/launchpad_util.h @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2013 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. + */ +/** + * @file launchpad_util.h + * @author Tae-Jeong Lee (taejeong.lee@samsung.com) + * @version 0.1 + * @brief Api library to support launchpad operation. + */ + +#ifndef __LAUNCHPAD_UTIL_H_ +#define __LAUNCHPAD_UTIL_H_ + +#include +#include +#include +#include + +#include "config.h" +#include "gl.h" +#include "app_sock.h" +#include "menu_db_util.h" +#include "simple_util.h" +#include "access_control.h" + +#define _static_ static inline +#define WRT_AUL_PR_NAME 16 +#define PKG_ID_LENGTH 11 +#define SDK_CODE_COVERAGE "CODE_COVERAGE" +#define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS" +#define PATH_DA_SO "/home/developer/sdk_tools/da/da_probe.so" +#define PATH_APP_ROOT "/opt/usr/apps" +#define PATH_DATA "/data" + +// Prototype +_static_ char** __create_argc_argv(bundle * kb, int *margc); +_static_ void __set_sdk_env(app_info_from_db* menu_info, char* str); +_static_ int __parser(const char *arg, char *out, int out_size); +_static_ void __modify_bundle(bundle * kb, int caller_pid, app_info_from_db * menu_info, int cmd); +_static_ void __set_oom(); +_static_ void __set_env(app_info_from_db * menu_info, bundle * kb); +_static_ int __wrt_prepare_exec(const char *pkg_name, const char *app_path, app_info_from_db * menu_info, bundle * kb); +_static_ void __wrt_launchpad_main_loop(app_pkt_t* pkt, char* out_app_path, int* out_argc, char ***out_argv); + +// Implementation + +_static_ char** __create_argc_argv(bundle * kb, int *margc) +{ + char **argv; + int argc; + + argc = bundle_export_to_argv(kb, &argv); + + *margc = argc; + return argv; +} + +_static_ void __set_sdk_env(app_info_from_db* menu_info, char* str) +{ + char buf[MAX_LOCAL_BUFSZ]; + int ret; + + _D("key : %s / value : %s", AUL_K_SDK, str); + /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/ + /* GCOV_PREFIX contains the prefix to add to the absolute paths in the + *object file. */ + /* Prefix can be absolute, or relative. The default is no prefix. + * */ + /* GCOV_PREFIX_STRIP indicates the how many initial directory names */ + /* to stripoff the hardwired absolute paths. Default value is 0. */ + if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) { + snprintf(buf, + MAX_LOCAL_BUFSZ, + PATH_APP_ROOT "/%s"PATH_DATA, + _get_pkgname(menu_info)); + ret = setenv("GCOV_PREFIX", buf, 1); + _D("GCOV_PREFIX : %d", ret); + ret = setenv("GCOV_PREFIX_STRIP", "4096", 1); + _D("GCOV_PREFIX_STRIP : %d", ret); + } else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0) { + ret = setenv("LD_PRELOAD", PATH_DA_SO, 1); + _D("LD_PRELOAD : %d", ret); + } +} + + +/* + * Parsing original app path to retrieve default bundle + * + * -1 : Invalid sequence + * -2 : Buffer overflow + * + */ +_static_ int __parser(const char *arg, char *out, int out_size) +{ + register int i; + int state = 1; + char *start_out = out; + + if (arg == NULL || out == NULL) { + /* Handles null buffer*/ + return 0; + } + + for (i = 0; out_size > 1; i++) { + switch (state) { + case 1: + switch (arg[i]) { + case ' ': + case '\t': + state = 5; + break; + case '\0': + state = 7; + break; + case '\"': + state = 2; + break; + case '\\': + state = 4; + break; + default: + *out = arg[i]; + out++; + out_size--; + break; + } + break; + case 2: /* escape start*/ + switch (arg[i]) { + case '\0': + state = 6; + break; + case '\"': + state = 1; + break; + default: + *out = arg[i]; + out++; + out_size--; + break; + } + break; + case 4: /* character escape*/ + if (arg[i] == '\0') { + state = 6; + } else { + *out = arg[i]; + out++; + out_size--; + state = 1; + } + break; + case 5: /* token*/ + if (out != start_out) { + *out = '\0'; + out_size--; + return i; + } + i--; + state = 1; + break; + case 6: + return -1; /* error*/ + case 7: /* terminate*/ + *out = '\0'; + out_size--; + return 0; + default: + state = 6; + break; /* error*/ + } + } + + if (out_size == 1) { + *out = '\0'; + } + /* Buffer overflow*/ + return -2; +} + + +_static_ void __modify_bundle(bundle * kb, int caller_pid, + app_info_from_db * menu_info, int cmd) +{ + // warning: unused parameter + caller_pid = caller_pid; + + bundle_del(kb, AUL_K_PKG_NAME); + bundle_del(kb, AUL_K_EXEC); + bundle_del(kb, AUL_K_PACKAGETYPE); + bundle_del(kb, AUL_K_HWACC); + + /* Parse app_path to retrieve default bundle*/ + if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN || cmd == + APP_RESUME) + { + char *ptr; + char exe[MAX_PATH_LEN]; + int flag; + + ptr = _get_original_app_path(menu_info); + + flag = __parser(ptr, exe, sizeof(exe)); + if (flag > 0) { + char key[256]; + char value[256]; + + ptr += flag; + _D("parsing app_path: EXEC - %s\n", exe); + + do { + flag = __parser(ptr, key, sizeof(key)); + if (flag <= 0) { + break; + } + ptr += flag; + + flag = __parser(ptr, value, sizeof(value)); + if (flag < 0) { + break; + } + ptr += flag; + + /*bundle_del(kb, key);*/ + bundle_add(kb, key, value); + } while (flag > 0); + } else if (flag == 0) { + _D("parsing app_path: No arguments\n"); + } else { + _D("parsing app_path: Invalid argument\n"); + } + } +} + + +_static_ void __set_oom() +{ + char buf[MAX_LOCAL_BUFSZ]; + FILE *fp; + + /* we should reset oomadj value as default because child + * inherits from parent oom_adj*/ + snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid()); + fp = fopen(buf, "w"); + if (fp == NULL) { + return; + } + fprintf(fp, "%d", -16); + fclose(fp); +} + +_static_ void __set_env(app_info_from_db * menu_info, bundle * kb) +{ + const char *str; + const char **str_array; + int len; + int i; + + setenv("PKG_NAME", _get_pkgname(menu_info), 1); + + USE_ENGINE("gl") + + str = bundle_get_val(kb, AUL_K_STARTTIME); + if (str != NULL) { + setenv("APP_START_TIME", str, 1); + } + + if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) { + str_array = bundle_get_str_array(kb, AUL_K_SDK, &len); + if (str_array != NULL) { + for (i = 0; i < len; i++) { + _D("index : [%d]", i); + __set_sdk_env(menu_info, (char *)str_array[i]); + } + } + } else { + str = bundle_get_val(kb, AUL_K_SDK); + if (str != NULL) { + __set_sdk_env(menu_info, (char *)str); + } + } + if (menu_info->hwacc != NULL) { + setenv("HWACC", menu_info->hwacc, 1); + } +} + +_static_ int __wrt_prepare_exec(const char *pkg_name, + const char *app_path, app_info_from_db * menu_info, + bundle * kb) +{ + const char *file_name; + char process_name[WRT_AUL_PR_NAME]; + + /* SET PRIVILEGES*/ + char pkg_id[PKG_ID_LENGTH]; + memset(pkg_id, '\0', PKG_ID_LENGTH); + snprintf(pkg_id, PKG_ID_LENGTH, "%s", pkg_name); + + if (__set_access(pkg_id, menu_info->pkg_type, app_path) < 0) { + _D("fail to set privileges - check your package's credential\n"); + return -1; + } + + /* SET PROCESS NAME*/ + if (app_path == NULL) { + _D("app_path should not be NULL - check menu db"); + return -1; + } + file_name = strrchr(app_path, '/') + 1; + if (file_name == NULL) { + _D("can't locate file name to execute"); + return -1; + } + memset(process_name, '\0', WRT_AUL_PR_NAME); + snprintf(process_name, WRT_AUL_PR_NAME, "%s", file_name); + prctl(PR_SET_NAME, process_name); + + /* SET ENVIROMENT*/ + __set_env(menu_info, kb); + + return 0; +} + +_static_ void __wrt_launchpad_main_loop(app_pkt_t* pkt, char* out_app_path, int* out_argc, char ***out_argv) + +{ + bundle *kb = NULL; + app_info_from_db *menu_info = NULL; + + const char *pkg_name = NULL; + const char *app_path = NULL; + struct ucred cr; + + kb = bundle_decode(pkt->data, pkt->len); + if (!kb) { + _E("bundle decode error"); + exit(-1); + } + + pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME); + _D("pkg name : %s", pkg_name); + + menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb); + if (menu_info == NULL) { + _D("such pkg no found"); + exit(-1); + } + + app_path = _get_app_path(menu_info); + + if (app_path == NULL) { + _E("app_path is NULL"); + exit(-1); + } + + if (app_path[0] != '/') { + _E("app_path is not absolute path"); + exit(-1); + } + + __modify_bundle(kb, cr.pid, menu_info, pkt->cmd); + pkg_name = _get_pkgname(menu_info); + _D("pkg name : %s", pkg_name); + + __wrt_prepare_exec(pkg_name, app_path, menu_info, kb); + + if (out_app_path != NULL && out_argc != NULL && out_argv != NULL) + { + int i; + + sprintf(out_app_path, "%s", app_path); + + *out_argv = __create_argc_argv(kb, out_argc); + (*out_argv)[0] = out_app_path; + + for (i = 0; i < *out_argc; i++) + { + _D("input argument %d : %s##", i, (*out_argv)[i]); + } + } + else + { + exit(-1); + } + + +#if 0 // intentional + if (menu_info != NULL) { + _free_app_info_from_db(menu_info); + } + + if (kb != NULL) { + bundle_free(kb); + } +#endif +} + +#endif // __LAUNCHPAD_UTIL_H_ diff --git a/src/wrt-launchpad-daemon/include/menu_db_util.h b/src/wrt-launchpad-daemon/include/menu_db_util.h index 7f8c8c5..c4d5d07 100644 --- a/src/wrt-launchpad-daemon/include/menu_db_util.h +++ b/src/wrt-launchpad-daemon/include/menu_db_util.h @@ -14,6 +14,9 @@ * limitations under the License. */ +#ifndef __MENU_DB_UTIL_H_ +#define __MENU_DB_UTIL_H_ + #include #include #include "simple_util.h" @@ -75,7 +78,7 @@ static inline char *_get_app_path(app_info_from_db *menu_info) free(menu_info->app_path); menu_info->app_path = NULL; } else if (path_len > 0) { - char *tmp_app_path = malloc(sizeof(char) * (path_len + 1)); + char *tmp_app_path = (char *)malloc(sizeof(char) * (path_len + 1)); if (tmp_app_path == NULL) { return NULL; } @@ -122,7 +125,7 @@ static inline app_info_from_db *_get_app_info_from_db_by_pkgname( ail_error_e ret; char *str = NULL; - menu_info = calloc(1, sizeof(app_info_from_db)); + menu_info = (app_info_from_db *)calloc(1, sizeof(app_info_from_db)); if (menu_info == NULL) { return NULL; } @@ -193,7 +196,7 @@ static inline app_info_from_db *_get_app_info_from_db_by_apppath( return NULL; } - menu_info = calloc(1, sizeof(app_info_from_db)); + menu_info = (app_info_from_db *)calloc(1, sizeof(app_info_from_db)); if (menu_info == NULL) { return NULL; } @@ -233,3 +236,30 @@ static inline app_info_from_db *_get_app_info_from_db_by_apppath( return menu_info; } + +static inline app_info_from_db *_get_app_info_from_bundle_by_pkgname( + const char *pkgname, bundle *kb) +{ + app_info_from_db *menu_info; + + menu_info = (app_info_from_db*)calloc(1, sizeof(app_info_from_db)); + if (menu_info == NULL) { + return NULL; + } + + menu_info->pkg_name = strdup(pkgname); + menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC)); + if (menu_info->app_path != NULL) { + menu_info->original_app_path = strdup(menu_info->app_path); + } + menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE)); + menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC)); + + if (!_get_app_path(menu_info)) { + _free_app_info_from_db(menu_info); + return NULL; + } + + return menu_info; +} +#endif //__MENU_DB_UTIL_H_ \ No newline at end of file diff --git a/src/wrt-launchpad-daemon/include/process_pool.h b/src/wrt-launchpad-daemon/include/process_pool.h new file mode 100644 index 0000000..4a1ed38 --- /dev/null +++ b/src/wrt-launchpad-daemon/include/process_pool.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 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. + */ +/** + * @file process_pool.h + * @author Tae-Jeong Lee (taejeong.lee@samsung.com) + * @version 0.1 + * @brief process pool socket api prototypes + */ + +#ifndef __PROCESS_POOL_H_ +#define __PROCESS_POOL_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif //__cplusplus + +#include + +int __create_process_pool_server(); +int __connect_process_pool_server(); +int __accept_dummy_process(int server_fd, int* out_client_fd, int* out_client_pid); +void __refuse_dummy_process(int server_fd); +int __send_pkt_raw_data(int client_fd, app_pkt_t* pkt); + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__PROCESS_POOL_H_ + diff --git a/src/wrt-launchpad-daemon/launchpad_src/launchpad.c b/src/wrt-launchpad-daemon/launchpad_src/launchpad.c index 415519e..1dcab54 100644 --- a/src/wrt-launchpad-daemon/launchpad_src/launchpad.c +++ b/src/wrt-launchpad-daemon/launchpad_src/launchpad.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include "app_sock.h" @@ -53,23 +55,28 @@ #include #include +#include "process_pool.h" +#include "launchpad_util.h" + #define _static_ static inline -#define POLLFD_MAX 1 -#define SQLITE_FLUSH_MAX (1048576) /* (1024*1024) */ -#define AUL_POLL_CNT 15 -#define AUL_PR_NAME 16 -#define PKG_ID_LENGTH 11 -#define PATH_APP_ROOT "/opt/usr/apps" -#define PATH_DATA "/data" -#define SDK_CODE_COVERAGE "CODE_COVERAGE" -#define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS" -#define PATH_DA_SO "/home/developer/sdk_tools/da/da_probe.so" +#define SQLITE_FLUSH_MAX (1048576) /* (1024*1024) */ +#define AUL_POLL_CNT 15 +#define AUL_PR_NAME 16 +#define PKG_ID_LENGTH 11 + +#define EXEC_DUMMY_EXPIRED 5 +#define DIFF(a,b) (((a)>(b))?(a)-(b):(b)-(a)) +#define WRT_CLIENT_PATH "/usr/bin/wrt-client" +#define LOWEST_PRIO 20 +#define DUMMY_NONE 0 static char *launchpad_cmdline; static int initialized = 0; +static int dummy_process_pid = DUMMY_NONE; +static int dummy_process_fd = -1; +static int last_dummy_exec_time = 0; +static int process_pool_disable = 0; -_static_ void __set_oom(); -_static_ void __set_env(app_info_from_db * menu_info, bundle * kb); _static_ int __prepare_exec(const char *pkg_name, const char *app_path, app_info_from_db * menu_info, bundle * kb); @@ -77,9 +84,7 @@ _static_ int __fake_launch_app(int cmd, int pid, bundle * kb); _static_ char **__create_argc_argv(bundle * kb, int *margc); _static_ int __normal_fork_exec(int argc, char **argv); _static_ void __real_launch(const char *app_path, bundle * kb); -static inline int __parser(const char *arg, char *out, int out_size); -_static_ void __modify_bundle(bundle * kb, int caller_pid, - app_info_from_db * menu_info, int cmd); +_static_ int __dummy_launch(int dummy_client_fd, app_pkt_t* pkt); _static_ int __child_raise_win_by_x(int pid, void *priv); _static_ int __raise_win_by_x(int pid); _static_ int __send_to_sigkill(int pid); @@ -87,91 +92,13 @@ _static_ int __term_app(int pid); _static_ int __resume_app(int pid); _static_ void __real_send(int clifd, int ret); _static_ void __send_result_to_caller(int clifd, int ret); -_static_ void __launchpad_main_loop(int main_fd); +_static_ void __launchpad_exec_dummy(int main_fd, int pool_fd, int client_fd); +_static_ void __launchpad_main_loop(int main_fd, int pool_fd); _static_ int __launchpad_pre_init(int argc, char **argv); _static_ int __launchpad_post_init(); extern ail_error_e ail_db_close(void); -_static_ void __set_oom() -{ - char buf[MAX_LOCAL_BUFSZ]; - FILE *fp; - - /* we should reset oomadj value as default because child - * inherits from parent oom_adj*/ - snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid()); - fp = fopen(buf, "w"); - if (fp == NULL) { - return; - } - fprintf(fp, "%d", -16); - fclose(fp); -} - -_static_ void __set_sdk_env(app_info_from_db* menu_info, char* str) -{ - char buf[MAX_LOCAL_BUFSZ]; - int ret; - - _D("key : %s / value : %s", AUL_K_SDK, str); - /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/ - /* GCOV_PREFIX contains the prefix to add to the absolute paths in the - *object file. */ - /* Prefix can be absolute, or relative. The default is no prefix. - * */ - /* GCOV_PREFIX_STRIP indicates the how many initial directory names */ - /* to stripoff the hardwired absolute paths. Default value is 0. */ - if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) { - snprintf(buf, - MAX_LOCAL_BUFSZ, - PATH_APP_ROOT "/%s"PATH_DATA, - _get_pkgname(menu_info)); - ret = setenv("GCOV_PREFIX", buf, 1); - _D("GCOV_PREFIX : %d", ret); - ret = setenv("GCOV_PREFIX_STRIP", "4096", 1); - _D("GCOV_PREFIX_STRIP : %d", ret); - } else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0) { - ret = setenv("LD_PRELOAD", PATH_DA_SO, 1); - _D("LD_PRELOAD : %d", ret); - } -} - -_static_ void __set_env(app_info_from_db * menu_info, bundle * kb) -{ - const char *str; - - setenv("PKG_NAME", _get_pkgname(menu_info), 1); - - USE_ENGINE("gl") - - str = bundle_get_val(kb, AUL_K_STARTTIME); - if (str != NULL) { - setenv("APP_START_TIME", str, 1); - } - - if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) { - int len; - const char **str_array; - str_array = bundle_get_str_array(kb, AUL_K_SDK, &len); - if (str_array != NULL) { - int i; - for (i = 0; i < len; i++) { - _D("index : [%d]", i); - __set_sdk_env(menu_info, (char *)str_array[i]); - } - } - } else { - str = bundle_get_val(kb, AUL_K_SDK); - if (str != NULL) { - __set_sdk_env(menu_info, (char *)str); - } - } - if (menu_info->hwacc != NULL) { - setenv("HWACC", menu_info->hwacc, 1); - } -} - _static_ int __prepare_exec(const char *pkg_name, const char *app_path, app_info_from_db * menu_info, bundle * kb) @@ -198,6 +125,7 @@ _static_ int __prepare_exec(const char *pkg_name, _D("fail to set privileges - check your package's credential\n"); return -1; } + /* SET DUMPABLE - for coredump*/ prctl(PR_SET_DUMPABLE, 1); @@ -235,17 +163,6 @@ _static_ int __fake_launch_app(int cmd, int pid, bundle * kb) return ret; } -_static_ char **__create_argc_argv(bundle * kb, int *margc) -{ - char **argv; - int argc; - - argc = bundle_export_to_argv(kb, &argv); - - *margc = argc; - return argv; -} - _static_ int __normal_fork_exec(int argc, char **argv) { _D("start real fork and exec\n"); @@ -299,152 +216,9 @@ _static_ void __real_launch(const char *app_path, bundle * kb) __normal_fork_exec(app_argc, app_argv); } -/* - * Parsing original app path to retrieve default bundle - * - * -1 : Invalid sequence - * -2 : Buffer overflow - * - */ -static inline int __parser(const char *arg, char *out, int out_size) -{ - register int i; - int state = 1; - char *start_out = out; - - if (arg == NULL || out == NULL) { - /* Handles null buffer*/ - return 0; - } - - for (i = 0; out_size > 1; i++) { - switch (state) { - case 1: - switch (arg[i]) { - case ' ': - case '\t': - state = 5; - break; - case '\0': - state = 7; - break; - case '\"': - state = 2; - break; - case '\\': - state = 4; - break; - default: - *out = arg[i]; - out++; - out_size--; - break; - } - break; - case 2: /* escape start*/ - switch (arg[i]) { - case '\0': - state = 6; - break; - case '\"': - state = 1; - break; - default: - *out = arg[i]; - out++; - out_size--; - break; - } - break; - case 4: /* character escape*/ - if (arg[i] == '\0') { - state = 6; - } else { - *out = arg[i]; - out++; - out_size--; - state = 1; - } - break; - case 5: /* token*/ - if (out != start_out) { - *out = '\0'; - out_size--; - return i; - } - i--; - state = 1; - break; - case 6: - return -1; /* error*/ - case 7: /* terminate*/ - *out = '\0'; - out_size--; - return 0; - default: - state = 6; - break; /* error*/ - } - } - - if (out_size == 1) { - *out = '\0'; - } - /* Buffer overflow*/ - return -2; -} - -_static_ void __modify_bundle(bundle * kb, int caller_pid, - app_info_from_db * menu_info, int cmd) +_static_ int __dummy_launch(int dummy_client_fd, app_pkt_t* pkt) { - // warning: unused parameter - (void)caller_pid; - - bundle_del(kb, AUL_K_PKG_NAME); - bundle_del(kb, AUL_K_EXEC); - bundle_del(kb, AUL_K_PACKAGETYPE); - bundle_del(kb, AUL_K_HWACC); - - /* Parse app_path to retrieve default bundle*/ - if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN || cmd == - APP_RESUME) - { - char *ptr; - char exe[MAX_PATH_LEN]; - int flag; - - ptr = _get_original_app_path(menu_info); - - flag = __parser(ptr, exe, sizeof(exe)); - if (flag > 0) { - char key[256]; - char value[256]; - - ptr += flag; - _D("parsing app_path: EXEC - %s\n", exe); - - do { - flag = __parser(ptr, key, sizeof(key)); - if (flag <= 0) { - break; - } - ptr += flag; - - flag = __parser(ptr, value, sizeof(value)); - if (flag < 0) { - break; - } - ptr += flag; - - /*bundle_del(kb, key);*/ - bundle_add(kb, key, value); - } while (flag > 0); - } else if (flag == 0) { - _D("parsing app_path: No arguments\n"); - } else { - _D("parsing app_path: Invalid argument\n"); - } - } + return __send_pkt_raw_data(dummy_client_fd, pkt); } _static_ int __child_raise_win_by_x(int pid, void *priv) @@ -646,33 +420,84 @@ _static_ void __send_result_to_caller(int clifd, int ret) return; } -static app_info_from_db *_get_app_info_from_bundle_by_pkgname( - const char *pkgname, bundle *kb) +_static_ void __launchpad_exec_dummy(int main_fd, int pool_fd, int client_fd) { - app_info_from_db *menu_info; + int pid; - menu_info = calloc(1, sizeof(app_info_from_db)); - if (menu_info == NULL) { - return NULL; - } + last_dummy_exec_time = time(NULL); - menu_info->pkg_name = strdup(pkgname); - menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC)); - if (menu_info->app_path != NULL) { - menu_info->original_app_path = strdup(menu_info->app_path); - } - menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE)); - menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC)); + pid = fork(); - if (!_get_app_path(menu_info)) { - _free_app_info_from_db(menu_info); - return NULL; - } + if (pid == 0) // child + { + setpriority(PRIO_PROCESS, 0, LOWEST_PRIO); + _D("Launch dummy process..."); + + //temp - this requires some optimization. + sleep(1); + _D("sleeping 1sec..."); + + /* Set new session ID & new process group ID*/ + /* In linux, child can set new session ID without check permission */ + /* TODO : should be add to check permission in the kernel*/ + setsid(); + + /* SET OOM*/ + __set_oom(); + + + if (main_fd != -1) + { + close(main_fd); + } + + if (pool_fd != -1) + { + close(pool_fd); + } + + if (client_fd != -1) + { + close(client_fd); + } + + __signal_unset_sigchld(); + __signal_fini(); + + /* SET DUMPABLE - for coredump*/ + prctl(PR_SET_DUMPABLE, 1); + + { + void *handle = NULL; + int (*dl_main) (int, char **); + + handle = dlopen(WRT_CLIENT_PATH, RTLD_NOW | RTLD_GLOBAL); + + if (handle == NULL) + { + _E("dlopen failed."); + exit(-1); + } + + dl_main = dlsym(handle, "main"); + + sprintf(g_argv[1], "%s", "-d"); + + if (dl_main != NULL) + { + dl_main(g_argc, g_argv); + } + else + { + _E("dlsym not founded. bad preloaded app - check fpie pie"); + } - return menu_info; + exit(0); + } + } } -_static_ void __launchpad_main_loop(int main_fd) +_static_ void __launchpad_main_loop(int main_fd, int pool_fd) { bundle *kb = NULL; app_pkt_t *pkt = NULL; @@ -726,9 +551,33 @@ _static_ void __launchpad_main_loop(int main_fd) PERF("get package information & modify bundle done"); + if (dummy_process_pid != DUMMY_NONE) + { + snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, dummy_process_pid); + unlink(sock_path); + + __dummy_launch(dummy_process_fd, pkt); + + pid = dummy_process_pid; + is_real_launch = 1; + close(dummy_process_fd); + + dummy_process_pid = DUMMY_NONE; + dummy_process_fd = -1; + + /* Temporary log: launch time checking */ + LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path); + + __launchpad_exec_dummy(main_fd, pool_fd, clifd); + + _D("==> dummy launch pid : %d %s\n", pid, app_path); + } + else { pid = fork(); - if (pid == 0) { + + if (pid == 0) + { PERF("fork done"); _E("lock up test log(no error) : fork done"); @@ -846,38 +695,143 @@ _static_ int __launchpad_post_init() int main(int argc, char **argv) { - int main_fd; + enum { + LAUNCH_PAD = 0, + POOL_SERVER, + DUMMY_PROCESS, + POLLFD_MAX + }; + + int main_fd = -1, pool_fd = -1; struct pollfd pfds[POLLFD_MAX]; - int i; + + memset(pfds, 0x00, sizeof(pfds)); + + // process pool feature disable + if (getenv("WRT_PROCESS_POOL_DISABLE")) + { + process_pool_disable = 1; + } /* init without concerning X & EFL*/ main_fd = __launchpad_pre_init(argc, argv); - if (main_fd < 0) { + + if (main_fd < 0) + { _E("launchpad pre init failed"); - exit(-1); + goto exit_main; + } + + pfds[LAUNCH_PAD].fd = main_fd; + pfds[LAUNCH_PAD].events = POLLIN; + pfds[LAUNCH_PAD].revents = 0; + + pool_fd = __create_process_pool_server(); + + if (pool_fd == -1) + { + _E("Error creationg pool server!"); + goto exit_main; } - pfds[0].fd = main_fd; - pfds[0].events = POLLIN; - pfds[0].revents = 0; + pfds[POOL_SERVER].fd = pool_fd; + pfds[POOL_SERVER].events = POLLIN; + pfds[POOL_SERVER].revents = 0; - while (1) { - if (poll(pfds, POLLFD_MAX, -1) < 0) { + while (1) + { + if (dummy_process_pid == DUMMY_NONE) + { + pfds[DUMMY_PROCESS].fd = -1; + pfds[DUMMY_PROCESS].events = 0; + pfds[DUMMY_PROCESS].revents = 0; + + if ( !process_pool_disable && + DIFF(last_dummy_exec_time, time(NULL)) > EXEC_DUMMY_EXPIRED) + { + __launchpad_exec_dummy(main_fd, pool_fd, -1); + } + } + + if (poll(pfds, POLLFD_MAX, -1) < 0) + { continue; } + _D("pfds[LAUNCH_PAD].revents : 0x%x", pfds[LAUNCH_PAD].revents) ; + _D("pfds[POOL_SERVER].revents : 0x%x", pfds[POOL_SERVER].revents) ; + _D("pfds[DUMMY_PROCESS].revents : 0x%x", pfds[DUMMY_PROCESS].revents) ; + /* init with concerning X & EFL (because of booting - * sequence problem)*/ - if (__launchpad_post_init() < 0) { + * sequence problem)*/ + if (__launchpad_post_init() < 0) + { _E("launcpad post init failed"); - exit(-1); + goto exit_main; + } + + if ((pfds[LAUNCH_PAD].revents & POLLIN) != 0) + { + _D("pfds[LAUNCH_PAD].revents & POLLIN"); + __launchpad_main_loop(pfds[LAUNCH_PAD].fd, pfds[POOL_SERVER].fd); } - for (i = 0; i < POLLFD_MAX; i++) { - if ((pfds[i].revents & POLLIN) != 0) { - __launchpad_main_loop(pfds[i].fd); + if ((pfds[POOL_SERVER].revents & POLLIN) != 0) + { + int server_fd, client_fd, client_pid; + + server_fd = pfds[POOL_SERVER].fd; + + _D("pfds[POOL_SERVER].revents & POLLIN"); + + if (dummy_process_pid == DUMMY_NONE) + { + __accept_dummy_process(server_fd, &client_fd, &client_pid); + + dummy_process_pid = client_pid; + dummy_process_fd = client_fd; + + pfds[DUMMY_PROCESS].fd = dummy_process_fd; + pfds[DUMMY_PROCESS].events = POLLIN|POLLHUP; + pfds[DUMMY_PROCESS].revents = 0; + + _D("Dummy process was connected! (pid:%d)", dummy_process_pid); + } + else + { + __refuse_dummy_process(server_fd); + + _E("Refused dummy process connection!"); } } + + if ((pfds[DUMMY_PROCESS].revents & (POLLHUP|POLLNVAL)) != 0) + { + _D("pfds[DUMMY_PROCESS].revents & (POLLHUP|POLLNVAL) (pid:%d)", dummy_process_pid); + close(pfds[DUMMY_PROCESS].fd); + + dummy_process_pid = DUMMY_NONE; + dummy_process_fd = -1; + + pfds[DUMMY_PROCESS].fd = -1; + pfds[DUMMY_PROCESS].events = 0; + pfds[DUMMY_PROCESS].revents = 0; + } } + + return 0; + + exit_main: + if (main_fd != -1) + { + close(main_fd); + } + + if (pool_fd != -1) + { + close(pool_fd); + } + + return -1; } diff --git a/src/wrt-launchpad-daemon/legacy/preload_list_wrt.txt b/src/wrt-launchpad-daemon/legacy/preload_list_wrt.txt index 01635cd..5197b66 100644 --- a/src/wrt-launchpad-daemon/legacy/preload_list_wrt.txt +++ b/src/wrt-launchpad-daemon/legacy/preload_list_wrt.txt @@ -1,2 +1,4 @@ /usr/bin/wrt-client -/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so \ No newline at end of file +/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so +/usr/lib/wrt-plugins/w3c-widget-interface/libwrt-plugins-w3c-widget-interface.so +/usr/lib/wrt-plugins/tizen-tizen/libwrt-plugins-tizen-tizen.so diff --git a/src/wrt-launchpad-daemon/src/app_sock.c b/src/wrt-launchpad-daemon/src/app_sock.c index 26edf9f..9089610 100644 --- a/src/wrt-launchpad-daemon/src/app_sock.c +++ b/src/wrt-launchpad-daemon/src/app_sock.c @@ -153,10 +153,11 @@ int __create_client_sock(int pid) { int fd = -1; struct sockaddr_un saddr; - memset(&saddr, 0, sizeof(saddr)); int retry = 1; int ret = -1; + memset(&saddr, 0x00, sizeof(struct sockaddr_un)); + fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); /* support above version 2.6.27*/ if (fd < 0) { @@ -329,11 +330,11 @@ app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr) { int len; struct sockaddr_un aul_addr; - memset(&aul_addr, 0, sizeof(aul_addr)); int sun_size; app_pkt_t *pkt = NULL; int cl = sizeof(struct ucred); + memset(&aul_addr, 0x00, sizeof(struct sockaddr_un)); sun_size = sizeof(struct sockaddr_un); if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr, diff --git a/src/wrt-launchpad-daemon/src/process_pool.c b/src/wrt-launchpad-daemon/src/process_pool.c new file mode 100644 index 0000000..11debe1 --- /dev/null +++ b/src/wrt-launchpad-daemon/src/process_pool.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2013 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. + */ +/** + * @file process_pool.c + * @author Tae-Jeong Lee (taejeong.lee@samsung.com) + * @version 0.1 + * @brief process pool socket apis + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "process_pool.h" +#include "simple_util.h" + +#define TMP_PATH "/tmp" +#define PROCESS_POOL_SERVER "wrt_process_pool_server" +#define MAX_PENDING_CONNECTIONS 10 +#define CONNECT_RETRY_TIME 100 * 1000 +#define CONNECT_RETRY_COUNT 3 + +int __create_process_pool_server() +{ + struct sockaddr_un addr; + int fd = -1; + + memset(&addr, 0x00, sizeof(struct sockaddr_un)); + + fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + + if (fd < 0) + { + _E("socket error"); + goto err_create_process_pool_server; + } + + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%s", TMP_PATH, PROCESS_POOL_SERVER); + unlink(addr.sun_path); + + _D("bind to %s", addr.sun_path); + if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + _E("bind error"); + goto err_create_process_pool_server; + } + + _D("chmod to %s", addr.sun_path); + if (chmod(addr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) + { + _E("chmod error"); + goto err_create_process_pool_server; + } + + _D("listen to %s", addr.sun_path); + if (listen(fd, MAX_PENDING_CONNECTIONS) == -1) + { + _E("listen error"); + goto err_create_process_pool_server; + } + + _D("__create_process_pool_server done : %d", fd); + return fd; + + +err_create_process_pool_server: + + if (fd != -1) + { + close(fd); + } + + return -1; +} + + +int __connect_process_pool_server() +{ + struct sockaddr_un addr; + int fd = -1; + int retry = CONNECT_RETRY_COUNT; + int send_ret = -1; + int client_pid = getpid(); + + memset(&addr, 0x00, sizeof(struct sockaddr_un)); + + fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + + if (fd < 0) + { + _E("socket error"); + + goto err_connect_process_pool_server; + } + + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%s", TMP_PATH, PROCESS_POOL_SERVER); + + + _D("connect to %s", addr.sun_path); + while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + if (errno != ETIMEDOUT || retry <= 0) + { + _E("connect error : %d", errno); + + goto err_connect_process_pool_server; + } + + usleep(CONNECT_RETRY_TIME); + retry--; + _D("re-connect to %s (%d)", addr.sun_path, retry); + } + + send_ret = send(fd, &client_pid, sizeof(client_pid), 0); + _D("send(%d) : %d", client_pid, send_ret); + + if (send_ret == -1) + { + _E("send error"); + + goto err_connect_process_pool_server; + } + + _D("__connect_process_pool_server done : %d", fd); + return fd; + +err_connect_process_pool_server: + + if (fd != -1) + { + close(fd); + } + + return -1; +} + + +int __accept_dummy_process(int server_fd, int* out_client_fd, int* out_client_pid) +{ + int client_fd = -1, client_pid = 0, recv_ret = 0; + + if (server_fd == -1 || out_client_fd == NULL || out_client_pid == NULL) + { + _E("arguments error!"); + + goto err__accept_dummy_process; + } + + client_fd = accept(server_fd, NULL, NULL); + + if (client_fd == -1) + { + _E("accept error!"); + + goto err__accept_dummy_process; + } + + recv_ret = recv(client_fd, &client_pid, sizeof(client_pid), MSG_WAITALL); + + if (recv_ret == -1) + { + _E("recv error!"); + + goto err__accept_dummy_process; + } + + *out_client_fd = client_fd; + *out_client_pid = client_pid; + + return *out_client_fd; + +err__accept_dummy_process: + + if (client_fd != -1) + { + close(client_fd); + } + + return -1; +} + +void __refuse_dummy_process(int server_fd) +{ + int client_fd = -1; + + if (server_fd == -1) + { + _E("arguments error!"); + + goto err__refuse_dummy_process; + } + + client_fd = accept(server_fd, NULL, NULL); + + if (client_fd == -1) + { + _E("accept error!"); + + goto err__refuse_dummy_process; + } + + close(client_fd); + _D("refuse connection!"); + + return; + +err__refuse_dummy_process: + + if (client_fd != -1) + { + close(client_fd); + } + + return; +} + + +int __send_pkt_raw_data(int client_fd, app_pkt_t* pkt) +{ + int send_ret = 0; + int pkt_size = 0; + + if (client_fd == -1 || pkt == NULL) + { + _E("arguments error!"); + + goto err__send_pkt_raw_data; + } + + pkt_size = sizeof(pkt->cmd) + sizeof(pkt->len) + pkt->len; + + send_ret = send(client_fd, pkt, pkt_size, 0); + _D("send(%d) : %d / %d", client_fd, send_ret, pkt_size); + + if (send_ret == -1) + { + _E("send error!"); + + goto err__send_pkt_raw_data; + } + else if (send_ret != pkt_size) + { + _E("send byte fail!"); + + goto err__send_pkt_raw_data; + } + + return 0; + +err__send_pkt_raw_data: + + return -1; +} \ No newline at end of file diff --git a/wrt_env.sh b/wrt_env.sh new file mode 100644 index 0000000..d09621f --- /dev/null +++ b/wrt_env.sh @@ -0,0 +1,2 @@ +# This env is enabled in private ONLY +#export WRT_PROCESS_POOL_DISABLE=ON -- 2.7.4