Merge changes I62af2333,I9317aba8,I03d801f5 into tizen_2.2
[platform/framework/native/appfw.git] / src / app / FApp_AppControlManager.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
17 /**
18  * @file        FApp_AppControlManager.cpp
19  * @brief       This is the implementation for the _AppControlManager class.
20  */
21
22 #include <stdint.h>
23 #include <cstdio>
24 #include <unique_ptr.h>
25
26 #include <appsvc/appsvc.h>
27 #include <aul/aul.h>
28 #include <bundle.h>
29 #include <content/mime_type.h>
30 #include <appinfo.h>
31
32 #include <FBaseInteger.h>
33 #include <FBaseObject.h>
34 #include <FBaseString.h>
35 #include <FBaseColIListT.h>
36 #include <FBaseColArrayList.h>
37 #include <FBaseErrors.h>
38 #include <FAppAppControl.h>
39 #include <FAppAppManager.h>
40 #include <FAppIAppControlListener.h>
41 #include <FAppIAppControlResponseListener.h>
42 #include <FAppIAppFrame.h>
43 #include <FAppSqlDataControl.h>
44 #include <FAppMapDataControl.h>
45 #include <FAppPkgPackageInfo.h>
46
47 #include <FBaseSysLog.h>
48 #include <FBase_StringConverter.h>
49 #include <FBaseRt_LibraryImpl.h>
50 #include <FIo_DataControlResultSetImpl.h>
51
52 #include "FApp_AppArg.h"
53 #include "FApp_AppControlEventArg.h"
54 #include "FApp_AppControlRegistry.h"
55 #include "FApp_AppControlImpl.h"
56 #include "FApp_AppImpl.h"
57 #include "FApp_AppInfo.h"
58 #include "FApp_AppManagerEventArg.h"
59 #include "FApp_Aul.h"
60 #include "FApp_AppControlManager.h"
61 #include "FApp_AppManagerProxy.h"
62 #include "FApp_ConditionManagerProxy.h"
63 #include "FApp_IAppManagerEventListener.h"
64 #include "FApp_MapDataControlImpl.h"
65 #include "FApp_SqlDataControlImpl.h"
66 #include "FAppPkg_PackageManagerImpl.h"
67 #include "FAppPkg_PackageInfoImpl.h"
68 #include "FApp_AppMessageImpl.h"
69 #include "FApp_AppManagerImpl.h"
70 #include "FApp_AppControlResponseEvent.h"
71
72 using namespace Tizen::App::Package;
73 using namespace Tizen::Base;
74 using namespace Tizen::Base::Collection;
75 using namespace Tizen::Base::Runtime;
76 using namespace Tizen::Base::Utility;
77 using namespace Tizen::Io;
78
79 namespace
80 {
81 const char SELECTOR_NOTI_KEY[] = "__APP_SVC_CALLER_NOTI__";
82 }
83
84 namespace Tizen { namespace App
85 {
86 const wchar_t TIZEN_OPERATION_PICK[] = L"http://tizen.org/appcontrol/operation/pick";
87
88
89 _AppControlManager::_AppControlManager(void)
90 {
91         SysLog(NID_APP, "");
92
93         // AppControl event handling is expected to be performed in the main thread.
94         __appControlEvent.Construct();
95         __appControlEvent.AddListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
96         __listenerList.Construct();
97         __appControlResponseEventContainer.Construct();
98         __appControlResponseEventList.Construct();
99 }
100
101 _AppControlManager::~_AppControlManager(void)
102 {
103         SysLog(NID_APP, "");
104         __appControlEvent.RemoveListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
105         IEnumeratorT<int>* pEnum = __appControlResponseEventList.GetEnumeratorN();
106
107         if (pEnum != null)
108         {
109                 while(pEnum->MoveNext() == E_SUCCESS)
110                 {
111                         int reqId;
112                         pEnum->GetCurrent(reqId);
113                         _AppControlResponseEvent* pResponseEvent = null;
114                         __appControlResponseEventContainer.GetValue(reqId, pResponseEvent);
115                         delete pResponseEvent;
116
117                         __appControlResponseEventContainer.Remove(reqId);
118                         SysLog(NID_APP, "pResponseEvent gets deleted. reqId(%d)", reqId);
119                 }
120         }
121         delete pEnum;
122 }
123
124 _AppControlManager*
125 _AppControlManager::GetInstance(void)
126 {
127         static _AppControlManager inst;
128
129         return &inst;
130 }
131
132 result
133 _AppControlManager::GetMimeFromExt(const String& ext, String& out)
134 {
135         std::unique_ptr<char[]> pExtension(_StringConverter::CopyToCharArrayN(ext));
136         SysTryReturnResult(NID_APP, pExtension != null, E_OUT_OF_MEMORY, "String allocation failure.");
137
138         char* mime = NULL;
139         mime_type_get_mime_type(pExtension.get(), &mime);
140
141         SysTryReturnResult(NID_APP, mime != NULL, E_UNSUPPORTED_FORMAT, "MIME type conversion failure for %ls.", ext.GetPointer());
142
143         out = mime;
144         free(mime);
145
146         return E_SUCCESS;
147 }
148
149 void
150 _AppControlManager::OnAppControlEventReceivedN(int reqId, _AppArg* pAppArg, int res)
151 {
152         SysLog(NID_APP, "Received request Id %d, arg 0x%x", reqId, pAppArg);
153
154         //_AppArg::Print(b);
155         // get launch info from request Id
156         _LaunchInfo* pInfo = __launchManager.FindItem(reqId);
157         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with response %d", reqId,
158                                         res);
159
160         // invoke callback
161         if (pInfo->launchCb)
162         {
163                 if (pInfo->magic == LAUNCH_INFO_MAGIC)
164                 {
165                         SysLog(NID_APP, "Invoking callback 0x%x", pInfo->launchCb);
166                         //pAppArg->Print();
167
168                         if (pInfo->pUserData && (!__listenerList.Contains(pInfo->pUserData)))
169                         {
170                                 (*pInfo->launchCb)(pInfo->pUserData, pInfo->pArg, pAppArg, static_cast<service_result_e>(res), pInfo->property, reqId);
171                         }
172                 }
173                 else
174                 {
175                         SysLogException(NID_APP, E_SYSTEM, "Corrupted data structure.");
176                 }
177         }
178
179         // clean up argument
180         __launchManager.RemoveItem(reqId);
181 }
182
183
184 // callback for out-of-process AppControl start event
185 void
186 _AppControlManager::OnAppControlEventReceivedN(int reqId, const AppId& appId, const String& operationId)
187 {
188         SysLog(NID_APP, "Received request Id %d, app %ls, operationId %ls", reqId, appId.GetPointer(), operationId.GetPointer());
189
190         // get launch info from request Id
191         _LaunchInfo* pInfo = __launchManager.FindItem(reqId);
192         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found.", reqId);
193
194         // at least listener
195         IAppControlResponseListener* pListener = static_cast<IAppControlResponseListener*>(pInfo->pUserData);
196         SysTryReturnVoidResult(NID_APP, typeid(pListener) == typeid(IAppControlResponseListener*), E_SYSTEM, "[E_SYSTEM] Invalid result callback.");
197
198         if (pListener)
199         {
200                 result r = E_SUCCESS;
201                 AppId actualAppId = appId;
202                 if (appId == L'c')
203                 {
204                         actualAppId.Clear();
205                         r = E_OPERATION_CANCELED;
206                 }
207                 SysLog(NID_APP, "Invoking callback 0x%x.", pListener);
208
209                 _AppControlResponseEvent* pResponseEvent = null;
210                 __appControlResponseEventContainer.GetValue(reqId, pResponseEvent);
211                 SysLog(NID_APP, "StartResponseReceived Request Id(%d), ResponseEvent 0x%x.", reqId, pResponseEvent);
212                 if (pResponseEvent != null)
213                 {
214                         String oId(operationId);
215                         _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_START, actualAppId, oId, r, APP_CTRL_RESULT_SUCCEEDED, null, reqId, false);
216
217                         if (pResponseEventArg != null)
218                         {
219                                 pResponseEvent->Fire(*pResponseEventArg);
220                                 SysLog(NID_APP, "pResponseEvent is Fired");
221                         }
222                 }
223                 else
224                 {
225                         pListener->OnAppControlStartResponseReceived(actualAppId, operationId, r);
226                         SysLog(NID_APP, "OnAppControlStartResponseReceived called directly");
227                 }
228         }
229         else
230         {
231                 SysLog(NID_APP, "No listener registered.");
232         }
233 }
234
235
236 void
237 _AppControlManager::InvokeAppControlCompleteListener(IAppControlResponseListener& listener, const AppId& appId, const String& op, AppCtrlResult res, const IMap* pExtraData, bool isSubMode)
238 {
239         listener.OnAppControlCompleteResponseReceived(appId, op, res, pExtraData);
240
241         if (!isSubMode)
242         {
243                 _AppImpl::GetInstance()->SendUserEvent(_APP_EVENT_RAISE, null, false);
244         }
245
246         SysLog(NID_APP, "AppControl response finished.");
247 }
248
249
250 void
251 _AppControlManager::InvokeLegacyAppControlCompleteListener(IAppControlEventListener& listener, const AppId& appId, const String& op, const IList* pList, bool isSubMode)
252 {
253         listener.OnAppControlCompleted(appId, op, pList);
254
255         if (!isSubMode)
256         {
257                 _AppImpl::GetInstance()->SendUserEvent(_APP_EVENT_RAISE, null, false);
258         }
259
260         SysLog(NID_APP, "Legacy AppControl response finished.");
261 }
262
263
264 // callback for in-process event handling
265 void
266 _AppControlManager::OnAppControlEventReceivedN(int reqId, int res, const IMap* pArgs, int property)
267 {
268         SysLog(NID_APP, "Received request Id %d, res %d, args 0x%x", reqId, res, pArgs);
269
270         // process proper callback
271         _InProcessInfo* pInfo = __inAppManager.FindItem(reqId);
272         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with args 0x%x", reqId,
273                                         pArgs);
274
275         if (pInfo->pListener && (!__listenerList.Contains(pInfo->pListener)))
276         {
277                 String aId = pInfo->providerId;
278                 String oId = pInfo->operationId;
279
280                 SysLog(NID_APP, "Invoking callback 0x%x for (%ls, %ls).", pInfo->pListener, aId.GetPointer(), oId.GetPointer());
281
282                 if (pInfo->property & _APPCONTROL_PROPERTY_ALIAS)
283                 {
284                         const _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
285                         pEntry = _AppControlRegistry::GetInstance()->GetReverseAppControlAliasEntry(aId, oId);
286                         if (pEntry)
287                         {
288                                 aId = pEntry->provider;
289                                 oId = pEntry->operation;
290
291                                 SysLog(NID_APP, "Legacy AppControl (%ls, %ls).", aId.GetPointer(), oId.GetPointer());
292                         }
293                 }
294
295                 const bool isSubMode = (property & _APPCONTROL_PROPERTY_SUBMODE);
296
297                 if (pInfo->isLegacy)
298                 {
299                         IAppControlEventListener* pListener = dynamic_cast<IAppControlEventListener*>(pInfo->pListener);
300                         if (pListener)
301                         {
302                                 ArrayList list(SingleObjectDeleter);
303                                 _AppArg::FillLegacyAppControlResult(list, res, pArgs, aId);
304
305                                 InvokeLegacyAppControlCompleteListener(*pListener, aId, oId, &list, isSubMode);
306                         }
307                         else
308                         {
309                                 SysLog(NID_APP, "Wrong AppControl listener type.");
310                         }
311                 }
312                 else
313                 {
314                         IAppControlResponseListener* pListener = dynamic_cast<IAppControlResponseListener*>(pInfo->pListener);
315                         if (pListener)
316                         {
317                                 _AppControlResponseEvent* pResponseEvent = null;
318                                 int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + reqId;
319                                 __appControlResponseEventContainer.GetValue(responseEventRequestId, pResponseEvent);
320
321                                 if (pResponseEvent != null)
322                                 {
323                                         _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_COMPLETE, aId, oId, E_SUCCESS, static_cast<AppCtrlResult>(res), const_cast<IMap*> (pArgs), responseEventRequestId, isSubMode);
324                                         if (pResponseEventArg != null)
325                                         {
326                                                 pResponseEvent->Fire(*pResponseEventArg);
327                                                 SysLog(NID_APP, "pResponseEvent is Fired");
328                                         }
329                                 }
330                                 else
331                                 {
332                                         InvokeAppControlCompleteListener(*pListener, aId, oId, ConvertAppControlResultCode(res), pArgs, isSubMode);
333                                         SysLog(NID_APP, "Listener called directly");
334                                         delete pArgs;
335                                 }
336                         }
337                         else
338                         {
339                                 SysLog(NID_APP, "Wrong AppControl listener type.");
340                         }
341                 }
342         }
343         else
344         {
345                 SysLogException(NID_APP, E_SYSTEM, "Invalid AppControl listener.");
346         }
347
348         // call TerminateAppControl
349         result (* pFunc)(int req) = null;
350         pFunc = reinterpret_cast<result (*)(int)>(pInfo->pLib->GetProcAddress(L"TerminateAppControl"));
351         if (pFunc)
352         {
353                 (*pFunc)(pInfo->reqId);
354         }
355         else
356         {
357                 SysLogException(NID_APP, E_SYSTEM, "No TerminateAppControl() function.");
358         }
359
360         // remove from list and unload dll
361         __inAppManager.RemoveItem(reqId);
362 }
363
364
365 result
366 _AppControlManager::SendAppControlEvent(IEventArg& arg)
367 {
368         return __appControlEvent.FireAsync(arg);
369 }
370
371 Tizen::Base::Collection::IMapT<int,_AppControlResponseEvent*>*
372 _AppControlManager::GetAppControlResponseEventContainer(void)
373 {
374         return &__appControlResponseEventContainer;
375 }
376
377
378 // generic launch callback
379 static void
380 LaunchResultCb(bundle* b, int request_code, appsvc_result_val res, void* data)
381 {
382         SysLog(NID_APP, "SLP callee result: %d", res);
383
384         _AppControlManager* pImpl = static_cast<_AppControlManager*>(data);
385         if (pImpl == null)
386         {
387                 return;
388         }
389
390         _AppArg* pAppArg = new (std::nothrow) _AppArg;
391         SysTryReturnVoidResult(NID_APP, pAppArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
392
393         _AppControlEventArg* pArg = null;
394         result r = pAppArg->Construct(b);
395         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] AppControl event argument creation failure.", GetErrorMessage(r));
396
397         pArg = new (std::nothrow) _AppControlEventArg(request_code, pAppArg, res);
398         SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, r, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
399
400         //_AppArg::Print(b);
401         pImpl->SendAppControlEvent(*pArg);
402
403         return;
404
405 CATCH:
406         delete pAppArg;
407 }
408
409
410 result
411 _AppControlManager::SendAppControlStartResponse(int req, const char* pValue, const char* pOp)
412 {
413         _AppControlStartEventArg* pArg = new (std::nothrow) _AppControlStartEventArg(req, AppId(pValue), String(pOp));
414         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "AppControl start event creation failure.");
415
416         SendAppControlEvent(*pArg);
417
418         return E_SUCCESS;
419 }
420
421
422 result
423 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
424 {
425         bundle* kb = msg.GetBundle();
426         SysTryReturnResult(NID_APP, kb != NULL, E_OUT_OF_MEMORY, "Bundle allocation failure.");
427
428         if (pkg_name)
429         {
430                 appsvc_set_pkgname(kb, pkg_name);
431         }
432
433         appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
434
435         if (mime)
436         {
437                 appsvc_set_mime(kb, mime);
438         }
439
440         if (uri)
441         {
442                 appsvc_set_uri(kb, uri);
443         }
444
445         if (_AppImpl::GetInstance() != null)
446         {
447                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
448                 _AppArg::UpdateWindowHandle(kb, handle);
449         }
450
451         SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
452         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
453
454         result r = E_SUCCESS;
455         if (pid < 0)
456         {
457                 switch (pid)
458                 {
459                 case APPSVC_RET_EILLACC:
460                         r = E_ILLEGAL_ACCESS;
461                         break;
462                 case APPSVC_RET_EINVAL:
463                         r = E_MAX_EXCEEDED;
464                         break;
465                 default:
466                         r = E_SYSTEM;
467                         break;
468                 }
469                 SysLog(NID_APP, "[%s] Launching service %s failure", GetErrorMessage(r), pkg_name);
470         }
471
472         return r;
473 }
474
475
476 int
477 _AppControlManager::Launch(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
478 {
479         bundle* kb = msg.GetBundle();
480         SysTryReturn(NID_APP, kb != NULL, -1, E_OUT_OF_MEMORY, "Bundle allocation failure.");
481
482         if (pkg_name)
483         {
484                 appsvc_set_pkgname(kb, pkg_name);
485         }
486
487         appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
488
489         if (mime)
490         {
491                 appsvc_set_mime(kb, mime);
492         }
493
494         if (uri)
495         {
496                 appsvc_set_uri(kb, uri);
497         }
498
499         if (_AppImpl::GetInstance() != null)
500         {
501                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
502                 _AppArg::UpdateWindowHandle(kb, handle);
503         }
504
505         SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
506         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
507
508         result r = E_SUCCESS;
509         if (pid < 0)
510         {
511                 switch (pid)
512                 {
513                 case APPSVC_RET_EILLACC:
514                         r = E_ILLEGAL_ACCESS;
515                         break;
516                 case APPSVC_RET_EINVAL:
517                         r = E_MAX_EXCEEDED;
518                         break;
519                 default:
520                         r = E_SYSTEM;
521                         break;
522                 }
523                 SysLog(NID_APP, "[%s]Launching service %s failure", GetErrorMessage(r), pkg_name);
524         }
525         SetLastResult(r);
526
527         return pid;
528 }
529
530
531 int
532 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const AppId& appId, const String& opId, const String* pUri, const String* pMime, AppSvcResFn pCb, void* data)
533 {
534         std::unique_ptr<char[]> pPackage(_StringConverter::CopyToCharArrayN(appId));
535         std::unique_ptr<char[]> pOperation(_StringConverter::CopyToCharArrayN(opId));
536
537         const char* pUriData = null;
538         if (pUri)
539         {
540                 pUriData =  _StringConverter::CopyToCharArrayN(*pUri);
541         }
542
543         const char* pMimeData = null;
544         if (pMime)
545         {
546                 pMimeData = _StringConverter::CopyToCharArrayN(*pMime);
547         }
548
549         int pid = Launch(msg, pPackage.get(), pOperation.get(), pMimeData, pUriData, pCb, data);
550
551         delete [] pUriData;
552         delete [] pMimeData;
553
554         return pid;
555 }
556
557
558 result
559 _AppControlManager::LaunchPkg(const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
560 {
561         _AppMessageImpl msg;
562
563         return LaunchPkg(msg, pkg_name, op, mime, uri, pCb, data);
564 }
565
566 result
567 _AppControlManager::LaunchAppWithCondition(const AppId& appId, const String& condition, IList* pArrayArgs)
568 {
569         result r = E_SUCCESS;
570         _AppArg * pArg = new (std::nothrow) _AppArg();
571         SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]");
572
573         r = pArg->ConstructForAppLaunchCondition(condition, pArrayArgs);
574         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] ConstructForAppLaunchCondition(%ls, .. ) fails", GetErrorMessage(r), condition.GetPointer());
575
576         r = _AppControlManager::LaunchApp(appId, pArg);
577 CATCH:
578         delete pArg;
579         return r;
580 }
581
582 result
583 _AppControlManager::LaunchApp(const AppId& appId, _AppArg* pArg, int req)
584 {
585         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
586         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
587
588         String actualAppId = appId;
589         if (appId.GetLength() == 10)
590         {
591                 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
592
593                 if (!name.IsEmpty())
594                 {
595                         actualAppId.Append(L'.');
596                         actualAppId.Append(name);
597                 }
598         }
599
600         pArg->UpdateRequestId(req);
601
602         if (_AppImpl::GetInstance() != null)
603         {
604                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
605                 pArg->UpdateWindowHandle(handle);
606         }
607
608         int pid = -1;
609         bundle* kb = NULL;
610         String tempId;
611         actualAppId.SubString(0, 10, tempId);
612         tempId += L'.';
613         tempId += L"_AppControl";
614
615         // [INFO] Ugly solution for submode support
616         pArg->UpdateAppId(tempId);
617         kb = pArg->GetBundle();
618         
619         pid = appsvc_run_service(kb, req, LaunchResultCb, this);
620         if (pid >= 0)
621         {
622                 SysLog(NID_APP, "Submode launch successful");
623                 return E_SUCCESS;
624         }
625         else if (pid == APPSVC_RET_EINVAL)
626         {
627                 SysLog(NID_APP, "Argument overflow");
628                 return E_MAX_EXCEEDED;
629         }
630
631         pArg->UpdateAppId(actualAppId);
632
633         // retry for possible failure
634         int count = 0;
635         const int TRY_COUNT = 3;
636         const int TRY_SLEEP_TIME = 65;
637         do
638         {
639                 kb = pArg->GetBundle();
640                 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
641                 if (pid >= 0)
642                 {
643                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
644                         return E_SUCCESS;
645                 }
646                 else if (pid == APPSVC_RET_EINVAL)
647                 {
648                         SysLog(NID_APP, "Argument overflow");
649                         return E_MAX_EXCEEDED;
650                 }
651
652                 count++;
653                 SysLog(NID_APP, "Waiting %dth time.", count);
654                 Thread::Sleep(TRY_SLEEP_TIME);
655         }
656         while (count < TRY_COUNT);
657
658         result r = E_SUCCESS;
659         switch (pid)
660         {
661         case APPSVC_RET_EILLACC:
662                 r = E_ILLEGAL_ACCESS;
663                 break;
664         default:
665                 r = E_SYSTEM;
666                 break;
667         }
668
669         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
670
671         return r;
672 }
673
674 static bool
675 _IsDefaultApplication(const AppId& packageId, const String& appId)
676 {
677         const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
678
679         int index = -1;
680         result r = appId.IndexOf(L'.', 0, index);
681         if (r != E_SUCCESS)
682         {
683                 return false;
684         }
685
686         String tmp;
687         appId.SubString(index + 1, tmp);
688         if (tmp == execName)
689         {
690                 SysLog(NID_APP, "Default application %ls", tmp.GetPointer());
691                 return true;
692         }
693
694         return false;
695 }
696
697
698 int
699 _AppControlManager::Launch(const _AppMessageImpl& msg, const AppId& aId, const String& oId, const String* pUriData, const String* pMimeType, AppSvcResFn pCb, void* pData)
700 {
701         SysLog(NID_APP, "Enter");
702
703         _AppArg arg;
704         arg.Construct(msg, oId, pUriData, pMimeType);
705
706         int pid = Launch(aId, &arg, pCb, pData, -1); 
707         SysTryReturn(NID_APP, pid >= 0, -1, GetLastResult(), "Launching(%ls) is failed", aId.GetPointer());
708
709         SysLog(NID_APP, "Exit");
710
711         return pid;
712 }
713
714
715 int
716 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
717 {
718         return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
719 }
720
721
722 int
723 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, AppSvcResFn pCb, void* pData, int req)
724 {
725         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Invalid launch argument");
726         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
727
728         String actualAppId = appId;
729 #if 0
730         if (appId.GetLength() == 10)
731         {
732                 const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
733
734                 if (!execName.IsEmpty())
735                 {
736                         actualAppId.Append(L'.');
737                         actualAppId.Append(execName);
738                 }
739         }
740 #endif
741
742         pArg->UpdateRequestId(req);
743
744         if (_AppImpl::GetInstance() != null)
745         {
746                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
747                 pArg->UpdateWindowHandle(handle);
748         }
749
750         int pid = -1;
751         bundle* kb = NULL;
752         String tempId;
753
754         actualAppId.SubString(0, 10, tempId);
755
756         const int type = _AppInfo::GetAppType();
757         if ((!(type & _APP_TYPE_SERVICE_APP)) && _IsDefaultApplication(tempId, appId))
758         {
759                 tempId += L'.';
760                 tempId += L"_AppControl";
761
762                 // [INFO] Ugly solution for submode support
763                 pArg->UpdateAppId(tempId);
764                 kb = pArg->GetBundle();
765
766                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
767                 if (pid >= 0)
768                 {
769                         SysLog(NID_APP, "Submode launch successful");
770                         SetLastResult(E_SUCCESS);
771                         return pid;
772                 }
773                 else if (pid == APPSVC_RET_EINVAL)
774                 {
775                         SetLastResult(E_MAX_EXCEEDED);
776                         return pid;
777                 }
778         }
779
780         pArg->UpdateAppId(actualAppId);
781
782         // retry for possible failure
783         int count = 0;
784         const int TRY_COUNT = 3;
785         const int TRY_SLEEP_TIME = 65;
786         do
787         {
788                 kb = pArg->GetBundle();
789                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
790                 if (pid >= 0)
791                 {
792                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
793                         SetLastResult(E_SUCCESS);
794                         return pid;
795                 }
796                 else if (pid == APPSVC_RET_EINVAL)
797                 {
798                         SetLastResult(E_MAX_EXCEEDED);
799                         return pid;
800                 }
801
802                 count++;
803                 SysLog(NID_APP, "Waiting %dth time with %d.", count, pid);
804                 Thread::Sleep(TRY_SLEEP_TIME);
805         }
806         while (count < TRY_COUNT);
807
808         result r = E_SUCCESS;
809         switch (pid)
810         {
811         case APPSVC_RET_EILLACC:
812                 r = E_ILLEGAL_ACCESS;
813                 break;
814         default:
815                 r = E_SYSTEM;
816                 break;
817         }
818
819         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
820
821         SetLastResult(r);
822
823         return pid;
824 }
825
826 result
827 _AppControlManager::LaunchAppImplicit(_AppArg* pArg, int req)
828 {
829         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
830
831         result r = E_SUCCESS;
832         bundle* kb = pArg->GetBundle();
833
834         if (req >= 0)
835         {
836                 pArg->UpdateRequestId(req);
837                 appsvc_add_data(kb, SELECTOR_NOTI_KEY, appinfo_get_appid());
838         }
839
840         if (_AppImpl::GetInstance() != null)
841         {
842                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
843                 _AppArg::UpdateWindowHandle(kb, handle);
844         }
845
846         int pid = appsvc_run_service(kb, req, LaunchResultCb, this);
847         if (pid >= 0)
848         {
849                 if (pid == 0)
850                 {
851                         SysLog(NID_APP, "Sending local process again.");
852                         pid = getpid();
853                 }
854
855                 char pkgname[255] = {0, };
856                 if (aul_app_get_pkgname_bypid(pid, pkgname, 255) != AUL_R_OK)
857                 {
858                         SysLog(NID_APP, "Fail to get package name by pid : (%d).", pid);
859                         return E_SYSTEM;
860                 }
861
862                 if (strncmp(pkgname, APP_SELECTOR, strlen(APP_SELECTOR)) != 0)
863                 {
864                         const char* pOperation = appsvc_get_operation(kb);
865
866                         SysLog(NID_APP, "Starting application without selector : (%s, %s).", pkgname, pOperation);
867
868                         SendAppControlStartResponse(req, pkgname, pOperation);
869                 }
870         }
871         else
872         {
873                 switch (pid)
874                 {
875                         case APPSVC_RET_EINVAL:
876                                 r = E_OBJ_NOT_FOUND;
877                                 break;
878                         case APPSVC_RET_ENOMATCH:
879                                 r = E_OBJ_NOT_FOUND;
880                                 break;
881                         case APPSVC_RET_EILLACC:
882                                 r = E_ILLEGAL_ACCESS;
883                                 break;
884                         case APPSVC_RET_ERROR:
885                                 // fall through
886                         case APPSVC_RET_ELAUNCH:
887                                 // fall through
888                         default:
889                                 r = E_SYSTEM;
890                                 break;
891                 }
892         }
893
894         SysLog(NID_APP, "[%s] Application(%d) launched with reqId(%d) and arg(0x%x).", GetErrorMessage(r), pid, req, pArg);
895
896         return r;
897 }
898
899 void
900 _AppControlManager::FinishAppControl(int reqId, int res, IMap* pMap)
901 {
902         SysLog(NID_APP, "req %d, res %d.", reqId, res);
903         _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap, _APPCONTROL_PROPERTY_SUBMODE);
904         SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
905
906         SendAppControlEvent(*pArg);
907         SysLog(NID_APP, "Exit.");
908 }
909
910 void
911 _AppControlManager::RemoveResultRequest(int reqId)
912 {
913         __resultManager.RemoveItem(reqId);
914 }
915
916 const _AppArg*
917 _AppControlManager::FindResultRequest(int reqId) const
918 {
919         const _ResultInfo* pInfo = __resultManager.FindItem(reqId);
920         return (pInfo) ? &(pInfo->arg) : null;
921 }
922
923 int
924 _AppControlManager::AddLaunchRequest(_AppArg* pArg, LaunchCbType pCb, void* pData, int prop)
925 {
926         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Empty argument.");
927
928         _LaunchInfo* pItem = new (std::nothrow) _LaunchInfo(pArg, pCb, pData, prop);
929         SysTryReturn(NID_APP, pItem != null, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
930
931         SysLog(NID_APP, "Registering callback 0x%x, 0x%x", pCb, pData);
932
933         return __launchManager.InsertItem(pItem);
934 }
935
936 void
937 _AppControlManager::RemoveLaunchRequest(int req)
938 {
939         __launchManager.RemoveItem(req);
940 }
941
942 result
943 _AppControlManager::RegisterRequest(service_s* service, int& req, _AppHandler& handler)
944 {
945         bundle* b = _AppArg::GetBundleFromSvc(service);
946
947         _AppArg* pArg = new (std::nothrow) _AppArg();
948         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "ArrayList creation failure.");
949         pArg->Construct(b);
950
951         result r = E_SUCCESS;
952
953         // ownership is transfered to RequestManager
954         _ResultInfo* pItem = new (std::nothrow) _ResultInfo(*pArg);
955         SysTryCatch(NID_APP, pItem != null, , r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
956
957         req = __resultManager.InsertItem(pItem);
958         SysTryCatch(NID_APP, req != -1, , r = E_INVALID_STATE, "[E_INVALID_STATE] Invalid argument handling state.");
959
960         handler = _AppArg::GetHandler(b);
961
962         return E_SUCCESS;
963
964 CATCH:
965         delete pArg;
966
967         return r;
968 }
969
970
971 bool
972 _AppControlManager::IsAllowedAppControl(const char aTable[][2][96], int count, const String& aId, const String& oId)
973 {
974         for (int i = 0; i < count; i++)
975         {
976                 if (aId == aTable[i][0] && oId == aTable[i][1])
977                 {
978                         SysLog(NID_APP, "Found entry (%s, %s)", aTable[i][0], aTable[i][1]);
979                         return true;
980                 }
981         }
982
983         return false;
984 }
985
986
987 AppCtrlResult
988 _AppControlManager::ConvertAppControlResultCode(int resCode)
989 {
990         AppCtrlResult ret = APP_CTRL_RESULT_FAILED;
991
992         switch(resCode)
993         {
994                 case SERVICE_RESULT_SUCCEEDED:
995                         ret = APP_CTRL_RESULT_SUCCEEDED;
996                         break;
997                 case SERVICE_RESULT_FAILED:
998                         ret = APP_CTRL_RESULT_CANCELED;
999                         break;
1000                 case SERVICE_RESULT_CANCELED:
1001                         ret = APP_CTRL_RESULT_ABORTED;
1002                         break;
1003                 case APPSVC_OSP_RES_FAIL:
1004                         ret = APP_CTRL_RESULT_FAILED;
1005                         break;
1006                 case APPSVC_OSP_RES_TERMINATE:
1007                         ret = APP_CTRL_RESULT_TERMINATED;
1008                         break;
1009                 default:
1010                         ret = APP_CTRL_RESULT_FAILED;
1011                         break;
1012         }
1013
1014         return ret;
1015 }
1016
1017
1018 void
1019 _AppControlManager::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
1020 {
1021         const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
1022
1023         if (pEventArg != null)
1024         {
1025                 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
1026
1027                 if(pResponseListener != null)
1028                 {
1029                         if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_START)
1030                         {
1031                                 pResponseListener->OnAppControlStartResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetResult());
1032                                 SysLog(NID_APP, "OnAppControlStartResponseReceived called");
1033                         }
1034                         else
1035                         {
1036                                 InvokeAppControlCompleteListener(*pResponseListener, pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData(), pEventArg->IsSubMode());
1037                                 SysLog(NID_APP, "Listener called");
1038
1039                                 _AppControlResponseEvent* pResponseEvent = null;
1040                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
1041                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
1042
1043                                 delete pResponseEvent;
1044                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
1045                         }
1046                 }
1047                 else
1048                 {
1049                         SysLog(NID_APP, "Invalid ResponseListener");
1050                 }
1051         }
1052         else
1053         {
1054                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
1055         }
1056 }
1057
1058 AppId
1059 _AppControlManager::GetAliasAppId(const AppId& appId)
1060 {
1061         return _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
1062 }
1063
1064 }} // Tizen::App