2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 #include "wrt-client.h"
20 #include <dpl/log/log.h>
21 #include <dpl/optional_typedefs.h>
22 #include <common/application_data.h>
23 #include <core_module.h>
24 #include <global_logic.h>
25 #include <widget_model.h>
26 #include <widget_localize_model.h>
27 #include <localization_setting.h>
28 #include <widget_deserialize_model.h>
29 #include <launch_user_data.h>
32 //W3C PACKAGING enviroment variable name
33 #define W3C_DEBUG_ENV_VARIABLE "DEBUG_LOAD_FINISH"
35 // window signal callback
36 const char *EDJE_SHOW_BACKWARD_SIGNAL = "show,backward,signal";
37 const std::string VIEWMODE_TYPE_FULLSCREEN = "fullscreen";
38 const std::string VIEWMODE_TYPE_MAXIMIZED = "maximized";
40 WrtClient::WrtClient(int argc, char **argv) :
41 Application(argc, argv, "wrt-client", false),
42 DPL::TaskDecl<WrtClient>(this),
45 m_initializing(false),
50 m_returnStatus(ReturnStatus::Succeeded),
51 m_widgetState(WidgetState::WidgetState_Stopped)
54 LogDebug("App Created");
57 WrtClient::~WrtClient()
59 LogDebug("App Finished");
62 WrtClient::ReturnStatus::Type WrtClient::getReturnStatus() const
64 return m_returnStatus;
67 void WrtClient::OnStop()
69 LogInfo("Stopping Dummy Client");
73 void WrtClient::OnCreate()
79 void WrtClient::OnResume()
81 if (m_widgetState != WidgetState_Suspended) {
82 LogWarning("Widget is not suspended, resuming was skipped");
86 evas_object_focus_set(m_widget->GetCurrentWebview(), EINA_TRUE);
87 m_widgetState = WidgetState_Running;
91 void WrtClient::OnPause()
93 if (m_widgetState != WidgetState_Running) {
94 LogWarning("Widget is not running to be suspended");
98 m_widgetState = WidgetState_Suspended;
101 void WrtClient::OnReset(bundle *b)
104 // bundle argument is freed after OnReset() is returned
105 // So bundle duplication is needed
106 ApplicationDataSingleton::Instance().setBundle(bundle_dup(b));
108 if (true == m_initializing) {
109 LogDebug("can not handle reset event");
112 if (true == m_launched) {
113 if (m_widgetState == WidgetState_Stopped) {
114 LogError("Widget is not running to be reset");
118 m_windowData->emitSignalForUserLayout(EDJE_SHOW_BACKWARD_SIGNAL, "");
119 elm_win_raise(m_windowData->m_win);
120 evas_object_focus_set(m_widget->GetCurrentWebview(), EINA_TRUE);
121 m_widgetState = WidgetState_Running;
123 if (true == checkArgument())
134 void WrtClient::OnTerminate()
136 LogDebug("Wrt Shutdown now");
140 void WrtClient::showHelpAndQuit()
142 printf("Usage: wrt-client [OPTION]... [WIDGET: ID]...\n"
144 "Mandatory arguments to long options are mandatory for short "
146 " -h, --help show this help\n"
148 "launch widget with given ID\n"
154 bool WrtClient::checkArgument()
156 LogInfo("checkArgument");
158 std::string arg = m_argv[0];
164 if (arg.find("wrt-client") != std::string::npos)
172 if (arg == "-h" || arg == "--help") {
175 } else if (arg == "-l" || arg == "--launch") {
179 m_handle = atoi(m_argv[2]);
184 size_t pos = arg.find_last_of('/');
186 if (pos != std::string::npos) {
187 arg = arg.erase(0, pos + 1);
190 // Launch widget based on application basename
191 if (sscanf(arg.c_str(), "%i", &m_handle) != 1) {
192 printf("failed: invalid widget handle\n");
196 LogDebug("Widget Id: " << m_handle << " (" << arg << ")");
202 void WrtClient::setStep()
206 AddStep(&WrtClient::initStep);
208 setSdkLauncherDebugData();
210 AddStep(&WrtClient::launchStep);
211 AddStep(&WrtClient::shutdownStep);
213 m_initializing = true;
215 DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(NextStepEvent());
218 void WrtClient::setSdkLauncherDebugData()
220 LogDebug("setSdkLauncherDebugData");
222 /* check bundle from sdk launcher */
223 bundle *bundleFromSdkLauncher;
224 bundleFromSdkLauncher = bundle_import_from_argv(m_argc, m_argv);
225 const char *bundle_debug = bundle_get_val(bundleFromSdkLauncher, "debug");
226 const char *bundle_pid = bundle_get_val(bundleFromSdkLauncher, "pid");
227 if (bundle_debug != NULL && bundle_pid != NULL) {
228 if (strcmp(bundle_debug, "true") == 0) {
230 m_sdkLauncherPid = atoi(bundle_pid);
237 bool WrtClient::checkDebugMode(WidgetModel* model, SDKDebugData* debugData)
239 LogError("Checking for debug mode");
240 Assert(model && "Passed widget model is NULL!");
242 bool debugMode = debugData->debugMode;
244 LogInfo("[DEBUG_MODE] Widget is launched in " <<
245 (debugMode ? "DEBUG" : "RETAIL") <<
248 if (debugMode == true) {
249 // In WAC widget, only test widgets can use web inspector.
251 // every launched widgets as debug mode can use it.
252 if (model->Type.Get().appType ==
253 WrtDB::APP_TYPE_WAC20)
256 GlobalLogicSingleton::Instance().GetGlobalModel()
257 ->DeveloperMode.Get();
258 //This code will be activated
259 //after WAC test certificate is used by SDK
260 //bool isTestWidget = view->m_widgetModel->IsTestWidget.Get();
263 // LogInfo("This is not WAC Test Widget");
266 if (!developerMode) {
267 LogInfo("This is not WAC Developer Mode");
275 void WrtClient::OnEventReceived(const NextStepEvent& /*event*/)
277 LogDebug("Executing next step");
281 void WrtClient::initStep()
284 if (WRT::CoreModuleSingleton::Instance().Init()) {
285 m_initialized = true;
287 m_returnStatus = ReturnStatus::Failed;
288 SwitchToStep(&WrtClient::shutdownStep);
290 DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
294 void WrtClient::localizeWidgetModel() {
296 WRT::WidgetModelPtr model = m_widget->GetModel();
298 Domain::localizeWidgetModel(model);
299 model->RunningName.Set(model->Name.Get());
300 model->RunningIcon.Set(model->Icon.Get());
301 model->RunningStartURL.Set(model->StartURL.Get());
302 model->RunningShortName.Set(model->ShortName.Get());
303 model->RunningDescription.Set(model->Description.Get());
304 model->RunningLicense.Set(model->License.Get());
305 model->RunningLicenseHref.Set(model->LicenseHref.Get());
306 model->RunningStartFileInfo.Set(
307 model->StartFileInfo.Get());
310 bool WrtClient::checkWACTestCertififedWidget()
312 // WAC Waikiki Beta Release Core Specification: Widget Runtime
315 // WR-4710 The WRT MUST enable debug functions only for WAC test widgets
316 // i.e. the functions must not be usable for normal WAC widgets, even when
317 // a WAC test widget is executing.
318 ADD_PROFILING_POINT("DeveloperModeCheck", "start");
320 WRT::WidgetModelPtr model = m_widget->GetModel();
323 // A widget signed with a WAC-issued test certificate as described in
326 bool developerWidget = model->IsTestWidget.Get();
328 GlobalLogicSingleton::Instance().GetGlobalModel()->DeveloperMode.Get();
330 LogDebug("Is WAC test widget: " << developerWidget);
331 LogDebug("Is developer Mode: " << developerMode);
333 if (developerWidget) {
336 LogError("WAC test certified developer widget is needed for " <<
340 //TODO: WR-4660 (show popup about developer widget
342 LogInfo("POPUP: THIS IS TEST WIDGET!");
345 ADD_PROFILING_POINT("DeveloperModeCheck", "stop");
349 void WrtClient::loadFinishCallback(bool success, void* data)
351 WrtClient* wrtClient = static_cast<WrtClient*>(data);
352 SDKDebugData* debug = new SDKDebugData;
353 debug->debugMode = wrtClient->m_debugMode;
354 debug->pid = new unsigned long(getpid());
356 LogInfo("Post result of launch");
358 // Start inspector server, if current mode is debugger mode.
359 // In the WK2 case, ewk_view_inspector_server_start should
360 // be called after WebProcess is created.
361 if (wrtClient->checkDebugMode(
362 wrtClient->m_widget->GetModel().get(), debug))
365 ewk_view_inspector_server_start(
366 wrtClient->m_widget->GetCurrentWebview(), 0);
367 if (debug->portnum == 0) {
368 LogWarning("Failed to get portnum");
370 LogInfo("Assigned port number for inspector : "
374 LogDebug("Debug mode is disabled");
377 //w3c packaging test debug (message on 4>)
378 const char * makeScreen = getenv(W3C_DEBUG_ENV_VARIABLE);
379 if(makeScreen != NULL && strcmp(makeScreen, "1") == 0)
381 FILE* doutput = fdopen(4, "w");
382 fprintf(doutput,"didFinishLoadForFrameCallback: ready\n");
387 LogDebug("Launch succesfull");
389 wrtClient->m_launched = true;
390 wrtClient->m_initializing = false;
392 printf("launched\n");
397 wrtClient->m_returnStatus = ReturnStatus::Failed;
399 wrtClient->DPL::Event::ControllerEventHandler<NextStepEvent>::
400 PostEvent(NextStepEvent());
405 LogDebug("Send RT signal to wrt-launcher(pid: "
406 << wrtClient->m_sdkLauncherPid << ", status: " << success);
408 /* send real time signal with result to wrt-launcher */
411 LogDebug("userData->portnum : " << debug->portnum);
412 sv.sival_int = debug->portnum;
418 sigqueue(wrtClient->m_sdkLauncherPid, SIGRTMIN, sv);
421 ApplicationDataSingleton::Instance().freeBundle();
423 LogDebug("Cleaning wrtClient launch resources...");
428 void WrtClient::progressFinishCallback(void* data)
430 WrtClient* wrtClient = static_cast<WrtClient*>(data);
431 wrtClient->m_splashScreen->stopSplashScreen();
434 void WrtClient::windowCloseCallback(void* data)
436 LogDebug("window close called, terminating app");
437 WrtClient* wrtClient = static_cast<WrtClient*>(data);
438 wrtClient->SwitchToStep(&WrtClient::shutdownStep);
439 wrtClient->DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
443 void WrtClient::webCrashCallback(void* data)
445 LogDebug("webProcess crashed");
446 WrtClient* wrtClient = static_cast<WrtClient*>(data);
447 wrtClient->SwitchToStep(&WrtClient::shutdownStep);
448 wrtClient->DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
452 void WrtClient::launchStep()
454 LogDebug("Launching widget ...");
457 WRT::CoreModuleSingleton::Instance().getRunnableWidgetObject(m_handle);
459 LogError("RunnableWidgetObject is NULL, stop launchStep");
460 DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
465 if (m_widgetState == WidgetState_Running) {
466 LogWarning("Widget already running, stop launchStep");
467 DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
472 if (m_widgetState == WidgetState_Authorizing) {
473 LogWarning("Widget already authorizing, stop launchStep");
474 DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
479 // Widget is not running, localized data can be updated
480 localizeWidgetModel();
481 LocalizationSetting::SetLanguageChangedCallback(
482 languageChangedCallback, this);
484 ADD_PROFILING_POINT("CreateWindow", "start");
485 m_windowData.reset(new WindowData(static_cast<unsigned long>(getpid())));
486 ADD_PROFILING_POINT("CreateWindow", "stop");
488 WRT::UserCallbacksPtr cbs(new WRT::UserCallbacks);
489 m_splashScreen.reset(
490 new SplashScreenSupport(m_windowData->m_win));
491 if (m_splashScreen->createSplashScreen(m_handle)) {
492 m_splashScreen->startSplashScreen();
493 cbs->progressFinish = progressFinishCallback;
495 DPL::OptionalString startUrl = m_widget->GetModel()->RunningStartURL.Get();
496 m_widget->PrepareView(DPL::ToUTF8String(*startUrl),
497 m_windowData->m_win);
498 //you can't show window with splash screen before PrepareView
499 //ewk_view_add_with_context() in viewLogic breaks window
500 evas_object_show(m_windowData->m_win);
501 initializeWindowModes();
502 connectElmCallback();
504 if (!checkWACTestCertififedWidget())
506 LogWarning("WAC Certificate failed, stop launchStep");
510 m_widgetState = WidgetState_Authorizing;
511 if (!m_widget->CheckBeforeLaunch()) {
512 LogError("CheckBeforeLaunch failed, stop launchStep");
513 DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
517 LogInfo("Widget launch accepted. Entering running state");
518 m_widgetState = WidgetState_Running;
520 cbs->loadFinish = loadFinishCallback;
521 cbs->bufferSet = setLayout;
522 cbs->bufferUnset = unsetLayout;
523 cbs->windowClose = windowCloseCallback;
524 cbs->webCrash = webCrashCallback;
526 m_widget->SetUserCallbacks(cbs, this);
528 m_windowData->emitSignalForUserLayout(EDJE_SHOW_BACKWARD_SIGNAL, "");
531 void WrtClient::initializeWindowModes()
533 Assert(m_windowData);
534 WRT::WidgetModelPtr model = m_widget->GetModel();
536 auto windowModes = model->WindowModes.Get();
537 bool fullscreen = false;
538 FOREACH(it, windowModes)
540 std::string viewMode = DPL::ToUTF8String(*it);
541 if (viewMode == VIEWMODE_TYPE_FULLSCREEN) {
544 } else if (viewMode == VIEWMODE_TYPE_MAXIMIZED) {
548 bool indicator = true;
549 bool backbutton = false;
550 if (model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
552 = (model->SettingList.Get().getIndicatorPresence()
553 == Indicator_Enable);
555 = (model->SettingList.Get().getBackButtonPresence()
556 == BackButton_Enable);
560 std::string name = "";
561 if (!(model->Name.Get().IsNull())) {
562 name = DPL::ToUTF8String(*(model->Name.Get()));
564 m_windowData->setViewModeMaximized(
565 name.c_str(), indicator, backbutton);
567 m_windowData->setViewModeFullScreen(
568 indicator, backbutton);
572 void WrtClient::backButtonCallback(void* data,
573 Evas_Object * /*obj*/,
574 void * /*event_info*/)
576 LogInfo("BackButtonCallback");
579 WrtClient* This = static_cast<WrtClient*>(data);
581 This->m_widget->GoBack();
584 void WrtClient::connectElmCallback()
586 Assert(m_windowData);
587 WRT::WidgetModelPtr model = m_widget->GetModel();
589 if (model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
590 if (model->SettingList.Get().getBackButtonPresence() ==
593 m_windowData->addFloatBackButtonCallback(
595 &WrtClient::backButtonCallback,
599 WidgetSettingScreenLock rotationValue =
600 model->SettingList.Get().getRotationValue();
601 if (rotationValue == Screen_Portrait) {
602 elm_win_rotation_with_resize_set(m_windowData->m_win, 0);
603 } else if (rotationValue == Screen_Landscape) {
604 elm_win_rotation_with_resize_set(m_windowData->m_win, 270);
606 elm_win_rotation_with_resize_set(m_windowData->m_win, 0);
611 void WrtClient::setLayout(Evas_Object* newBuffer, void* data) {
612 LogDebug("add new webkit buffer to window");
615 WrtClient* wrtClient = static_cast<WrtClient*>(data);
616 elm_object_content_set(wrtClient->m_windowData->m_conformant, newBuffer);
617 evas_object_show(newBuffer);
618 evas_object_focus_set(newBuffer, EINA_TRUE);
621 void WrtClient::unsetLayout(Evas_Object* currentBuffer, void* data) {
622 LogDebug("remove current webkit buffer from window");
624 Assert(currentBuffer);
625 WrtClient* wrtClient = static_cast<WrtClient*>(data);
626 evas_object_hide(currentBuffer);
627 elm_object_content_unset(wrtClient->m_windowData->m_conformant);
630 void WrtClient::shutdownStep()
632 LogDebug("Closing Wrt connection ...");
633 if (m_initialized && m_widget) {
634 m_widgetState = WidgetState_Stopped;
637 m_windowData.reset();
638 WRT::CoreModuleSingleton::Instance().Terminate();
639 m_initialized = false;
644 int WrtClient::languageChangedCallback(void *data)
646 LogDebug("Language Changed");
647 WrtClient* wrtClient = static_cast<WrtClient*>(data);
648 WRT::WidgetModelPtr model = wrtClient->m_widget->GetModel();
650 LocalizationSetting::SetLocalization();
652 LanguageTagsList tags = LocalizationUtils::GetUserAgentLanguageTags();
653 if (model->LanguageTags.Get() != tags) {
654 // update localized data
655 wrtClient->localizeWidgetModel();
657 if (true == wrtClient->m_launched &&
658 wrtClient->m_widgetState != WidgetState_Stopped) {
659 wrtClient->m_widget->Reset();
668 ADD_PROFILING_POINT("main-entered", "point");
670 // Output on stdout will be flushed after every newline character,
671 // even if it is redirected to a pipe. This is useful for running
672 // from a script and parsing output.
673 // (Standard behavior of stdlib is to use full buffering when
674 // redirected to a pipe, which means even after an end of line
675 // the output may not be flushed).
678 // set evas backend type
679 if (!getenv("ELM_ENGINE")) {
680 if (setenv("ELM_ENGINE", "gl", 1)) {
681 LogDebug("Enable backend");
684 setenv("COREGL_FASTPATH", "1", 1);
686 DPL::Log::LogSystemSingleton::Instance().SetTag("WRT-CLIENT");
688 WrtClient app(argc, argv);
689 int ret = app.Exec();
690 LogDebug("App returned: " << ret);
691 ret = app.getReturnStatus();
692 LogDebug("WrtClient returned: " << ret);