N_SE-36002 : fix submode for implicit resolution
[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 namespace Tizen { namespace App
80 {
81
82 const wchar_t TIZEN_OPERATION_PICK[] = L"http://tizen.org/appcontrol/operation/pick";
83 const wchar_t SELECTOR_NOTI_KEY[] = L"__APP_SVC_CALLER_NOTI__";
84 const int _MAX_PACKAGE_ID_LENGTH = 10;
85
86 _InProcessInfo::~_InProcessInfo(void)
87 {
88         delete pLib;
89 }
90
91 _LaunchInfo::~_LaunchInfo(void)
92 {
93         delete pArg;
94 }
95
96
97 _AppControlManager::_AppControlManager(void)
98 {
99         SysLog(NID_APP, "");
100
101         // AppControl event handling is expected to be performed in the main thread.
102         __appControlEvent.Construct();
103         __appControlEvent.AddListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
104         __listenerList.Construct();
105         __pAppControlResponseEventContainer = new (std::nothrow)HashMapT<int, _AppControlResponseEvent*>;
106         __pAppControlResponseEventContainer->Construct();
107         __appControlResponseEventList.Construct();
108 }
109
110 _AppControlManager::~_AppControlManager(void)
111 {
112         SysLog(NID_APP, "");
113         __appControlEvent.RemoveListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
114         IEnumeratorT<int>* pEnum = __appControlResponseEventList.GetEnumeratorN();
115
116         if (pEnum != null)
117         {
118                 while(pEnum->MoveNext() == E_SUCCESS)
119                 {
120                         int reqId;
121                         pEnum->GetCurrent(reqId);
122                         if (__pAppControlResponseEventContainer != null)
123                         {
124                                 _AppControlResponseEvent* pResponseEvent = null;
125                                 __pAppControlResponseEventContainer->GetValue(reqId, pResponseEvent);
126                                 delete pResponseEvent;
127
128                                 __pAppControlResponseEventContainer->Remove(reqId);
129                                 SysLog(NID_APP, "pResponseEvent gets deleted. reqId(%d)", reqId);
130                         }
131                 }
132         }
133         delete __pAppControlResponseEventContainer;
134         delete pEnum;
135 }
136
137 _AppControlManager*
138 _AppControlManager::GetInstance(void)
139 {
140         static _AppControlManager inst;
141
142         return &inst;
143 }
144
145 result
146 _AppControlManager::GetMimeFromExt(const String& ext, String& out)
147 {
148         std::unique_ptr<char[]> pExtension(_StringConverter::CopyToCharArrayN(ext));
149         SysTryReturnResult(NID_APP, pExtension != null, E_OUT_OF_MEMORY, "String allocation failure.");
150
151         char* mime = NULL;
152         mime_type_get_mime_type(pExtension.get(), &mime);
153
154         SysTryReturnResult(NID_APP, mime != NULL, E_UNSUPPORTED_FORMAT, "MIME type conversion failure for %ls.", ext.GetPointer());
155
156         out = mime;
157         free(mime);
158
159         return E_SUCCESS;
160 }
161
162 void
163 _AppControlManager::OnAppControlEventReceivedN(int reqId, _AppArg* pAppArg, int res)
164 {
165         SysLog(NID_APP, "Received request Id %d, arg 0x%x", reqId, pAppArg);
166
167         //_AppArg::Print(b);
168         // get launch info from request Id
169         _LaunchInfo* pInfo = __launchManager.FindItem(reqId);
170         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with response %d", reqId,
171                                         res);
172
173         // invoke callback
174         if (pInfo->launchCb)
175         {
176                 if (pInfo->magic == LAUNCH_INFO_MAGIC)
177                 {
178                         SysLog(NID_APP, "Invoking callback 0x%x", pInfo->launchCb);
179                         //pAppArg->Print();
180
181                         if (pInfo->pUserData && (!__listenerList.Contains(pInfo->pUserData)))
182                         {
183                                 (*pInfo->launchCb)(pInfo->pUserData, pInfo->pArg, pAppArg, static_cast<service_result_e>(res), pInfo->property, reqId);
184                         }
185                 }
186                 else
187                 {
188                         SysLogException(NID_APP, E_SYSTEM, "Corrupted data structure.");
189                 }
190         }
191
192         // clean up argument
193         __launchManager.RemoveItem(reqId);
194 }
195
196
197 // callback for out-of-process AppControl start event
198 void
199 _AppControlManager::OnAppControlEventReceivedN(int reqId, const AppId& appId, const String& operationId)
200 {
201         SysLog(NID_APP, "Received request Id %d, app %ls, operationId %ls", reqId, appId.GetPointer(), operationId.GetPointer());
202
203         // get launch info from request Id
204         _LaunchInfo* pInfo = __launchManager.FindItem(reqId);
205         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found.", reqId);
206
207         // at least listener
208         IAppControlResponseListener* pListener = static_cast<IAppControlResponseListener*>(pInfo->pUserData);
209         SysTryReturnVoidResult(NID_APP, typeid(pListener) == typeid(IAppControlResponseListener*), E_SYSTEM, "[E_SYSTEM] Invalid result callback.");
210
211         if (pListener)
212         {
213                 result r = E_SUCCESS;
214                 AppId actualAppId = appId;
215                 if (appId == L'c')
216                 {
217                         actualAppId.Clear();
218                         r = E_OPERATION_CANCELED;
219                 }
220                 SysLog(NID_APP, "Invoking callback 0x%x.", pListener);
221
222                 _AppControlResponseEvent* pResponseEvent = null;
223                 __pAppControlResponseEventContainer->GetValue(reqId, pResponseEvent);
224                 SysLog(NID_APP, "StartResponseReceived Request Id(%d), ResponseEvent 0x%x.", reqId, pResponseEvent);
225                 if (pResponseEvent != null)
226                 {
227                         String oId(operationId);
228                         _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_START, actualAppId, oId, r, APP_CTRL_RESULT_SUCCEEDED, null, reqId);
229
230                         if (pResponseEventArg != null)
231                         {
232                                 pResponseEvent->Fire(*pResponseEventArg);
233                                 SysLog(NID_APP, "pResponseEvent is Fired");
234                         }
235                 }
236                 else
237                 {
238                         pListener->OnAppControlStartResponseReceived(actualAppId, operationId, r);
239                         SysLog(NID_APP, "OnAppControlStartResponseReceived called directly");
240                 }
241         }
242         else
243         {
244                 SysLog(NID_APP, "No listener registered.");
245         }
246 }
247
248
249 // callback for in-process event handling
250 void
251 _AppControlManager::OnAppControlEventReceivedN(int reqId, int res, const IMap* pArgs)
252 {
253         SysLog(NID_APP, "Received request Id %d, res %d, args 0x%x", reqId, res, pArgs);
254
255         // process proper callback
256         _InProcessInfo* pInfo = __inAppManager.FindItem(reqId);
257         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with args 0x%x", reqId,
258                                         pArgs);
259
260         if (pInfo->pListener)
261         {
262                 String aId = pInfo->providerId;
263                 String oId = pInfo->operationId;
264
265                 SysLog(NID_APP, "Invoking callback 0x%x for (%ls, %ls).", pInfo->pListener, aId.GetPointer(), oId.GetPointer());
266
267                 if (pInfo->property & _APPCONTROL_PROPERTY_ALIAS)
268                 {
269                         const _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
270                         pEntry = _AppControlRegistry::GetInstance()->GetReverseAppControlAliasEntry(aId, oId);
271                         if (pEntry)
272                         {
273                                 aId = pEntry->provider;
274                                 oId = pEntry->operation;
275
276                                 SysLog(NID_APP, "Legacy AppControl name (%ls, %ls).", aId.GetPointer(), oId.GetPointer());
277                         }
278                 }
279
280                 if (pInfo->isLegacy)
281                 {
282                         IAppControlEventListener* pListener = dynamic_cast<IAppControlEventListener*>(pInfo->pListener);
283                         if (pListener)
284                         {
285                                 ArrayList list(SingleObjectDeleter);
286                                 _AppArg::FillLegacyAppControlResult(list, res, pArgs, aId);
287
288                                 pListener->OnAppControlCompleted(aId, oId, &list);
289                         }
290                         else
291                         {
292                                 SysLog(NID_APP, "Wrong AppControl listener type.");
293                         }
294                 }
295                 else
296                 {
297                         IAppControlResponseListener* pListener = dynamic_cast<IAppControlResponseListener*>(pInfo->pListener);
298                         if (pListener && (!__listenerList.Contains(pInfo->pListener)))
299                         {
300                                 _AppControlResponseEvent* pResponseEvent = null;
301                                 int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + reqId;
302                                 __pAppControlResponseEventContainer->GetValue(responseEventRequestId, pResponseEvent);
303
304                                 if (pResponseEvent != null)
305                                 {
306                                         _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_COMPLETE, aId, oId, E_SUCCESS, static_cast<AppCtrlResult>(res), const_cast<IMap*> (pArgs), responseEventRequestId);
307                                         if (pResponseEventArg != null)
308                                         {
309                                                 pResponseEvent->Fire(*pResponseEventArg);
310                                                 SysLog(NID_APP, "pResponseEvent is Fired");
311                                         }
312                                 }
313                                 else
314                                 {
315                                         pListener->OnAppControlCompleteResponseReceived(aId, oId, ConvertAppControlResultCode(res), pArgs);
316                                         SysLog(NID_APP, "OnAppControlCompleteResponseReceived called directly");
317                                         IMap* pMap = const_cast<IMap*> (pArgs);
318                                         delete pMap;
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 int
510 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const AppId& appId, const String& opId, const String* pUri, const String* pMime, AppSvcResFn pCb, void* data)
511 {
512         std::unique_ptr<char[]> pPackage(_StringConverter::CopyToCharArrayN(appId));
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         int pid = Launch(msg, pPackage.get(), pOperation.get(), pMimeData, pUriData, pCb, data);
528
529         delete [] pUriData;
530         delete [] pMimeData;
531
532         return pid;
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, "App: %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
665 int
666 _AppControlManager::Launch(const _AppMessageImpl& msg, const AppId& aId, const String& oId, const String* pUriData, const String* pMimeType, AppSvcResFn pCb, void* pData)
667 {
668         SysLog(NID_APP, "Enter");
669
670         _AppArg arg;
671         arg.Construct(msg, oId, pUriData, pMimeType);
672
673         int pid = Launch(aId, &arg, pCb, pData, -1); 
674         SysTryReturn(NID_APP, pid >= 0, -1, GetLastResult(), "Launching(%ls) is failed", aId.GetPointer());
675
676         SysLog(NID_APP, "Exit");
677
678         return pid;
679 }
680
681
682 int
683 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
684 {
685         return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
686 }
687
688
689 int
690 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, AppSvcResFn pCb, void* pData, int req)
691 {
692         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Invalid launch argument");
693         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
694
695         String actualAppId = appId;
696         if (appId.GetLength() == 10)
697         {
698                 const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
699
700                 if (!execName.IsEmpty())
701                 {
702                         actualAppId.Append(L'.');
703                         actualAppId.Append(execName);
704                 }
705         }
706
707         pArg->UpdateRequestId(req);
708
709         if (_AppImpl::GetInstance() != null)
710         {
711                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
712                 pArg->UpdateWindowHandle(handle);
713         }
714
715         int pid = -1;
716         bundle* kb = NULL;
717         String tempId;
718
719         actualAppId.SubString(0, 10, tempId);
720
721         if (_IsDefaultApplication(tempId, appId))
722         {
723                 tempId += L'.';
724                 tempId += L"_AppControl";
725
726                 // [INFO] Ugly solution for submode support
727                 pArg->UpdateAppId(tempId);
728                 kb = pArg->GetBundle();
729
730                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
731                 if (pid > 0)
732                 {
733                         SysLog(NID_APP, "Submode launch successful");
734                         return pid;
735                 }
736         }
737
738         pArg->UpdateAppId(actualAppId);
739
740         // retry for possible failure
741         int count = 0;
742         const int TRY_COUNT = 3;
743         const int TRY_SLEEP_TIME = 65;
744         do
745         {
746                 kb = pArg->GetBundle();
747                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
748                 if (pid > 0)
749                 {
750                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
751                         return pid;
752                 }
753                 count++;
754                 SysLog(NID_APP, "Waiting %dth time.", count);
755                 Thread::Sleep(TRY_SLEEP_TIME);
756         }
757         while (count < TRY_COUNT);
758
759         result r = E_SUCCESS;
760         switch (pid)
761         {
762         case APPSVC_RET_EILLACC:
763                 r = E_ILLEGAL_ACCESS;
764                 break;
765         default:
766                 r = E_SYSTEM;
767                 break;
768         }
769
770         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
771
772         SetLastResult(r);
773
774         return pid;
775 }
776
777 result
778 _AppControlManager::LaunchAppImplicit(_AppArg* pArg, int req)
779 {
780         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
781
782         result r = E_SUCCESS;
783         bundle* kb = pArg->GetBundle();
784
785         if (req >= 0)
786         {
787                 pArg->UpdateRequestId(req);
788                 _AppMessageImpl::AddData(kb, SELECTOR_NOTI_KEY, _AppInfo::GetApplicationId());
789         }
790
791         if (_AppImpl::GetInstance() != null)
792         {
793                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
794                 _AppArg::UpdateWindowHandle(kb, handle);
795         }
796
797         int pid = appsvc_run_service(kb, req, LaunchResultCb, this);
798         if (pid > 0)
799         {
800                 char pkgname[255] = {0, };
801                 aul_app_get_pkgname_bypid(pid, pkgname, 255);
802
803                 if (strncmp(pkgname, APP_SELECTOR, strlen(APP_SELECTOR)) != 0)
804                 {
805                         const char* pOperation = appsvc_get_operation(kb);
806
807                         SysLog(NID_APP, "Starting application without selector : (%s, %s).", pkgname, pOperation);
808
809                         SendAppControlStartResponse(req, pkgname, pOperation);
810                 }
811         }
812         else
813         {
814                 switch (pid)
815                 {
816                         case APPSVC_RET_EINVAL:
817                                 r = E_OBJ_NOT_FOUND;
818                                 break;
819                         case APPSVC_RET_ENOMATCH:
820                                 r = E_OBJ_NOT_FOUND;
821                                 break;
822                         case APPSVC_RET_EILLACC:
823                                 r = E_ILLEGAL_ACCESS;
824                                 break;
825                         case APPSVC_RET_ERROR:
826                                 // fall through
827                         case APPSVC_RET_ELAUNCH:
828                                 // fall through
829                         default:
830                                 r = E_SYSTEM;
831                                 break;
832                 }
833         }
834
835         SysLog(NID_APP, "[%s] Application(%d) launched with reqId(%d) and arg(0x%x).", GetErrorMessage(r), pid, req, pArg);
836
837         return r;
838 }
839
840 void
841 _AppControlManager::FinishAppControl(int reqId, int res, IMap* pMap)
842 {
843         SysLog(NID_APP, "req %d, res %d.", reqId, res);
844         _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap);
845         SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
846
847         SendAppControlEvent(*pArg);
848         SysLog(NID_APP, "Exit.");
849 }
850
851 const _AppArg*
852 _AppControlManager::FindResultRequest(int reqId) const
853 {
854         const _ResultInfo* pInfo = __resultManager.FindItem(reqId);
855         return (pInfo) ? &(pInfo->arg) : null;
856 }
857
858 int
859 _AppControlManager::AddLaunchRequest(_AppArg* pArg, LaunchCbType pCb, void* pData, int prop)
860 {
861         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Empty argument.");
862
863         _LaunchInfo* pItem = new (std::nothrow) _LaunchInfo(pArg, pCb, pData, prop);
864         SysTryReturn(NID_APP, pItem != null, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
865
866         SysLog(NID_APP, "Registering callback 0x%x, 0x%x", pCb, pData);
867
868         return __launchManager.InsertItem(pItem);
869 }
870
871 void
872 _AppControlManager::RemoveLaunchRequest(int req)
873 {
874         __launchManager.RemoveItem(req);
875 }
876 int
877 _AppControlManager::GetLaunchRequestCount(void)
878 {
879         return __launchManager.GetCount();
880 }
881
882 result
883 _AppControlManager::RegisterRequest(service_s* service, int& req, _AppHandler& handler)
884 {
885         bundle* b = _AppArg::GetBundleFromSvc(service);
886
887         _AppArg* pArg = new (std::nothrow) _AppArg();
888         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "ArrayList creation failure.");
889         pArg->Construct(b);
890
891         result r = E_SUCCESS;
892
893         // ownership is transfered to RequestManager
894         _ResultInfo* pItem = new (std::nothrow) _ResultInfo(*pArg);
895         SysTryCatch(NID_APP, pItem != null, , r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
896
897         req = __resultManager.InsertItem(pItem);
898         SysTryCatch(NID_APP, req != -1, , r = E_INVALID_STATE, "[E_INVALID_STATE] Invalid argument handling state.");
899
900         handler = _AppArg::GetHandler(b);
901
902         return E_SUCCESS;
903
904 CATCH:
905         delete pArg;
906
907         return r;
908 }
909
910
911 bool
912 _AppControlManager::IsAllowedAppControl(const char aTable[][2][96], int count, const String& aId, const String& oId)
913 {
914         for (int i = 0; i < count; i++)
915         {
916                 if (aId == aTable[i][0] && oId == aTable[i][1])
917                 {
918                         SysLog(NID_APP, "Found entry (%s, %s)", aTable[i][0], aTable[i][1]);
919                         return true;
920                 }
921         }
922
923         return false;
924 }
925
926
927 AppCtrlResult
928 _AppControlManager::ConvertAppControlResultCode(int resCode)
929 {
930         AppCtrlResult ret = APP_CTRL_RESULT_FAILED;
931
932         switch(resCode)
933         {
934                 case SERVICE_RESULT_SUCCEEDED:
935                         ret = APP_CTRL_RESULT_SUCCEEDED;
936                         break;
937                 case SERVICE_RESULT_FAILED:
938                         ret = APP_CTRL_RESULT_CANCELED;
939                         break;
940                 case SERVICE_RESULT_CANCELED:
941                         ret = APP_CTRL_RESULT_ABORTED;
942                         break;
943                 case APPSVC_OSP_RES_FAIL:
944                         ret = APP_CTRL_RESULT_FAILED;
945                         break;
946                 case APPSVC_OSP_RES_TERMINATE:
947                         ret = APP_CTRL_RESULT_TERMINATED;
948                         break;
949                 default:
950                         ret = APP_CTRL_RESULT_FAILED;
951                         break;
952         }
953
954         return ret;
955 }
956
957
958 void
959 _AppControlManager::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
960 {
961         const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
962
963         if (pEventArg != null)
964         {
965                 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
966
967                 if(pResponseListener != null)
968                 {
969                         if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_START)
970                         {
971                                 pResponseListener->OnAppControlStartResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetResult());
972                                 SysLog(NID_APP, "OnAppControlStartResponseReceived called");
973                         }
974                         else
975                         {
976                                 pResponseListener->OnAppControlCompleteResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData());
977                                 SysLog(NID_APP, "OnAppControlCompleteResponseReceived called");
978
979                                 _AppControlResponseEvent* pResponseEvent = null;
980                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
981                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
982
983                                 delete pResponseEvent;
984                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
985                         }
986                 }
987                 else
988                 {
989                         SysLog(NID_APP, "Invalid ResponseListener");
990                 }
991         }
992         else
993         {
994                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
995         }
996 }
997
998 AppId
999 _AppControlManager::GetAliasAppId(const AppId& appId)
1000 {
1001         return _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
1002 }
1003
1004 }} // Tizen::App