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