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