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 WrtClient::WrtClient(int argc, char **argv) :
36 Application(argc, argv, "wrt-client", false),
37 DPL::TaskDecl<WrtClient>(this),
40 m_initializing(false),
45 m_returnStatus(ReturnStatus::Succeeded),
46 m_widgetState(WidgetState::WidgetState_Stopped)
49 LogDebug("App Created");
52 WrtClient::~WrtClient()
54 LogDebug("App Finished");
57 WrtClient::ReturnStatus::Type WrtClient::getReturnStatus() const
59 return m_returnStatus;
62 void WrtClient::OnStop()
64 LogInfo("Stopping Dummy Client");
68 void WrtClient::OnCreate()
74 void WrtClient::OnResume()
76 if (m_widgetState != WidgetState_Suspended) {
77 LogWarning("Widget is not suspended, resuming was skipped");
81 m_widgetState = WidgetState_Running;
85 void WrtClient::OnPause()
87 if (m_widgetState != WidgetState_Running) {
88 LogWarning("Widget is not running to be suspended");
92 m_widgetState = WidgetState_Suspended;
95 void WrtClient::OnReset(bundle *b)
98 // bundle argument is freed after OnReset() is returned
99 // So bundle duplication is needed
100 ApplicationDataSingleton::Instance().setBundle(bundle_dup(b));
102 if (true == m_initializing) {
103 LogDebug("can not handle reset event");
106 if (true == m_launched) {
107 if (m_widgetState == WidgetState_Stopped) {
108 LogError("Widget is not running to be reset");
112 m_widgetState = WidgetState_Running;
114 if (true == checkArgument())
125 void WrtClient::OnTerminate()
127 LogDebug("Wrt Shutdown now");
131 void WrtClient::showHelpAndQuit()
133 printf("Usage: wrt-client [OPTION]... [WIDGET: ID]...\n"
135 "Mandatory arguments to long options are mandatory for short "
137 " -h, --help show this help\n"
139 "launch widget with given ID\n"
145 bool WrtClient::checkArgument()
147 LogInfo("checkArgument");
149 std::string arg = m_argv[0];
155 if (arg.find("wrt-client") != std::string::npos)
163 if (arg == "-h" || arg == "--help") {
166 } else if (arg == "-l" || arg == "--launch") {
170 m_handle = atoi(m_argv[2]);
175 size_t pos = arg.find_last_of('/');
177 if (pos != std::string::npos) {
178 arg = arg.erase(0, pos + 1);
181 // Launch widget based on application basename
182 if (sscanf(arg.c_str(), "%i", &m_handle) != 1) {
183 printf("failed: invalid widget handle\n");
187 LogDebug("Widget Id: " << m_handle << " (" << arg << ")");
193 void WrtClient::setStep()
197 AddStep(&WrtClient::initStep);
199 setSdkLauncherDebugData();
201 AddStep(&WrtClient::launchStep);
202 AddStep(&WrtClient::shutdownStep);
204 m_initializing = true;
206 DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(NextStepEvent());
209 void WrtClient::setSdkLauncherDebugData()
211 LogDebug("setSdkLauncherDebugData");
213 /* check bundle from sdk launcher */
214 bundle *bundleFromSdkLauncher;
215 bundleFromSdkLauncher = bundle_import_from_argv(m_argc, m_argv);
216 const char *bundle_debug = bundle_get_val(bundleFromSdkLauncher, "debug");
217 const char *bundle_pid = bundle_get_val(bundleFromSdkLauncher, "pid");
218 if (bundle_debug != NULL && bundle_pid != NULL) {
219 if (strcmp(bundle_debug, "true") == 0) {
221 m_sdkLauncherPid = atoi(bundle_pid);
228 bool WrtClient::checkDebugMode(WidgetModel* model, SDKDebugData* debugData)
230 LogError("Checking for debug mode");
231 Assert(model && "Passed widget model is NULL!");
233 bool debugMode = debugData->debugMode;
235 LogInfo("[DEBUG_MODE] Widget is launched in " <<
236 (debugMode ? "DEBUG" : "RETAIL") <<
239 if (debugMode == true) {
240 // In WAC widget, only test widgets can use web inspector.
242 // every launched widgets as debug mode can use it.
243 if (model->Type.Get().appType ==
244 WrtDB::APP_TYPE_WAC20)
247 GlobalLogicSingleton::Instance().GetGlobalModel()
248 ->DeveloperMode.Get();
249 //This code will be activated
250 //after WAC test certificate is used by SDK
251 //bool isTestWidget = view->m_widgetModel->IsTestWidget.Get();
254 // LogInfo("This is not WAC Test Widget");
257 if (!developerMode) {
258 LogInfo("This is not WAC Developer Mode");
266 void WrtClient::OnEventReceived(const NextStepEvent& /*event*/)
268 LogDebug("Executing next step");
272 void WrtClient::initStep()
275 if (WRT::CoreModuleSingleton::Instance().Init()) {
276 m_initialized = true;
278 m_returnStatus = ReturnStatus::Failed;
279 SwitchToStep(&WrtClient::shutdownStep);
281 DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
285 void WrtClient::localizeWidgetModel() {
287 WRT::WidgetModelPtr model = m_widget->GetModel();
289 Domain::localizeWidgetModel(model);
290 model->RunningName.Set(model->Name.Get());
291 model->RunningIcon.Set(model->Icon.Get());
292 model->RunningStartURL.Set(model->StartURL.Get());
293 model->RunningShortName.Set(model->ShortName.Get());
294 model->RunningDescription.Set(model->Description.Get());
295 model->RunningLicense.Set(model->License.Get());
296 model->RunningLicenseHref.Set(model->LicenseHref.Get());
297 model->RunningStartFileInfo.Set(
298 model->StartFileInfo.Get());
301 bool WrtClient::checkWACTestCertififedWidget()
303 // WAC Waikiki Beta Release Core Specification: Widget Runtime
306 // WR-4710 The WRT MUST enable debug functions only for WAC test widgets
307 // i.e. the functions must not be usable for normal WAC widgets, even when
308 // a WAC test widget is executing.
309 ADD_PROFILING_POINT("DeveloperModeCheck", "start");
311 WRT::WidgetModelPtr model = m_widget->GetModel();
314 // A widget signed with a WAC-issued test certificate as described in
317 bool developerWidget = model->IsTestWidget.Get();
319 GlobalLogicSingleton::Instance().GetGlobalModel()->DeveloperMode.Get();
321 LogDebug("Is WAC test widget: " << developerWidget);
322 LogDebug("Is developer Mode: " << developerMode);
324 if (developerWidget) {
327 LogError("WAC test certified developer widget is needed for " <<
331 //TODO: WR-4660 (show popup about developer widget
333 LogInfo("POPUP: THIS IS TEST WIDGET!");
336 ADD_PROFILING_POINT("DeveloperModeCheck", "stop");
340 void WrtClient::loadFinishCallback(bool success, void* data)
342 WrtClient* wrtClient = static_cast<WrtClient*>(data);
343 SDKDebugData* debug = new SDKDebugData;
344 debug->debugMode = wrtClient->m_debugMode;
345 debug->pid = new unsigned long(getpid());
347 LogInfo("Post result of launch");
349 // Start inspector server, if current mode is debugger mode.
350 // In the WK2 case, ewk_view_inspector_server_start should
351 // be called after WebProcess is created.
352 if (wrtClient->checkDebugMode(
353 wrtClient->m_widget->GetModel().get(), debug))
356 ewk_view_inspector_server_start(
357 wrtClient->m_widget->GetCurrentWebview(), 0);
358 if (debug->portnum == 0) {
359 LogWarning("Failed to get portnum");
361 LogInfo("Assigned port number for inspector : "
365 LogDebug("Debug mode is disabled");
368 //w3c packaging test debug (message on 4>)
369 const char * makeScreen = getenv(W3C_DEBUG_ENV_VARIABLE);
370 if(makeScreen != NULL && strcmp(makeScreen, "1") == 0)
372 FILE* doutput = fdopen(4, "w");
373 fprintf(doutput,"didFinishLoadForFrameCallback: ready\n");
378 LogDebug("Launch succesfull");
380 wrtClient->m_launched = true;
381 wrtClient->m_initializing = false;
383 printf("launched\n");
388 wrtClient->m_returnStatus = ReturnStatus::Failed;
390 wrtClient->DPL::Event::ControllerEventHandler<NextStepEvent>::
391 PostEvent(NextStepEvent());
396 LogDebug("Send RT signal to wrt-launcher(pid: "
397 << wrtClient->m_sdkLauncherPid << ", status: " << success);
399 /* send real time signal with result to wrt-launcher */
402 LogDebug("userData->portnum : " << debug->portnum);
403 sv.sival_int = debug->portnum;
409 sigqueue(wrtClient->m_sdkLauncherPid, SIGRTMIN, sv);
412 ApplicationDataSingleton::Instance().freeBundle();
414 LogDebug("Cleaning wrtClient launch resources...");
419 void WrtClient::launchStep()
421 LogDebug("Launching widget ...");
424 WRT::CoreModuleSingleton::Instance().getRunnableWidgetObject(m_handle);
426 LogError("RunnableWidgetObject is NULL, stop launchStep");
427 DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
432 if (m_widgetState == WidgetState_Running) {
433 LogWarning("Widget already running, stop launchStep");
434 DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
439 if (m_widgetState == WidgetState_Authorizing) {
440 LogWarning("Widget already authorizing, stop launchStep");
441 DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
446 // Widget is not running, localized data can be updated
447 localizeWidgetModel();
448 LocalizationSetting::SetLanguageChangedCallback(
449 languageChangedCallback, this);
451 if (!checkWACTestCertififedWidget())
453 LogWarning("WAC Certificate failed, stop launchStep");
457 m_widgetState = WidgetState_Authorizing;
458 if (!m_widget->CheckBeforeLaunch()) {
459 LogError("CheckBeforeLaunch failed, stop launchStep");
460 DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
464 LogInfo("Widget launch accepted. Entering running state");
465 DPL::OptionalString startUrl = m_widget->GetModel()->RunningStartURL.Get();
466 m_widgetState = WidgetState_Running;
467 m_widget->PrepareView(DPL::ToUTF8String(*startUrl), NULL);
469 m_cbs.reset(new WRT::UserCallbacks);
470 m_cbs->loadFinish = loadFinishCallback;
471 m_cbs->resume = NULL;
472 m_cbs->suspend = NULL;
475 m_widget->SetUserCallbacks(m_cbs, this);
479 void WrtClient::shutdownStep()
481 LogDebug("Closing Wrt connection ...");
482 if (m_initialized && m_widget) {
483 m_widgetState = WidgetState_Stopped;
486 WRT::CoreModuleSingleton::Instance().Terminate();
487 m_initialized = false;
492 int WrtClient::languageChangedCallback(void *data)
494 LogDebug("Language Changed");
495 WrtClient* wrtClient = static_cast<WrtClient*>(data);
496 WRT::WidgetModelPtr model = wrtClient->m_widget->GetModel();
498 LocalizationSetting::SetLocalization();
500 LanguageTagsList tags = LocalizationUtils::GetUserAgentLanguageTags();
501 if (model->LanguageTags.Get() != tags) {
502 // update localized data
503 wrtClient->localizeWidgetModel();
505 if (true == wrtClient->m_launched &&
506 wrtClient->m_widgetState != WidgetState_Stopped) {
507 wrtClient->m_widget->Reset();
516 ADD_PROFILING_POINT("main-entered", "point");
518 // Output on stdout will be flushed after every newline character,
519 // even if it is redirected to a pipe. This is useful for running
520 // from a script and parsing output.
521 // (Standard behavior of stdlib is to use full buffering when
522 // redirected to a pipe, which means even after an end of line
523 // the output may not be flushed).
526 // set evas backend type
527 if (!getenv("ELM_ENGINE")) {
528 if (setenv("ELM_ENGINE", "gl", 1)) {
529 LogDebug("Enable backend");
534 DPL::Log::LogSystemSingleton::Instance().SetTag("WRT-CLIENT");
536 WrtClient app(argc, argv);
537 int ret = app.Exec();
538 LogDebug("App returned: " << ret);
539 ret = app.getReturnStatus();
540 LogDebug("WrtClient returned: " << ret);