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