[Release] livebox.web-provider-1.46
[platform/framework/web/web-provider.git] / src / Daemon / BoxDaemonImpl.cpp
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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 /**
17  * @file    BoxDaemonImpl.cpp
18  * @author  Yunchan Cho (yunchan.cho@samsung.com)
19  */
20 #include <sys/types.h>
21 #include <unistd.h>
22 #include <string>
23 #include <cstring>
24 #include <app.h>
25 #include <aul.h>
26 #include <Ecore_X.h>
27 #include <provider.h>
28 #include <livebox-service.h>
29 #include <Core/Util/Log.h>
30 #include <Plugin/IBoxPluginConnector.h>
31 #include <Plugin/BoxPluginConnector.h>
32 #include <API/web_provider_livebox_info.h>
33 #include "BoxDaemonUtil.h"
34 #include "BoxDaemonImpl.h"
35
36 #define MASTER_PROVIDER_PING_TIME  120.0f
37
38 // These are string for handling application service from app
39 static const std::string BOX_SERVICE_SCHEME("box-service://");
40 static const std::string OPERATION_UPDATE_BOX(
41         "http://tizen.org/appcontrol/operation/dynamicbox/web/update");
42 static const std::string CONTENT_INFO_KEY("content-info");
43 static const std::string ALARM_CALLER_KEY("__ALARM_MGR_CALLER_APPID");
44
45 BoxDaemonImpl::BoxDaemonImpl()
46     : m_pluginConnector(BoxPluginConnector::create())
47 {
48 }
49
50 BoxDaemonImpl::~BoxDaemonImpl()
51 {
52 }
53
54 bool BoxDaemonImpl::start(std::string& name)
55 {
56     LogD("enter");
57
58     // initialize existing plugins for web livebox
59     if (!m_pluginConnector->initialize()) { 
60         LogD("failed to initialize plugins");
61         return false;
62     }
63         
64     // set name
65     m_daemonName = name;
66
67     // provider init
68     ProviderCallbacks callbacks;
69     setProviderCallbacks(callbacks);
70
71     int ret = provider_init(ecore_x_display_get(),
72                             m_daemonName.c_str(),
73                             &callbacks,
74                             this);
75     if (ret < 0) {
76         LogD("failed to initialize provider");
77         return false;
78     }
79
80     return true;
81 }
82
83 bool BoxDaemonImpl::stop()
84 {
85     LogD("enter");
86
87     // deinitialize provider
88     provider_fini();
89
90     // deinitialize existing plugins for web livebox
91     if (!m_pluginConnector->shutdown()) { 
92         LogD("failed to shutdown plugins");
93         return false;
94     }
95
96     return true;
97 }
98
99 bool BoxDaemonImpl::handleAppService(service_h service)
100 {
101     LogD("enter");
102     int ret;
103     bool result = false;
104     Ecore_Job* jobResult = NULL;
105     char* operation;
106
107     ret = service_get_operation(service, &operation);
108     if (ret != SERVICE_ERROR_NONE) {
109         LogD("no operation");
110         return false;
111     }
112
113     if (OPERATION_UPDATE_BOX == operation) {
114         BoxInfoPtr info = handleOperationUpdate(service);
115         if (info) {
116             JobInfo* jobInfo = new JobInfo(REQUEST_CMD_UPDATE_BOX, info, this);
117             jobResult = ecore_job_add(requestBoxJobCallback, jobInfo);
118             if (jobResult) {
119                 result = true;
120             }
121         }
122     } else {
123         LogD("unknown operation: %s", operation);
124     }
125
126     delete[] operation;
127     return result;
128 }
129
130 int BoxDaemonImpl::connectedCallback(ProviderEventArgPtr arg, void* data)
131 {
132     LogD("enter");
133
134     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
135     if (!provider_send_hello()) {
136         This->m_pingTimer = 
137             ecore_timer_add(MASTER_PROVIDER_PING_TIME, pingToMasterCallback, This);
138     }
139
140     return 0;
141 }
142
143 int BoxDaemonImpl::disconnectedCallback(ProviderEventArgPtr arg, void* data)
144 {
145     LogD("enter");
146
147         aul_terminate_pid(getpid());
148
149     return 0;
150 }
151
152 int BoxDaemonImpl::boxCreateCallback( 
153         ProviderEventArgPtr arg, 
154         int* width, int* height, 
155         double* priority, void* data)
156 {
157     LogD("enter");
158
159     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
160     BoxInfoPtr info = This->initializeBoxInfo(arg);
161     if (!info) {
162         return -1;
163     }
164
165     if ((arg->info.lb_create.width == 0) || (arg->info.lb_create.height == 0)) {
166         livebox_service_get_size(LB_SIZE_TYPE_1x1, width, height);
167     } else {
168         *width = arg->info.lb_create.width;
169         *height = arg->info.lb_create.height;
170     }
171
172     info->boxWidth = *width;
173     info->boxHeight = *height;
174     info->priority = 1.0f;
175     info->period = arg->info.lb_create.period;
176     if (arg->info.lb_create.content) {
177         info->contentInfo = std::string(arg->info.lb_create.content);
178     }
179
180     // box information
181     LogD("--------------------------------------------");
182     LogD("boxId: %s", info->boxId.c_str());
183     LogD("InstanceId: %s", info->instanceId.c_str());
184     LogD("width: %d", info->boxWidth);
185     LogD("height: %d", info->boxHeight);
186     LogD("update period: %f", info->period);
187     LogD("--------------------------------------------");
188
189     JobInfo* jobInfo = new JobInfo(REQUEST_CMD_ADD_BOX, info, This);
190     Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo);
191
192     return ret ? 0 : -1;
193 }
194
195 int BoxDaemonImpl::boxReCreateCallback(ProviderEventArgPtr arg, void* data)
196 {
197     LogD("enter");
198
199     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
200     BoxInfoPtr info = This->initializeBoxInfo(arg);
201     if (!info) {
202         return -1;
203     }
204
205     int* width;
206     int* height;
207
208     if ((arg->info.lb_recreate.width == 0) || (arg->info.lb_recreate.height == 0)) {
209         livebox_service_get_size(LB_SIZE_TYPE_1x1, width, height);
210         arg->info.lb_recreate.width = *width;
211         arg->info.lb_recreate.height = *height;
212     }
213
214     info->boxWidth = arg->info.lb_recreate.width;
215     info->boxHeight = arg->info.lb_recreate.height;
216     info->priority = 1.0f;
217     info->period = arg->info.lb_recreate.period;
218     if (arg->info.lb_recreate.content) {
219         info->contentInfo = std::string(arg->info.lb_recreate.content);
220     }
221
222     // box information
223     LogD("--------------------------------------------");
224     LogD("boxId: %s", info->boxId.c_str());
225     LogD("InstanceId: %s", info->instanceId.c_str());
226     LogD("width: %d", info->boxWidth);
227     LogD("height: %d", info->boxHeight);
228     LogD("update period: %f", info->period);
229     LogD("--------------------------------------------");
230
231     JobInfo* jobInfo = new JobInfo(REQUEST_CMD_ADD_BOX, info, This);
232     Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo);
233
234     return ret ? 0 : -1;
235 }
236
237 int BoxDaemonImpl::boxDestroyCallback(ProviderEventArgPtr arg, void* data)
238 {
239     LogD("enter");
240
241     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
242     BoxInfoPtr info = This->initializeBoxInfo(arg);
243     if (!info) {
244         return -1;
245     }
246
247     LogD("--------------------------------------------");
248     LogD("boxId: %s", info->boxId.c_str());
249     LogD("InstanceId: %s", info->instanceId.c_str());
250     LogD("--------------------------------------------");
251
252     JobInfo* jobInfo = new JobInfo(REQUEST_CMD_REMOVE_BOX, info, This);
253     Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo);
254
255     return ret ? 0 : -1;
256 }
257
258 int BoxDaemonImpl::pdCreateCallback(ProviderEventArgPtr arg, void* data)
259 {
260     LogD("enter");
261
262     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
263     BoxInfoPtr info = This->initializeBoxInfo(arg);
264     if (!info) {
265         return -1;
266     }
267     if (arg->info.pd_create.w == 0 || arg->info.pd_create.h == 0) {
268         return -1;
269     }
270     //Use the screen width to fix the device width
271     ecore_x_window_size_get(0, &info->pdWidth, NULL);
272     info->pdHeight = arg->info.pd_create.h;
273     info->pdX = arg->info.pd_create.x;
274     info->pdY = arg->info.pd_create.y;
275
276     LogD("--------------------------------------------");
277     LogD("boxId: %s", info->boxId.c_str());
278     LogD("InstanceId: %s", info->instanceId.c_str());
279     LogD("width: %d", info->pdWidth);
280     LogD("height: %d", info->pdHeight);
281     LogD("x: %f", info->pdX);
282     LogD("y: %f", info->pdY);
283     LogD("--------------------------------------------");
284
285     JobInfo* jobInfo = new JobInfo(REQUEST_CMD_OPEN_PD, info, This);
286     Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo);
287
288     return ret ? 0 : -1;
289 }
290
291 int BoxDaemonImpl::pdDestroyCallback(ProviderEventArgPtr arg, void* data)
292 {
293     LogD("enter");
294
295     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
296     BoxInfoPtr info = This->initializeBoxInfo(arg);
297     if (!info) {
298         return -1;
299     }
300
301     LogD("--------------------------------------------");
302     LogD("boxId: %s", info->boxId.c_str());
303     LogD("InstanceId: %s", info->instanceId.c_str());
304     LogD("--------------------------------------------");
305
306     JobInfo* jobInfo = new JobInfo(REQUEST_CMD_CLOSE_PD, info, This);
307     Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo);
308
309     return ret ? 0 : -1;
310 }
311
312 int BoxDaemonImpl::clickedCallback(ProviderEventArgPtr arg, void* data)
313 {
314     LogD("enter");
315
316     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
317     BoxInfoPtr info = This->initializeBoxInfo(arg);
318     if (!info) {
319         return -1;
320     }
321
322     int flag = web_provider_livebox_get_auto_launch(info->boxId.c_str());
323     if (!flag) {
324         return -1;
325     }
326
327     BoxDaemonUtil::launchApplication(info->boxId, info->instanceId);
328     return 0;
329 }
330
331 int BoxDaemonImpl::boxResizeCallback(ProviderEventArgPtr arg, void* data)
332 {
333     LogD("enter");
334
335     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
336     BoxInfoPtr info = This->initializeBoxInfo(arg);
337     if (!info) {
338         return -1;
339     }
340     if (arg->info.resize.w == 0 || arg->info.resize.h == 0) {
341         return -1;
342     }
343
344     info->boxWidth = arg->info.resize.w;
345     info->boxHeight = arg->info.resize.h;
346
347     // box information
348     LogD("--------------------------------------------");
349     LogD("boxId: %s", info->boxId.c_str());
350     LogD("InstanceId: %s", info->instanceId.c_str());
351     LogD("width: %d", info->boxWidth);
352     LogD("height: %d", info->boxHeight);
353     LogD("--------------------------------------------");
354
355     JobInfo* jobInfo = new JobInfo(REQUEST_CMD_RESIZE_BOX, info, This);
356     Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo);
357
358     return ret ? 0 : -1;
359 }
360
361 int BoxDaemonImpl::boxPauseCallback(ProviderEventArgPtr arg, void* data)
362 {
363     LogD("enter");
364
365     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
366     BoxInfoPtr info = This->initializeBoxInfo(arg);
367     if (!info) {
368         return -1;
369     }
370
371     // box information
372     LogD("--------------------------------------------");
373     LogD("boxId: %s", info->boxId.c_str());
374     LogD("InstanceId: %s", info->instanceId.c_str());
375     LogD("--------------------------------------------");
376
377     JobInfo* jobInfo = new JobInfo(REQUEST_CMD_PAUSE_BOX, info, This);
378     Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo);
379
380     return ret ? 0 : -1;
381 }
382
383 int BoxDaemonImpl::boxResumeCallback(ProviderEventArgPtr arg, void* data)
384 {
385     LogD("enter");
386
387     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
388     BoxInfoPtr info = This->initializeBoxInfo(arg);
389     if (!info) {
390         return -1;
391     }
392
393     // box information
394     LogD("--------------------------------------------");
395     LogD("boxId: %s", info->boxId.c_str());
396     LogD("InstanceId: %s", info->instanceId.c_str());
397     LogD("--------------------------------------------");
398
399     JobInfo* jobInfo = new JobInfo(REQUEST_CMD_RESUME_BOX, info, This);
400     Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo);
401
402     return ret ? 0 : -1;
403 }
404
405 int BoxDaemonImpl::pauseCallback(ProviderEventArgPtr arg, void* data)
406 {
407     LogD("enter");
408
409     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
410
411     LogD("--------------------------------------------");
412     LogD("web-provider is paused");
413     LogD("--------------------------------------------");
414
415     JobInfo* jobInfo = new JobInfo(REQUEST_CMD_PAUSE_ALL, BoxInfoPtr(), This);
416     Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo);
417
418     return ret ? 0 : -1;
419 }
420
421 int BoxDaemonImpl::resumeCallback(ProviderEventArgPtr arg, void* data)
422 {
423     LogD("enter");
424
425     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
426
427     LogD("--------------------------------------------");
428     LogD("web-provider is resumed");
429     LogD("--------------------------------------------");
430
431     JobInfo* jobInfo = new JobInfo(REQUEST_CMD_RESUME_ALL, BoxInfoPtr(), This);
432     Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo);
433
434     return ret ? 0 : -1;
435 }
436
437 int BoxDaemonImpl::boxPeriodChangeCallback(ProviderEventArgPtr arg, void* data)
438 {
439     LogD("enter");
440     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
441     BoxInfoPtr info = This->initializeBoxInfo(arg);
442     if (!info) {
443         return -1;
444     }
445     info->period = arg->info.set_period.period;
446
447     LogD("--------------------------------------------");
448     LogD("boxId: %s", info->boxId.c_str());
449     LogD("InstanceId: %s", info->instanceId.c_str());
450     LogD("period: %f", info->period);
451     LogD("--------------------------------------------");
452
453     JobInfo* jobInfo = new JobInfo(REQUEST_CMD_CHANGE_PERIOD, info, This);
454     Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo);
455
456     return ret ? 0 : -1;
457 }
458
459 int BoxDaemonImpl::boxUpdateCallback(ProviderEventArgPtr arg, void* data)
460 {
461     LogD("enter");
462
463     BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
464     BoxInfoPtr info = This->initializeBoxInfo(arg);
465     if (!info) {
466         return -1;
467     }
468
469     LogD("--------------------------------------------");
470     LogD("boxId: %s", info->boxId.c_str());
471     LogD("InstanceId: %s", info->instanceId.c_str());
472     LogD("--------------------------------------------");
473
474     JobInfo* jobInfo = new JobInfo(REQUEST_CMD_UPDATE_BOX, info, This);
475     Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo);
476
477     return ret ? 0 : -1;
478 }
479
480 void BoxDaemonImpl::setProviderCallbacks(ProviderCallbacks& callbacks)
481 {
482     LogD("enter");
483
484     memset(&callbacks, 0, sizeof(callbacks));
485     callbacks.connected = BoxDaemonImpl::connectedCallback;
486     callbacks.disconnected = BoxDaemonImpl::disconnectedCallback;
487     callbacks.pause = BoxDaemonImpl::pauseCallback;
488     callbacks.resume = BoxDaemonImpl::resumeCallback;
489     callbacks.lb_create = BoxDaemonImpl::boxCreateCallback;
490     callbacks.lb_recreate = BoxDaemonImpl::boxReCreateCallback;
491     callbacks.lb_destroy = BoxDaemonImpl::boxDestroyCallback;
492     callbacks.lb_pause = BoxDaemonImpl::boxPauseCallback;
493     callbacks.lb_resume = BoxDaemonImpl::boxResumeCallback;
494     callbacks.pd_create = BoxDaemonImpl::pdCreateCallback;
495     callbacks.pd_destroy = BoxDaemonImpl::pdDestroyCallback;
496     callbacks.clicked = BoxDaemonImpl::clickedCallback;
497     callbacks.resize = BoxDaemonImpl::boxResizeCallback;
498     callbacks.update_content = BoxDaemonImpl::boxUpdateCallback;
499     callbacks.set_period = BoxDaemonImpl::boxPeriodChangeCallback;
500 }
501
502 std::string BoxDaemonImpl::getBoxType(const char* boxId)
503 {
504     LogD("enter");
505
506     if (!boxId) {
507         return std::string();
508     }
509     
510     const char* type = web_provider_livebox_get_box_type(boxId);
511     if (!type) {
512         std::string boxType = m_pluginConnector->getBoxType(boxId);
513         if (boxType.empty()) {
514             LogD("unrecognized box id");
515         } else {
516             LogD("box id: %s, type: %s", boxId, boxType.c_str());
517         }
518         return boxType;
519     }
520
521     LogD("box id: %s, type: %s", boxId, type);
522     std::string result{type};
523     free(const_cast<char*>(type));
524     return result;
525 }
526
527 BoxInfoPtr BoxDaemonImpl::initializeBoxInfo(ProviderEventArgPtr arg)
528 {
529     LogD("enter");
530
531     if (!arg) {
532         return BoxInfoPtr();
533     }
534
535     if (!arg->pkgname || !arg->id) {
536         LogD("pkgname or id don't exist");
537         return BoxInfoPtr();
538     }
539
540     std::string type = getBoxType(arg->pkgname);
541     if (type.empty()) {
542         return BoxInfoPtr();
543     }
544     BoxInfoPtr infoPtr = BoxInfoPtr(new BoxInfo(type, arg->pkgname, arg->id));
545
546     return infoPtr;
547 }
548
549 std::string BoxDaemonImpl::getBoxIdFromService(service_h service)
550 {
551     LogD("enter");
552
553     int ret;
554     char* serviceUri = NULL;
555     ret = service_get_uri(service, &serviceUri);
556     if (ret != SERVICE_ERROR_NONE) {
557         LogD("no box uri");
558         return std::string();
559     }
560
561     std::string uri(serviceUri);
562     delete[] serviceUri;
563
564     if(uri.compare(0, BOX_SERVICE_SCHEME.size(), BOX_SERVICE_SCHEME)) {
565         // uri is not box-service scheme
566         return std::string();
567     }
568
569     std::string boxId = uri.substr(BOX_SERVICE_SCHEME.size());
570     return boxId;
571 }
572
573 bool BoxDaemonImpl::isServiceCallerBoxOwner(service_h service)
574 {
575     LogD("enter");
576
577     int ret;
578
579     std::string boxId = getBoxIdFromService(service);
580     if (boxId.empty()) {
581         LogD("error box-id");
582         return false;
583     }
584
585     // check if caller is owner of this box
586     const char* appId = web_provider_livebox_get_app_id(boxId.c_str());
587     if (!appId) {
588         return false;
589     }
590     std::string ownerAppId(appId);
591     delete[] appId;
592
593     char* caller = NULL;
594     ret = service_get_caller(service, &caller);
595     if (ret != SERVICE_ERROR_NONE) {
596         ret = service_get_extra_data(
597                 service, ALARM_CALLER_KEY.c_str(), &caller);
598         if (ret != SERVICE_ERROR_NONE) {
599             LogD("failed to get caller's appid from service");
600             return false;
601         }
602     }
603     std::string callerAppId(caller);
604
605     // release strings
606     delete[] caller;
607
608     if (ownerAppId != callerAppId) {
609         LogD("caller is not matched with owner of requested box");
610         return false;
611     }
612
613     return true;
614 }
615
616 BoxInfoPtr BoxDaemonImpl::handleOperationUpdate(service_h service)
617 {
618     LogD("enter");
619
620     int ret;
621
622     if (!isServiceCallerBoxOwner(service)) {
623         return BoxInfoPtr();
624     }
625
626     std::string boxId = getBoxIdFromService(service);
627     if (boxId.empty()) {
628         LogD("error box-id");
629         return BoxInfoPtr();
630     }
631
632     char* contentInfo = NULL;
633     service_get_extra_data(service, CONTENT_INFO_KEY.c_str(), &contentInfo);
634
635     std::string type(getBoxType(boxId.c_str()));
636     if (type.empty()) {
637         LogD("no type for this box");
638         delete[] contentInfo;
639         return BoxInfoPtr();
640     }
641     BoxInfoPtr info = BoxInfoPtr(new BoxInfo(type, boxId, ""));
642     if (contentInfo) {
643         info->contentInfo = std::string(contentInfo);
644     }
645
646     // release string 
647     delete[] contentInfo;
648
649     return info;
650 }
651
652 Eina_Bool BoxDaemonImpl::pingToMasterCallback(void* data)
653 {
654     LogD("enter");
655
656     provider_send_ping();
657
658     return ECORE_CALLBACK_RENEW;
659 }
660
661 void BoxDaemonImpl::requestBoxJobCallback(void* data)
662 {
663     JobInfo* jobInfo = static_cast<JobInfo*>(data);
664     if (!jobInfo) {
665         LogD("no information for job");
666         return;
667     }
668
669     // just for debugging
670     //volatile int flag = 0;
671     //while(flag == 0) {;}
672
673     // request box job!
674     jobInfo->daemonImpl->m_pluginConnector->requestCommand(
675             jobInfo->cmdType, jobInfo->boxInfo);
676
677     delete jobInfo;
678 }