Update wrt_0.8.86
[platform/framework/web/wrt.git] / src / wrt-client / wrt-client.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 #include "wrt-client.h"
17 #include <cstdlib>
18 #include <cstdio>
19 #include <string>
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_localize_model.h>
26
27 WrtClient::WrtClient(int argc, char **argv) :
28     Application(argc, argv, "wrt-client", false),
29     DPL::TaskDecl<WrtClient>(this),
30     m_handle(-1),
31     m_launched(false),
32     m_initializing(false),
33     m_initialized(false),
34     m_sdkLauncherPid(0),
35     m_debugMode(false),
36     m_debuggerPort(0),
37     m_returnStatus(ReturnStatus::Succeeded),
38     m_widgetState(WidgetState::WidgetState_Stopped)
39 {
40     Touch();
41     LogDebug("App Created");
42 }
43
44 WrtClient::~WrtClient()
45 {
46     LogDebug("App Finished");
47 }
48
49 WrtClient::ReturnStatus::Type WrtClient::getReturnStatus() const
50 {
51     return m_returnStatus;
52 }
53
54 void WrtClient::OnStop()
55 {
56     LogInfo("Stopping Dummy Client");
57 }
58
59
60 void WrtClient::OnCreate()
61 {
62     LogInfo("On Create");
63 }
64
65
66 void WrtClient::OnResume()
67 {
68     if (m_widgetState != WidgetState_Suspended) {
69         LogWarning("Widget is not suspended, resuming was skipped");
70         return;
71     }
72     m_widget->Resume();
73     m_widgetState = WidgetState_Running;
74 }
75
76
77 void WrtClient::OnPause()
78 {
79     if (m_widgetState != WidgetState_Running) {
80         LogWarning("Widget is not running to be suspended");
81         return;
82     }
83     m_widget->Suspend();
84     m_widgetState = WidgetState_Suspended;
85 }
86
87 void WrtClient::OnReset(bundle *b)
88 {
89     LogDebug("OnReset");
90     // bundle argument is freed after OnReset() is returned
91     // So bundle duplication is needed
92     ApplicationDataSingleton::Instance().setBundle(bundle_dup(b));
93
94     if (true == m_initializing) {
95         LogDebug("can not handle reset event");
96         return;
97     }
98     if (true == m_launched) {
99         if (m_widgetState == WidgetState_Stopped) {
100             LogError("Widget is not running to be reset");
101             return;
102         }
103         m_widget->Reset();
104         m_widgetState = WidgetState_Running;
105     } else {
106         if (true == checkArgument())
107         {
108             setStep();
109         }
110         else
111         {
112             showHelpAndQuit();
113         }
114     }
115 }
116
117 void WrtClient::OnTerminate()
118 {
119     LogDebug("Wrt Shutdown now");
120     shutdownStep();
121 }
122
123 void WrtClient::showHelpAndQuit()
124 {
125     printf("Usage: wrt-client [OPTION]... [WIDGET: ID]...\n"
126            "launch widgets.\n"
127            "Mandatory arguments to long options are mandatory for short "
128            "options too.\n"
129            "  -h,    --help                                 show this help\n"
130            "  -l,    --launch                               "
131            "launch widget with given ID\n"
132            "\n");
133
134     Quit();
135 }
136
137 bool WrtClient::checkArgument()
138 {
139     LogInfo("checkArgument");
140
141     std::string arg = m_argv[0];
142
143     if (arg.empty()) {
144         return false;
145     }
146
147     if (arg.find("wrt-client") != std::string::npos)
148     {
149         if (m_argc <= 1) {
150             return false;
151         }
152
153         arg = m_argv[1];
154
155         if (arg == "-h" || arg == "--help") {
156             // Just show help
157             return false;
158         } else if (arg == "-l" || arg == "--launch") {
159             if (m_argc != 3) {
160                 return false;
161             }
162             m_handle = atoi(m_argv[2]);
163         } else {
164             return false;
165         }
166     } else {
167         size_t pos = arg.find_last_of('/');
168
169         if (pos != std::string::npos) {
170             arg = arg.erase(0, pos + 1);
171         }
172
173         // Launch widget based on application basename
174         if (sscanf(arg.c_str(), "%i", &m_handle) != 1) {
175             printf("failed: invalid widget handle\n");
176             return false;
177         }
178
179         LogDebug("Widget Id: " << m_handle << " (" << arg << ")");
180     }
181
182     return true;
183 }
184
185 void WrtClient::setStep()
186 {
187     LogInfo("setStep");
188
189     AddStep(&WrtClient::initStep);
190
191     setSdkLauncherDebugData();
192
193     AddStep(&WrtClient::launchStep);
194     AddStep(&WrtClient::shutdownStep);
195
196     m_initializing = true;
197
198     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(NextStepEvent());
199 }
200
201 void WrtClient::setSdkLauncherDebugData()
202 {
203     LogDebug("setSdkLauncherDebugData");
204
205     /* check bundle from sdk launcher */
206     bundle *bundleFromSdkLauncher;
207     bundleFromSdkLauncher = bundle_import_from_argv(m_argc, m_argv);
208     const char *bundle_debug = bundle_get_val(bundleFromSdkLauncher, "debug");
209     const char *bundle_pid = bundle_get_val(bundleFromSdkLauncher, "pid");
210     if (bundle_debug != NULL && bundle_pid != NULL) {
211         if (strcmp(bundle_debug, "true") == 0) {
212             m_debugMode = true;
213             m_sdkLauncherPid = atoi(bundle_pid);
214         } else {
215             m_debugMode = false;
216         }
217     }
218 }
219
220 void WrtClient::OnEventReceived(const NextStepEvent& /*event*/)
221 {
222     LogDebug("Executing next step");
223     NextStep();
224 }
225
226 void WrtClient::initStep()
227 {
228     LogDebug("");
229     if (WRT::CoreModuleSingleton::Instance().Init()) {
230         m_initialized = true;
231     } else {
232         m_returnStatus = ReturnStatus::Failed;
233         SwitchToStep(&WrtClient::shutdownStep);
234     }
235     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
236             NextStepEvent());
237 }
238
239 void WrtClient::localizeWidgetModel() {
240     Assert(!!m_widget);
241     WRT::WidgetModelPtr model = m_widget->GetModel();
242     Assert(!!model);
243     Domain::localizeWidgetModel(model);
244     model->RunningName.Set(model->Name.Get());
245     model->RunningIcon.Set(model->Icon.Get());
246     model->RunningStartURL.Set(model->StartURL.Get());
247     model->RunningShortName.Set(model->ShortName.Get());
248     model->RunningDescription.Set(model->Description.Get());
249     model->RunningLicense.Set(model->License.Get());
250     model->RunningLicenseHref.Set(model->LicenseHref.Get());
251     model->RunningStartFileInfo.Set(
252         model->StartFileInfo.Get());
253 }
254
255 bool WrtClient::checkWACTestCertififedWidget()
256 {
257     // WAC Waikiki Beta Release Core Specification: Widget Runtime
258     // 10 Dec 2010
259     //
260     // WR-4710 The WRT MUST enable debug functions only for WAC test widgets
261     // i.e. the functions must not be usable for normal WAC widgets, even when
262     // a WAC test widget is executing.
263     ADD_PROFILING_POINT("DeveloperModeCheck", "start");
264     Assert(!!m_widget);
265     WRT::WidgetModelPtr model = m_widget->GetModel();
266     Assert(!!model);
267     // WAC test widget
268     // A widget signed with a WAC-issued test certificate as described in
269     // Developer Mode.
270
271     bool developerWidget = model->IsTestWidget.Get();
272     bool developerMode =
273         GlobalLogicSingleton::Instance().GetGlobalModel()->DeveloperMode.Get();
274
275     LogDebug("Is WAC test widget: " << developerWidget);
276     LogDebug("Is developer Mode: " << developerMode);
277
278     if (developerWidget) {
279         if(!developerMode)
280         {
281             LogError("WAC test certified developer widget is needed for " <<
282                     "developer mode");
283             return false;
284         }else{
285             //TODO: WR-4660 (show popup about developer widget
286             //      during launch
287             LogInfo("POPUP: THIS IS TEST WIDGET!");
288         }
289     }
290     ADD_PROFILING_POINT("DeveloperModeCheck", "stop");
291     return true;
292 }
293
294 void WrtClient::staticWrtLaunchWidgetCallback(int /*handle*/,
295                                               CommonError::Type status,
296                                               const std::string& errorMsg,
297                                               void* userdata)
298 {
299     WrtLaunchData* userData = static_cast<WrtLaunchData*>(userdata);
300     WrtClient* wrtClient = static_cast<WrtClient*>(userData->wrtClientContext);
301     SDKDebugData* debug = userData->sdkDebugData;
302
303     if (status == CommonError::WrtSuccess) {
304         LogDebug("Launch succesfull");
305
306         wrtClient->m_launched = true;
307         wrtClient->m_initializing = false;
308         setlinebuf(stdout);
309         printf("launched\n");
310         fflush(stdout);
311     } else {
312         LogError("Launch unsuccesfull: " << errorMsg);
313
314         printf("failed\n");
315
316         wrtClient->m_returnStatus = ReturnStatus::Failed;
317         //shutdownStep
318         wrtClient->DPL::Event::ControllerEventHandler<NextStepEvent>::
319                 PostEvent(NextStepEvent());
320     }
321
322     if(debug->debugMode)
323     {
324         LogDebug("Send RT signal to wrt-launcher(pid: "
325                 << wrtClient->m_sdkLauncherPid << ", status: " << status);
326         union sigval sv;
327         /* send real time signal with result to wrt-launcher */
328         if(status == CommonError::WrtSuccess)
329         {
330             LogDebug("userData->portnum : " << debug->portnum);
331             sv.sival_int = debug->portnum;
332         }
333         else
334         {
335            sv.sival_int = -1;
336         }
337         sigqueue(wrtClient->m_sdkLauncherPid, SIGRTMIN, sv);
338     }
339
340     ApplicationDataSingleton::Instance().freeBundle();
341
342     LogDebug("Cleaning wrtClient launch resources...");
343     delete debug->pid;
344     delete debug;
345     delete userData;
346 }
347
348 void WrtClient::launchStep()
349 {
350     LogDebug("Launching widget ...");
351
352     m_widget = WRT::CoreModuleSingleton::Instance().getRunnableWidgetObject(m_handle);
353     if (!m_widget) {
354         LogError("RunnableWidgetObject is NULL, stop launchStep");
355         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
356                     NextStepEvent());
357         return;
358     }
359
360     if (m_widgetState == WidgetState_Running) {
361         LogWarning("Widget already running, stop launchStep");
362         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
363                     NextStepEvent());
364         return;
365     }
366
367     if (m_widgetState == WidgetState_Authorizing) {
368         LogWarning("Widget already authorizing, stop launchStep");
369         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
370                     NextStepEvent());
371         return;
372     }
373
374     // Widget is not running, localized data can be updated
375     localizeWidgetModel();
376
377     if (!checkWACTestCertififedWidget())
378     {
379         LogWarning("WAC Certificate failed, stop launchStep");
380         return;
381     }
382
383     m_widgetState = WidgetState_Authorizing;
384     if (!m_widget->CheckBeforeLaunch()) {
385         LogError("CheckBeforeLaunch failed, stop launchStep");
386         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
387                     NextStepEvent());
388         return;
389     }
390     LogInfo("Widget launch accepted. Entering running state");
391     m_widgetState = WidgetState_Running;
392     m_widget->PrepareView();
393     SDKDebugData* debugData = new SDKDebugData;
394     debugData->debugMode = m_debugMode;
395     debugData->pid = new unsigned long(getpid());
396     WrtLaunchData* userData = new WrtLaunchData;
397     userData->wrtClientContext = this;
398     userData->sdkDebugData = debugData;
399     WidgetLaunchStruct launch(
400             debugData->pid,
401             &staticWrtLaunchWidgetCallback,
402             userData,
403             debugData,
404             "");
405     m_widget->Show(launch);
406 }
407
408 void WrtClient::shutdownStep()
409 {
410     LogDebug("Closing Wrt connection ...");
411     if (m_initialized && m_widget) {
412         m_widgetState = WidgetState_Stopped;
413         m_widget->Hide();
414         m_widget.reset();
415         WRT::CoreModuleSingleton::Instance().Terminate();
416         m_initialized = false;
417     }
418     Quit();
419 }
420
421 int main(int argc,
422          char *argv[])
423 {
424     ADD_PROFILING_POINT("main-entered", "point");
425
426     // Output on stdout will be flushed after every newline character,
427     // even if it is redirected to a pipe. This is useful for running
428     // from a script and parsing output.
429     // (Standard behavior of stdlib is to use full buffering when
430     // redirected to a pipe, which means even after an end of line
431     // the output may not be flushed).
432     setlinebuf(stdout);
433
434     // set evas backend type
435     if (!getenv("ELM_ENGINE")) {
436         if (setenv("ELM_ENGINE", "gl", 1)) {
437                 LogDebug("Enable backend");
438         }
439     }
440     setenv("COREGL_FASTPATH", "1", 1);
441     // Set log tagging
442     DPL::Log::LogSystemSingleton::Instance().SetTag("WRT-CLIENT");
443
444     WrtClient app(argc, argv);
445     int ret = app.Exec();
446     LogDebug("App returned: " << ret);
447     ret = app.getReturnStatus();
448     LogDebug("WrtClient returned: " << ret);
449     return ret;
450 }