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