X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fwrt-client%2Fwrt-client.cpp;h=188bf04ca18e472e1bb76fcc3d15cb3efd32eb9e;hb=4c33c56a40de04d4edd713f723e5716cb7a771f0;hp=4c60eb7c3f529f7deaede8d971cd1c8c6696739d;hpb=d75ad6801fb2e9bea53cadcba1f4000fac95291c;p=platform%2Fframework%2Fweb%2Fwrt.git diff --git a/src/wrt-client/wrt-client.cpp b/src/wrt-client/wrt-client.cpp index 4c60eb7..188bf04 100644 --- a/src/wrt-client/wrt-client.cpp +++ b/src/wrt-client/wrt-client.cpp @@ -14,28 +14,62 @@ * limitations under the License. */ #include "wrt-client.h" +#include +#include +#include +#include +#include #include #include #include #include #include #include -#include +#include #include -#include #include #include #include #include #include +#include +#include +#include "auto_rotation_support.h" + +#include +#include + +#include "client_command_line_parser.h" +#include "client_ide_support.h" +#include "client_security_support.h" +#include "client_service_support.h" +#include "client_submode_support.h" //W3C PACKAGING enviroment variable name #define W3C_DEBUG_ENV_VARIABLE "DEBUG_LOAD_FINISH" // window signal callback -const char *EDJE_SHOW_BACKWARD_SIGNAL = "show,backward,signal"; +const char *EDJE_SHOW_PROGRESS_SIGNAL = "show,progress,signal"; +const char *EDJE_HIDE_PROGRESS_SIGNAL = "hide,progress,signal"; const std::string VIEWMODE_TYPE_FULLSCREEN = "fullscreen"; const std::string VIEWMODE_TYPE_MAXIMIZED = "maximized"; +const std::string VIEWMODE_TYPE_WINDOWED = "windowed"; +char const* const ELM_SWALLOW_CONTENT = "elm.swallow.content"; +const char* const BUNDLE_PATH = LIBDIR_PREFIX "/usr/lib/libwrt-injected-bundle.so"; +const char* const MESSAGE_NAME_INITIALIZE = "ToInjectedBundle::INIT"; +const unsigned int UID_ROOT = 0; + +// 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; + +// env +const char* const HOME = "HOME"; +const char* const APP_HOME_PATH = "/opt/home/app"; +const char* const ROOT_HOME_PATH = "/opt/home/root"; WrtClient::WrtClient(int argc, char **argv) : Application(argc, argv, "wrt-client", false), @@ -43,11 +77,14 @@ WrtClient::WrtClient(int argc, char **argv) : m_launched(false), m_initializing(false), m_initialized(false), - m_sdkLauncherPid(0), m_debugMode(false), - m_debuggerPort(0), m_returnStatus(ReturnStatus::Succeeded), - m_widgetState(WidgetState::WidgetState_Stopped) + m_widgetState(WidgetState::WidgetState_Stopped), + m_initialViewMode(VIEWMODE_TYPE_MAXIMIZED), + m_currentViewMode(VIEWMODE_TYPE_MAXIMIZED), + m_isWebkitFullscreen(false), + m_isFullscreenByPlatform(false), + m_submodeSupport(new ClientModule::SubmodeSupport()) { Touch(); LogDebug("App Created"); @@ -65,18 +102,16 @@ WrtClient::ReturnStatus::Type WrtClient::getReturnStatus() const void WrtClient::OnStop() { - LogInfo("Stopping Dummy Client"); + LogDebug("Stopping Dummy Client"); } - void WrtClient::OnCreate() { - LogInfo("On Create"); + LogDebug("On Create"); ADD_PROFILING_POINT("OnCreate callback", "point"); ewk_init(); } - void WrtClient::OnResume() { if (m_widgetState != WidgetState_Suspended) { @@ -87,15 +122,17 @@ void WrtClient::OnResume() m_widgetState = WidgetState_Running; } - void WrtClient::OnPause() { - LogDebug("On pause"); - if (m_widgetState != WidgetState_Running) { LogWarning("Widget is not running to be suspended"); return; } + if (m_submodeSupport->isNeedTerminateOnSuspend()) { + LogDebug("Current mode cannot support suspend"); + elm_exit(); + return; + } m_widget->Suspend(); m_widgetState = WidgetState_Suspended; } @@ -106,6 +143,7 @@ void WrtClient::OnReset(bundle *b) // bundle argument is freed after OnReset() is returned // So bundle duplication is needed ApplicationDataSingleton::Instance().setBundle(bundle_dup(b)); + ApplicationDataSingleton::Instance().setEncodedBundle(b); if (true == m_initializing) { LogDebug("can not handle reset event"); @@ -117,18 +155,23 @@ void WrtClient::OnReset(bundle *b) return; } m_widget->Reset(); - m_windowData->emitSignalForUserLayout(EDJE_SHOW_BACKWARD_SIGNAL, ""); m_widgetState = WidgetState_Running; } else { - if (true == checkArgument()) - { - setStep(); - } - else - { + m_tizenId = + ClientModule::CommandLineParser::getTizenId(m_argc, m_argv); + if (m_tizenId.empty()) { showHelpAndQuit(); + } else { + setDebugMode(b); + setStep(); } } + + // low memory callback set + appcore_set_event_callback( + APPCORE_EVENT_LOW_MEMORY, + WrtClient::appcoreLowMemoryCallback, + this); } void WrtClient::OnTerminate() @@ -153,59 +196,11 @@ void WrtClient::showHelpAndQuit() Quit(); } -bool WrtClient::checkArgument() -{ - LogInfo("checkArgument"); - - std::string arg = m_argv[0]; - - if (arg.empty()) { - return false; - } - - if (arg.find("wrt-client") != std::string::npos) - { - if (m_argc <= 1) { - return false; - } - - arg = m_argv[1]; - - if (arg == "-h" || arg == "--help") { - // Just show help - return false; - } else if (arg == "-l" || arg == "--launch" || - arg == "-t" || arg == "--tizen") { - if (m_argc != 3) { - return false; - } - m_tizenId = std::string(m_argv[2]); - } else { - return false; - } - } else { - size_t pos = arg.find_last_of('/'); - - if (pos != std::string::npos) { - arg = arg.erase(0, pos + 1); - } - - // Launch widget based on application basename - m_tizenId = arg; - LogDebug("Tizen id: " << m_tizenId); - } - - return true; -} - void WrtClient::setStep() { - LogInfo("setStep"); + LogDebug("setStep"); AddStep(&WrtClient::initStep); - - setSdkLauncherDebugData(); - AddStep(&WrtClient::launchStep); AddStep(&WrtClient::shutdownStep); @@ -214,61 +209,10 @@ void WrtClient::setStep() DPL::Event::ControllerEventHandler::PostEvent(NextStepEvent()); } -void WrtClient::setSdkLauncherDebugData() +void WrtClient::setDebugMode(bundle* b) { - LogDebug("setSdkLauncherDebugData"); - - /* check bundle from sdk launcher */ - bundle *bundleFromSdkLauncher; - bundleFromSdkLauncher = bundle_import_from_argv(m_argc, m_argv); - const char *bundle_debug = bundle_get_val(bundleFromSdkLauncher, "debug"); - const char *bundle_pid = bundle_get_val(bundleFromSdkLauncher, "pid"); - if (bundle_debug != NULL && bundle_pid != NULL) { - if (strcmp(bundle_debug, "true") == 0) { - m_debugMode = true; - m_sdkLauncherPid = atoi(bundle_pid); - } else { - m_debugMode = false; - } - } - bundle_free(bundleFromSdkLauncher); -} - -bool WrtClient::checkDebugMode(SDKDebugData* debugData) -{ - LogError("Checking for debug mode"); - Assert(m_dao); - - bool debugMode = debugData->debugMode; - - LogInfo("[DEBUG_MODE] Widget is launched in " << - (debugMode ? "DEBUG" : "RETAIL") << - " mode."); - - if (debugMode == true) { - // In WAC widget, only test widgets can use web inspector. - // In TIZEN widget, - // every launched widgets as debug mode can use it. - if (m_dao->getWidgetType().appType == WrtDB::APP_TYPE_WAC20) - { - bool developerMode = - GlobalLogicSingleton::Instance().GetGlobalModel() - ->DeveloperMode.Get(); - //This code will be activated - //after WAC test certificate is used by SDK - //bool isTestWidget = view->m_widgetModel->IsTestWidget.Get(); - //if(!isTestWidget) - //{ - // LogInfo("This is not WAC Test Widget"); - // break; - //} - if (!developerMode) { - LogInfo("This is not WAC Developer Mode"); - debugMode = false; - } - } - } - return debugMode; + m_debugMode = ClientModule::IDESupport::getDebugMode(b); + LogDebug("debug mode : " << m_debugMode); } void WrtClient::OnEventReceived(const NextStepEvent& /*event*/) @@ -287,82 +231,26 @@ void WrtClient::initStep() SwitchToStep(&WrtClient::shutdownStep); } - // ecore_event_jobs are processed sequentially without concession to - // other type events. To give a chance of execute to other events, - // ecore_timer_add was used. - DPL::Event::ControllerEventHandler::PostTimedEvent( - NextStepEvent(),0.001); -} - -bool WrtClient::checkWACTestCertififedWidget() -{ - // WAC Waikiki Beta Release Core Specification: Widget Runtime - // 10 Dec 2010 - // - // WR-4710 The WRT MUST enable debug functions only for WAC test widgets - // i.e. the functions must not be usable for normal WAC widgets, even when - // a WAC test widget is executing. - ADD_PROFILING_POINT("DeveloperModeCheck", "start"); - Assert(!!m_dao); - // WAC test widget - // A widget signed with a WAC-issued test certificate as described in - // Developer Mode. - - bool developerWidget = m_dao->isTestWidget(); - bool developerMode = - GlobalLogicSingleton::Instance().GetGlobalModel()->DeveloperMode.Get(); - - LogDebug("Is WAC test widget: " << developerWidget); - LogDebug("Is developer Mode: " << developerMode); - - if (developerWidget) { - if(!developerMode) - { - LogError("WAC test certified developer widget is needed for " << - "developer mode"); - return false; - }else{ - //TODO: WR-4660 (show popup about developer widget - // during launch - LogInfo("POPUP: THIS IS TEST WIDGET!"); - } - } - ADD_PROFILING_POINT("DeveloperModeCheck", "stop"); - return true; + DPL::Event::ControllerEventHandler::PostEvent(NextStepEvent()); } void WrtClient::loadFinishCallback(Evas_Object* webview) { ADD_PROFILING_POINT("loadFinishCallback", "start"); - SDKDebugData* debug = new SDKDebugData; - debug->debugMode = m_debugMode; - debug->pid = new unsigned long(getpid()); - - LogInfo("Post result of launch"); - // Start inspector server, if current mode is debugger mode. - // In the WK2 case, ewk_view_inspector_server_start should - // be called after WebProcess is created. - if (checkDebugMode(debug)) + // Splash screen + if (m_splashScreen && m_splashScreen->isShowing()) { - debug->portnum = - ewk_view_inspector_server_start(m_widget->GetCurrentWebview(), 0); - if (debug->portnum == 0) { - LogWarning("Failed to get portnum"); - } else { - LogInfo("Assigned port number for inspector : " - << debug->portnum); - } - } else { - LogDebug("Debug mode is disabled"); + m_splashScreen->stopSplashScreenBuffered(); } + LogDebug("Post result of launch"); + //w3c packaging test debug (message on 4>) const char * makeScreen = getenv(W3C_DEBUG_ENV_VARIABLE); - if(makeScreen != NULL && strcmp(makeScreen, "1") == 0) - { + if (makeScreen != NULL && strcmp(makeScreen, "1") == 0) { FILE* doutput = fdopen(4, "w"); - fprintf(doutput,"didFinishLoadForFrameCallback: ready\n"); + fprintf(doutput, "didFinishLoadForFrameCallback: ready\n"); fclose(doutput); } @@ -381,33 +269,63 @@ void WrtClient::loadFinishCallback(Evas_Object* webview) m_returnStatus = ReturnStatus::Failed; //shutdownStep DPL::Event::ControllerEventHandler:: - PostEvent(NextStepEvent()); + PostEvent(NextStepEvent()); } - if(debug->debugMode) - { - LogDebug("Send RT signal to wrt-launcher(pid: " << m_sdkLauncherPid); - union sigval sv; - /* send real time signal with result to wrt-launcher */ - if(webview) { - LogDebug("userData->portnum : " << debug->portnum); - sv.sival_int = debug->portnum; - } else { - sv.sival_int = -1; + if (m_debugMode) { + unsigned int portNum = + ewk_view_inspector_server_start(m_widget->GetCurrentWebview(), 0); + LogDebug("Port for inspector : " << portNum); + bool ret = ClientModule::IDESupport::sendReply( + ApplicationDataSingleton::Instance().getBundle(), + portNum); + if (!ret) { + LogWarning("Fail to send reply"); } - sigqueue(m_sdkLauncherPid, SIGRTMIN, sv); } ApplicationDataSingleton::Instance().freeBundle(); +} + +void WrtClient::resetCallback(bool result) +{ + if (!result) { + LogDebug("Fail to handle reset event"); + // free bundle data + ApplicationDataSingleton::Instance().freeBundle(); + } +} - LogDebug("Cleaning wrtClient launch resources..."); - delete debug->pid; - delete debug; +void WrtClient::progressStartedCallback() +{ + if (m_settingList->getProgressBarPresence() == ProgressBar_Enable || + m_currentViewMode == VIEWMODE_TYPE_WINDOWED) + { + m_windowData->signalEmit(Layer::MAIN_LAYOUT, + EDJE_SHOW_PROGRESS_SIGNAL, + ""); + m_windowData->updateProgress(0); + } +} + +void WrtClient::loadProgressCallback(Evas_Object* /*webview*/, double value) +{ + if (m_settingList->getProgressBarPresence() == ProgressBar_Enable || + m_currentViewMode == VIEWMODE_TYPE_WINDOWED) + { + m_windowData->updateProgress(value); + } } void WrtClient::progressFinishCallback() { - m_splashScreen->stopSplashScreen(); + if (m_settingList->getProgressBarPresence() == ProgressBar_Enable || + m_currentViewMode == VIEWMODE_TYPE_WINDOWED) + { + m_windowData->signalEmit(Layer::MAIN_LAYOUT, + EDJE_HIDE_PROGRESS_SIGNAL, + ""); + } } void WrtClient::webkitExitCallback() @@ -415,7 +333,7 @@ void WrtClient::webkitExitCallback() LogDebug("window close called, terminating app"); SwitchToStep(&WrtClient::shutdownStep); DPL::Event::ControllerEventHandler::PostEvent( - NextStepEvent()); + NextStepEvent()); } void WrtClient::webCrashCallback() @@ -423,9 +341,29 @@ void WrtClient::webCrashCallback() LogError("webProcess crashed"); SwitchToStep(&WrtClient::shutdownStep); DPL::Event::ControllerEventHandler::PostEvent( - NextStepEvent()); + NextStepEvent()); } +void WrtClient::enterFullscreenCallback(Evas_Object* /*obj*/, + bool isFullscreenByPlatform) +{ + // enter fullscreen + m_windowData->toggleFullscreen(true); + m_currentViewMode = VIEWMODE_TYPE_FULLSCREEN; + m_isWebkitFullscreen = true; + if (isFullscreenByPlatform) { + m_isFullscreenByPlatform = true; + } +} + +void WrtClient::exitFullscreenCallback(Evas_Object* /*obj*/) +{ + // exit fullscreen + m_windowData->toggleFullscreen(false); + m_currentViewMode = m_initialViewMode; + m_isWebkitFullscreen = false; + m_isFullscreenByPlatform = false; +} void WrtClient::launchStep() { @@ -434,290 +372,538 @@ void WrtClient::launchStep() ADD_PROFILING_POINT("getRunnableWidgetObject", "start"); m_widget = WRT::CoreModuleSingleton::Instance() - .getRunnableWidgetObject(m_tizenId); + .getRunnableWidgetObject(m_tizenId); ADD_PROFILING_POINT("getRunnableWidgetObject", "stop"); if (!m_widget) { LogError("RunnableWidgetObject is NULL, stop launchStep"); DPL::Event::ControllerEventHandler::PostEvent( - NextStepEvent()); + NextStepEvent()); return; } if (m_widgetState == WidgetState_Running) { LogWarning("Widget already running, stop launchStep"); DPL::Event::ControllerEventHandler::PostEvent( - NextStepEvent()); + NextStepEvent()); return; } if (m_widgetState == WidgetState_Authorizing) { LogWarning("Widget already authorizing, stop launchStep"); DPL::Event::ControllerEventHandler::PostEvent( - NextStepEvent()); + NextStepEvent()); return; } m_dao.reset(new WrtDB::WidgetDAOReadOnly(DPL::FromASCIIString(m_tizenId))); + WrtDB::WidgetSettings widgetSettings; + m_dao->getWidgetSettings(widgetSettings); + m_settingList.reset(new WidgetSettingList(widgetSettings)); + m_submodeSupport->initialize(DPL::FromASCIIString(m_tizenId)); + DPL::Optional defloc = m_dao->getDefaultlocale(); - if(!defloc.IsNull()) - { - LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(*defloc); + if (!defloc.IsNull()) { + LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales( + *defloc); } + setInitialViewMode(); + + /* remove language change callback */ + /* LocalizationSetting::SetLanguageChangedCallback( languageChangedCallback, this); + */ ADD_PROFILING_POINT("CreateWindow", "start"); - m_windowData.reset(new WindowData(static_cast(getpid()))); + 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"); + if (!m_windowData->initScreenReaderSupport( + m_settingList->getAccessibility() == Accessibility_Enable)) + { + LogWarning("Fail to set screen reader support set"); + } + + // rotate window to initial value + setWindowInitialOrientation(); + setCtxpopupItem(); WRT::UserDelegatesPtr cbs(new WRT::UserDelegates); + ADD_PROFILING_POINT("Create splash screen", "start"); - m_splashScreen.reset( - new SplashScreenSupport(m_windowData->m_win)); - if (m_splashScreen->createSplashScreen(m_dao->getSplashImgSrc())) { + DPL::OptionalString splashImgSrc = m_dao->getSplashImgSrc(); + if (!splashImgSrc.IsNull()) + { + m_splashScreen.reset( + new SplashScreenSupport( + m_windowData->getEvasObject(Layer::WINDOW), + (DPL::ToUTF8String(*splashImgSrc)).c_str(), + m_currentViewMode != VIEWMODE_TYPE_FULLSCREEN, + m_settingList->getRotationValue() == Screen_Landscape)); m_splashScreen->startSplashScreen(); - cbs->progressFinish = DPL::MakeDelegate(this, &WrtClient::progressFinishCallback); } ADD_PROFILING_POINT("Create splash screen", "stop"); + DPL::OptionalString startUrl = W3CFileLocalization::getStartFile(m_dao); - m_widget->PrepareView(DPL::ToUTF8String(*startUrl), - m_windowData->m_win); + if (!m_widget->PrepareView( + DPL::ToUTF8String(*startUrl), + m_windowData->getEvasObject(Layer::WINDOW), + s_preparedEwkContext)) + { + DPL::Event::ControllerEventHandler::PostEvent( + NextStepEvent()); + return; + } + // send rotate information to ewk + setEwkInitialOrientation(); + //you can't show window with splash screen before PrepareView //ewk_view_add_with_context() in viewLogic breaks window + m_windowData->init(); + m_windowData->postInit(); + +#if X11 + // sub-mode support + if (m_submodeSupport->isInlineMode()) { + if (m_submodeSupport->transientWindow( + elm_win_xwindow_get( + m_windowData->getEvasObject(Layer::WINDOW)))) + { + LogDebug("Success to set submode"); + } else { + LogWarning("Fail to set submode"); + } + } +#endif + m_windowData->smartCallbackAdd(Layer::FOCUS, + "focused", + focusedCallback, + this); + m_windowData->smartCallbackAdd(Layer::FOCUS, + "unfocused", + unfocusedCallback, + this); WrtDB::WidgetLocalizedInfo localizedInfo = W3CFileLocalization::getLocalizedInfo(m_dao); - std:: string name = ""; + std::string name = ""; if (!(localizedInfo.name.IsNull())) { name = DPL::ToUTF8String(*(localizedInfo.name)); } - elm_win_title_set(m_windowData->m_win, name.c_str()); - evas_object_show(m_windowData->m_win); - initializeWindowModes(); - connectElmCallback(); + elm_win_title_set(m_windowData->getEvasObject(Layer::WINDOW), + name.c_str()); - if (!checkWACTestCertififedWidget()) - { - LogWarning("WAC Certificate failed, stop launchStep"); - return; - } + // window show + evas_object_show(m_windowData->getEvasObject(Layer::WINDOW)); + + initializeWindowModes(); m_widgetState = WidgetState_Authorizing; if (!m_widget->CheckBeforeLaunch()) { LogError("CheckBeforeLaunch failed, stop launchStep"); DPL::Event::ControllerEventHandler::PostEvent( - NextStepEvent()); + NextStepEvent()); return; } - LogInfo("Widget launch accepted. Entering running state"); + LogDebug("Widget launch accepted. Entering running state"); m_widgetState = WidgetState_Running; + cbs->progressStarted = DPL::MakeDelegate(this, &WrtClient::progressStartedCallback); + cbs->progress = DPL::MakeDelegate(this, &WrtClient::loadProgressCallback); + cbs->progressFinish = DPL::MakeDelegate(this, &WrtClient::progressFinishCallback); cbs->loadFinish = DPL::MakeDelegate(this, &WrtClient::loadFinishCallback); + cbs->reset = DPL::MakeDelegate(this, &WrtClient::resetCallback); cbs->bufferSet = DPL::MakeDelegate(this, &WrtClient::setLayout); cbs->bufferUnset = DPL::MakeDelegate(this, &WrtClient::unsetLayout); cbs->webkitExit = DPL::MakeDelegate(this, &WrtClient::webkitExitCallback); cbs->webCrash = DPL::MakeDelegate(this, &WrtClient::webCrashCallback); - cbs->toggleFullscreen = DPL::MakeDelegate(m_windowData.get(), &WindowData::toggleFullscreen); + cbs->enterFullscreen = DPL::MakeDelegate(this, &WrtClient::enterFullscreenCallback); + cbs->exitFullscreen = DPL::MakeDelegate(this, &WrtClient::exitFullscreenCallback); + cbs->setOrientation = DPL::MakeDelegate(this, &WrtClient::setWindowOrientation); + cbs->hwkey = DPL::MakeDelegate(this, &WrtClient::hwkeyCallback); m_widget->SetUserDelegates(cbs); m_widget->Show(); - m_windowData->emitSignalForUserLayout(EDJE_SHOW_BACKWARD_SIGNAL, ""); + ADD_PROFILING_POINT("launchStep", "stop"); } void WrtClient::initializeWindowModes() { Assert(m_windowData); - Assert(m_dao); - auto windowModes = m_dao->getWindowModes(); - bool fullscreen = false; - bool backbutton = false; - if (m_dao->getWidgetType().appType == WrtDB::APP_TYPE_TIZENWEBAPP) { - WidgetSettings widgetSettings; - m_dao->getWidgetSettings(widgetSettings); - WidgetSettingList settings(widgetSettings); - backbutton = - (settings.getBackButtonPresence() == BackButton_Enable); - } - - FOREACH(it, windowModes) + bool backbutton = + (m_settingList->getBackButtonPresence() == BackButton_Enable || + m_currentViewMode == VIEWMODE_TYPE_WINDOWED); + m_windowData->setViewMode(m_currentViewMode == VIEWMODE_TYPE_FULLSCREEN, + backbutton); +} + +Eina_Bool WrtClient::naviframeBackButtonCallback(void* data, + Elm_Object_Item* /*it*/) +{ + LogDebug("BackButtonCallback"); + Assert(data); + + WrtClient* This = static_cast(data); + This->m_widget->Backward(); + return EINA_FALSE; +} + +int WrtClient::appcoreLowMemoryCallback(void* /*data*/) +{ + LogDebug("appcoreLowMemoryCallback"); + //WrtClient* This = static_cast(data); + + // TODO call RunnableWidgetObject API regarding low memory + // The API should be implemented + + // temporary solution because we have no way to get ewk_context from runnable object. + if (s_preparedEwkContext) { + ewk_context_cache_clear(s_preparedEwkContext); + ewk_context_notify_low_memory(s_preparedEwkContext); + } + + return 0; +} + +void WrtClient::setInitialViewMode(void) +{ + Assert(m_dao); + WrtDB::WindowModeList windowModes = m_dao->getWindowModes(); + FOREACH(it, windowModes) { std::string viewMode = DPL::ToUTF8String(*it); - if (viewMode == VIEWMODE_TYPE_FULLSCREEN) { - fullscreen = true; - break; - } else if (viewMode == VIEWMODE_TYPE_MAXIMIZED) { - break; + switch(viewMode[0]) { + case 'f': + if (viewMode == VIEWMODE_TYPE_FULLSCREEN) { + m_initialViewMode = viewMode; + m_currentViewMode = m_initialViewMode; + break; + } + break; + case 'm': + if (viewMode == VIEWMODE_TYPE_MAXIMIZED) { + m_initialViewMode = viewMode; + m_currentViewMode = m_initialViewMode; + break; + } + break; + case 'w': + if (viewMode == VIEWMODE_TYPE_WINDOWED) { + m_initialViewMode = viewMode; + m_currentViewMode = m_initialViewMode; + break; + } + break; + default: + break; } } +} - LogInfo("initializeWindowModes " << m_debugMode); -#if 1 - m_windowData->m_debugMode = FALSE; -#else - if(m_debugMode) { - m_windowData->m_debugMode = TRUE; - } - else { - m_windowData->m_debugMode = FALSE; - } -#endif - WindowData::CtxMenuItems ctxMenuItems; - - WindowData::CtxMenuItem ctxMenuBackword; - ctxMenuBackword.label = WRT_OPTION_LABEL_BACKWARD; - ctxMenuBackword.icon = WRT_OPTION_ICON_BACKWARD; - ctxMenuBackword.callback = backwardCallback; - ctxMenuBackword.data = this; - ctxMenuItems.push_back(ctxMenuBackword); - - WindowData::CtxMenuItem ctxMenuReload; - ctxMenuReload.label = WRT_OPTION_LABEL_RELOAD; - ctxMenuReload.icon = WRT_OPTION_ICON_RELOAD; - ctxMenuReload.callback = reloadCallback; - ctxMenuReload.data = this; - ctxMenuItems.push_back(ctxMenuReload); - - WindowData::CtxMenuItem ctxMenuForward; - ctxMenuForward.label = WRT_OPTION_LABEL_FORWARD; - ctxMenuForward.icon = WRT_OPTION_ICON_FORWARD; - ctxMenuForward.callback = forwardCallback; - ctxMenuForward.data = this; - ctxMenuItems.push_back(ctxMenuForward); - - m_windowData->setViewMode(name.c_str(), - fullscreen, - backbutton, - ctxMenuItems); -} - -void WrtClient::backButtonCallback(void* data, - Evas_Object * /*obj*/, - void * /*event_info*/) -{ - LogInfo("BackButtonCallback"); - Assert(data); +void WrtClient::setWindowInitialOrientation(void) +{ + Assert(m_windowData); + Assert(m_dao); - WrtClient* This = static_cast(data); + WidgetSettingScreenLock rotationValue = m_settingList->getRotationValue(); + if (rotationValue == Screen_Portrait) { + setWindowOrientation(OrientationAngle::Window::Portrait::PRIMARY); + } else if (rotationValue == Screen_Landscape) { + setWindowOrientation(OrientationAngle::Window::Landscape::PRIMARY); + } else if (rotationValue == Screen_AutoRotation) { + if (!AutoRotationSupport::setAutoRotation( + m_windowData->getEvasObject(Layer::WINDOW), + autoRotationCallback, + this)) + { + LogError("Fail to set auto rotation"); + } + } else { + setWindowOrientation(OrientationAngle::Window::Portrait::PRIMARY); + } +} - This->m_widget->Backward(); +void WrtClient::setWindowOrientation(int angle) +{ + Assert(m_windowData); + m_windowData->setOrientation(angle); } -void WrtClient::backwardCallback(void *data, - Evas_Object */*obj*/, - void */*event_info*/) +void WrtClient::unsetWindowOrientation(void) { - LogInfo("BackButtonCallback"); - Assert(data); + Assert(m_windowData); + Assert(m_dao); - WrtClient* This = static_cast(data); + WidgetSettingScreenLock rotationValue = m_settingList->getRotationValue(); + if (rotationValue == Screen_AutoRotation) { + AutoRotationSupport::unsetAutoRotation( + m_windowData->getEvasObject(Layer::WINDOW), + autoRotationCallback); + } +} - This->m_widget->Backward(); - This->m_windowData->initFullViewMode(); +void WrtClient::setEwkInitialOrientation(void) +{ + Assert(m_widget); + Assert(m_dao); + + WidgetSettingScreenLock rotationValue = m_settingList->getRotationValue(); + if (rotationValue == Screen_Portrait) { + ewk_view_orientation_send( + m_widget->GetCurrentWebview(), + OrientationAngle::W3C::Portrait::PRIMARY); + } else if (rotationValue == Screen_Landscape) { + ewk_view_orientation_send( + m_widget->GetCurrentWebview(), + OrientationAngle::W3C::Landscape::PRIMARY); + } else if (rotationValue == Screen_AutoRotation) { + ewk_view_orientation_send( + m_widget->GetCurrentWebview(), + OrientationAngle::W3C::Portrait::PRIMARY); + } else { + ewk_view_orientation_send( + m_widget->GetCurrentWebview(), + OrientationAngle::W3C::Portrait::PRIMARY); + } } -void WrtClient::reloadCallback(void *data, - Evas_Object */*obj*/, - void */*event_info*/) +void WrtClient::ExitCallback(void* data, + Evas_Object * /*obj*/, + void * /*event_info*/) { - LogInfo("reloadCallback"); + LogInfo("ExitCallback"); + Assert(data); WrtClient* This = static_cast(data); - This->m_widget->Reload(); - This->m_windowData->initFullViewMode(); + This->OnTerminate(); } -void WrtClient::forwardCallback(void *data, - Evas_Object */*obj*/, - void */*event_info*/) +void WrtClient::setCtxpopupItem(void) { - LogInfo("forwardCallback"); + WindowData::CtxpopupItemDataList data; + + // 1. share + WindowData::CtxpopupCallbackType shareCallback = + DPL::MakeDelegate(this, &WrtClient::ctxpopupShare); + WindowData::CtxpopupItemData shareData("Share", + std::string(), + shareCallback); + + // 2. reload + WindowData::CtxpopupCallbackType reloadCallback = + DPL::MakeDelegate(this, &WrtClient::ctxpopupReload); + WindowData::CtxpopupItemData reloadData("Reload", + std::string(), + reloadCallback); + + // 3. Open in browser + WindowData::CtxpopupCallbackType launchBrowserCallback = + DPL::MakeDelegate(this, &WrtClient::ctxpopupLaunchBrowser); + WindowData::CtxpopupItemData launchBrowserData("Open in browser", + std::string(), + launchBrowserCallback); + data.push_back(shareData); + data.push_back(reloadData); + data.push_back(launchBrowserData); + m_windowData->setCtxpopupItemData(data); +} - WrtClient* This = static_cast(data); +void WrtClient::ctxpopupShare(void) +{ + LogDebug("share"); +#ifdef X11 + const char* url = ewk_view_url_get(m_widget->GetCurrentWebview()); + if (!url) { + LogError("url is empty"); + return; + } + if (ClientModule::ServiceSupport::launchShareService( + elm_win_xwindow_get(m_windowData->getEvasObject(Layer::WINDOW)), + url)) + { + LogDebug("success"); + } else { + LogDebug("fail"); + } + evas_object_smart_callback_add(m_windowData->m_win, + "delete,request", + &WrtClient::ExitCallback, + this); +#endif +} - This->m_widget->Forward(); - This->m_windowData->initFullViewMode(); +void WrtClient::ctxpopupReload(void) +{ + LogDebug("reload"); + ewk_view_reload(m_widget->GetCurrentWebview()); } +void WrtClient::ctxpopupLaunchBrowser(void) +{ + LogDebug("launchBrowser"); +#ifdef X11 + const char* url = ewk_view_url_get(m_widget->GetCurrentWebview()); + if (!url) { + LogError("url is empty"); + return; + } + if (ClientModule::ServiceSupport::launchViewService( + elm_win_xwindow_get(m_windowData->getEvasObject(Layer::WINDOW)), + url)) + { + LogDebug("success"); + } else { + LogDebug("fail"); + } +#endif +} -void WrtClient::connectElmCallback() +void WrtClient::hwkeyCallback(const std::string& key) { - Assert(m_windowData); - Assert(m_dao); - if (m_dao->getWidgetType().appType == WrtDB::APP_TYPE_TIZENWEBAPP) { - WidgetSettings widgetSettings; - m_dao->getWidgetSettings(widgetSettings); - WidgetSettingList settings(widgetSettings); - if (settings.getBackButtonPresence() == BackButton_Enable) { - m_windowData->addFloatBackButtonCallback( - "clicked", - &WrtClient::backButtonCallback, - this); + if (m_settingList->getBackButtonPresence() == BackButton_Enable + || m_currentViewMode == VIEWMODE_TYPE_WINDOWED) + { + // windowed UX - hosted application + if (key == KeyName::BACK) { + if (m_isWebkitFullscreen) { + // FIXME!!! This method has not yet landed in the tizen 3.0 + // webkit-efl source tree + //ewk_view_fullscreen_exit(m_widget->GetCurrentWebview()); + } else { + m_widget->Backward(); + } + } else if (key == KeyName::MENU) { + // UX isn't confirmed + // m_windowData->showCtxpopup(); } - - WidgetSettingScreenLock rotationValue = settings.getRotationValue(); - if (rotationValue == Screen_Portrait) { - elm_win_rotation_with_resize_set(m_windowData->m_win, 0); - } else if (rotationValue == Screen_Landscape) { - elm_win_rotation_with_resize_set(m_windowData->m_win, 270); - } else { - elm_win_rotation_with_resize_set(m_windowData->m_win, 0); + } else { + // packaged application + if (key == KeyName::BACK) { + if (m_isFullscreenByPlatform) { + // FIXME!!! This method has not yet landed in the tizen 3.0 + // webkit-efl source tree + //ewk_view_fullscreen_exit(m_widget->GetCurrentWebview()); + } } } } -void WrtClient::setLayout(Evas_Object* newBuffer) { +void WrtClient::setLayout(Evas_Object* webview) +{ LogDebug("add new webkit buffer to window"); - Assert(newBuffer); - elm_object_content_set(m_windowData->m_conformant, newBuffer); - evas_object_show(newBuffer); - evas_object_focus_set(newBuffer, EINA_TRUE); + Assert(webview); + m_windowData->setWebview(webview); + evas_object_show(webview); + evas_object_show(m_windowData->getEvasObject(Layer::WINDOW)); } -void WrtClient::unsetLayout(Evas_Object* currentBuffer) { +void WrtClient::unsetLayout(Evas_Object* webview) +{ LogDebug("remove current webkit buffer from window"); - Assert(currentBuffer); - evas_object_hide(currentBuffer); - elm_object_content_unset(m_windowData->m_conformant); + Assert(webview); + evas_object_hide(webview); + m_windowData->unsetWebview(); } void WrtClient::shutdownStep() { LogDebug("Closing Wrt connection ..."); - if (m_initialized && m_widget) { + + if (m_widget && m_widgetState) { m_widgetState = WidgetState_Stopped; m_widget->Hide(); + // AutoRotation, focusCallback use m_widget pointer internally. + // It must be unset before m_widget is released. + m_submodeSupport->deinitialize(); + unsetWindowOrientation(); + m_windowData->smartCallbackDel(Layer::FOCUS, + "focused", + focusedCallback); + m_windowData->smartCallbackDel(Layer::FOCUS, + "unfocused", + unfocusedCallback); m_widget.reset(); - m_windowData.reset(); + ewk_context_delete(s_preparedEwkContext); WRT::CoreModuleSingleton::Instance().Terminate(); + } + if (m_initialized) { m_initialized = false; } + m_windowData.reset(); Quit(); } +void WrtClient::autoRotationCallback(void* data, Evas_Object* obj, void* /*event*/) +{ + LogDebug("entered"); + + Assert(data); + Assert(obj); + + WrtClient* This = static_cast(data); + This->autoRotationSetOrientation(obj); +} + +void WrtClient::focusedCallback(void* data, + Evas_Object* /*obj*/, + void* /*eventInfo*/) +{ + LogDebug("entered"); + Assert(data); + WrtClient* This = static_cast(data); + elm_object_focus_set(This->m_widget->GetCurrentWebview(), EINA_TRUE); +} + +void WrtClient::unfocusedCallback(void* data, + Evas_Object* /*obj*/, + void* /*eventInfo*/) +{ + LogDebug("entered"); + Assert(data); + WrtClient* This = static_cast(data); + elm_object_focus_set(This->m_widget->GetCurrentWebview(), EINA_FALSE); +} + +void WrtClient::autoRotationSetOrientation(Evas_Object* obj) +{ + LogDebug("entered"); + Assert(obj); + + AutoRotationSupport::setOrientation(obj, m_widget->GetCurrentWebview(), + (m_splashScreen) ? m_splashScreen.get(): NULL); +} + int WrtClient::languageChangedCallback(void *data) { LogDebug("Language Changed"); - if(!data) + if (!data) { return 0; + } WrtClient* wrtClient = static_cast(data); - if(!(wrtClient->m_dao)) + if (!(wrtClient->m_dao)) { return 0; + } // reset function fetches system locales and recreates language tags LanguageTagsProviderSingleton::Instance().resetLanguageTags(); // widget default locales are added to language tags below DPL::OptionalString defloc = wrtClient->m_dao->getDefaultlocale(); - if(!defloc.IsNull()) - { - LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(*defloc); + if (!defloc.IsNull()) { + LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales( + *defloc); } if (wrtClient->m_launched && - wrtClient->m_widgetState != WidgetState_Stopped) { + wrtClient->m_widgetState != WidgetState_Stopped) + { wrtClient->m_widget->ReloadStartPage(); } return 0; @@ -729,13 +915,208 @@ 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 (fd == -1) + { + LogDebug("ECORE_FD_GET"); + exit(-1); + } + + if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR)) + { + LogDebug("ECORE_FD_ERROR"); + close(fd); + exit(-1); + } + + 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!"); + free(pkt); + exit(-1); + } + + LogDebug("recv_ret : " << recv_ret << ", pkt->len : " << pkt->len); + ecore_main_fd_handler_del(handler); + process_pool_launchpad_main_loop(pkt, app_argv[0], &app_argc, &app_argv); + free(pkt); + } + ecore_main_loop_quit(); + } + + return ECORE_CALLBACK_CANCEL; +} + +static void vconf_changed_handler(keynode_t* /*key*/, void* /*data*/) +{ + LogDebug("VCONFKEY_LANGSET vconf-key was changed!"); + + // When system language is changed, the candidate process will be created again. + exit(-1); +} + +void set_env() +{ +#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; + +#ifndef X11 + // Mesa does a bad job detecting the correct EGL + // platform to use, and ends up assuming that the + // wrt-client is using X + setenv("EGL_PLATFORM", "wayland", 1); +#endif + UNHANDLED_EXCEPTION_HANDLER_BEGIN { ADD_PROFILING_POINT("main-entered", "point"); + // Set log tagging + DPL::Log::LogSystemSingleton::Instance().SetTag("WRT"); + + // Set environment variables + set_env(); + + if (argc > 1 && argv[1] != NULL && !strcmp(argv[1], "-d")) + { + LogDebug("Entered dummy process mode"); + sprintf(argv[0], "%s ", + DUMMY_PROCESS_PATH); + + // Set 'root' home directory + setenv(HOME, ROOT_HOME_PATH, 1); + + LogDebug("Prepare ewk_context"); + appcore_set_i18n("wrt-client", NULL); + ewk_set_arguments(argc, argv); + setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1); + s_preparedEwkContext = ewk_context_new_with_injected_bundle_path(BUNDLE_PATH); + + if (s_preparedEwkContext == NULL) + { + LogDebug("Creating webkit context was failed!"); + exit(-1); + } + + int client_fd = __connect_process_pool_server(); + + if (client_fd == -1) + { + LogDebug("Connecting process_pool_server was failed!"); + exit(-1); + } + + // register language changed callback + vconf_notify_key_changed(VCONFKEY_LANGSET, vconf_changed_handler, NULL); + + LogDebug("Prepare window_data"); + // Temporarily change HOME path to app + // This change is needed for getting elementary profile + // /opt/home/app/.elementary/config/mobile/base.cfg + const char* backupEnv = getenv(HOME); + if (!backupEnv) { + // If getenv return "NULL", set empty string + backupEnv = ""; + } + setenv(HOME, APP_HOME_PATH, 1); + LogDebug("elm_init()"); + elm_init(argc, argv); + setenv(HOME, backupEnv, 1); + + LogDebug("WindowData()"); + s_preparedWindowData = new WindowData(static_cast(getpid())); + + Ecore_Fd_Handler* fd_handler = ecore_main_fd_handler_add(client_fd, + (Ecore_Fd_Handler_Flags)(ECORE_FD_READ|ECORE_FD_ERROR), + proces_pool_fd_handler, NULL, NULL, NULL); + + if (fd_handler == NULL) + { + LogDebug("fd_handler is NULL"); + exit(-1); + } + + setpriority(PRIO_PROCESS, 0, 0); + + LogDebug("ecore_main_loop_begin()"); + ecore_main_loop_begin(); + LogDebug("ecore_main_loop_begin()_end"); + + // deregister language changed callback + vconf_ignore_key_changed(VCONFKEY_LANGSET, vconf_changed_handler); + + std::string tizenId = + ClientModule::CommandLineParser::getTizenId(argc, argv); + ewk_context_message_post_to_injected_bundle( + s_preparedEwkContext, + MESSAGE_NAME_INITIALIZE, + tizenId.c_str()); + + } + else + { + // This code is to fork a web process without exec. + std::string tizenId = + ClientModule::CommandLineParser::getTizenId(argc, argv); + + if (!tizenId.empty()) { + if (UID_ROOT == getuid()) { + // Drop root permission + // Only launch web application by console command case has root permission + if (!ClientModule::SecuritySupport::setAppPrivilege(tizenId)) { + LogError("Fail to set app privilege : [" << tizenId << "]"); + exit(-1); + } + } + + LogDebug("Launching by fork mode"); + // Language env setup + appcore_set_i18n("wrt-client", NULL); + ewk_set_arguments(argc, argv); + setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1); + s_preparedEwkContext = ewk_context_new_with_injected_bundle_path( + BUNDLE_PATH); + + if (s_preparedEwkContext == NULL) + { + LogDebug("Creating webkit context was failed!"); + Wrt::Popup::PopupInvoker().showInfo("Error", "Creating webkit context was failed.", "OK"); + exit(-1); + } + + // plugin init + ewk_context_message_post_to_injected_bundle( + s_preparedEwkContext, + MESSAGE_NAME_INITIALIZE, + tizenId.c_str()); + } + } + // Output on stdout will be flushed after every newline character, // even if it is redirected to a pipe. This is useful for running // from a script and parsing output. @@ -744,27 +1125,7 @@ int main(int argc, // the output may not be flushed). setlinebuf(stdout); - // 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 log tagging - DPL::Log::LogSystemSingleton::Instance().SetTag("WRT-CLIENT"); - - WrtClient app(argc, argv); + WrtClient app(app_argc, app_argv); ADD_PROFILING_POINT("Before appExec", "point"); int ret = app.Exec();