fix AppControl E_MAX_EXCEEDED result
[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                 case APPSVC_RET_EINVAL:
446                         r = E_MAX_EXCEEDED;
447                         break;
448                 default:
449                         r = E_SYSTEM;
450                         break;
451                 }
452                 SysLog(NID_APP, "[%s] Launching service %s failure", GetErrorMessage(r), pkg_name);
453         }
454
455         return r;
456 }
457
458
459 int
460 _AppControlManager::Launch(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
461 {
462         bundle* kb = msg.GetBundle();
463         SysTryReturn(NID_APP, kb != NULL, -1, E_OUT_OF_MEMORY, "Bundle allocation failure.");
464
465         if (pkg_name)
466         {
467                 appsvc_set_pkgname(kb, pkg_name);
468         }
469
470         appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
471
472         if (mime)
473         {
474                 appsvc_set_mime(kb, mime);
475         }
476
477         if (uri)
478         {
479                 appsvc_set_uri(kb, uri);
480         }
481
482         if (_AppImpl::GetInstance() != null)
483         {
484                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
485                 _AppArg::UpdateWindowHandle(kb, handle);
486         }
487
488         SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
489         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
490
491         result r = E_SUCCESS;
492         if (pid < 0)
493         {
494                 switch (pid)
495                 {
496                 case APPSVC_RET_EILLACC:
497                         r = E_ILLEGAL_ACCESS;
498                         break;
499                 case APPSVC_RET_EINVAL:
500                         r = E_MAX_EXCEEDED;
501                         break;
502                 default:
503                         r = E_SYSTEM;
504                         break;
505                 }
506                 SysLog(NID_APP, "[%s]Launching service %s failure", GetErrorMessage(r), pkg_name);
507         }
508         SetLastResult(r);
509
510         return pid;
511 }
512
513
514 int
515 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const AppId& appId, const String& opId, const String* pUri, const String* pMime, AppSvcResFn pCb, void* data)
516 {
517         std::unique_ptr<char[]> pPackage(_StringConverter::CopyToCharArrayN(appId));
518         std::unique_ptr<char[]> pOperation(_StringConverter::CopyToCharArrayN(opId));
519
520         const char* pUriData = null;
521         if (pUri)
522         {
523                 pUriData =  _StringConverter::CopyToCharArrayN(*pUri);
524         }
525
526         const char* pMimeData = null;
527         if (pMime)
528         {
529                 pMimeData = _StringConverter::CopyToCharArrayN(*pMime);
530         }
531
532         int pid = Launch(msg, pPackage.get(), pOperation.get(), pMimeData, pUriData, pCb, data);
533
534         delete [] pUriData;
535         delete [] pMimeData;
536
537         return pid;
538 }
539
540
541 result
542 _AppControlManager::LaunchPkg(const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
543 {
544         _AppMessageImpl msg;
545
546         return LaunchPkg(msg, pkg_name, op, mime, uri, pCb, data);
547 }
548
549 result
550 _AppControlManager::LaunchAppWithCondition(const AppId& appId, const String& condition, IList* pArrayArgs)
551 {
552         result r = E_SUCCESS;
553         _AppArg * pArg = new (std::nothrow) _AppArg();
554         SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]");
555
556         r = pArg->ConstructForAppLaunchCondition(condition, pArrayArgs);
557         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] ConstructForAppLaunchCondition(%ls, .. ) fails", GetErrorMessage(r), condition.GetPointer());
558
559         r = _AppControlManager::LaunchApp(appId, pArg);
560 CATCH:
561         delete pArg;
562         return r;
563 }
564
565 result
566 _AppControlManager::LaunchApp(const AppId& appId, _AppArg* pArg, int req)
567 {
568         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
569         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
570
571         String actualAppId = appId;
572         if (appId.GetLength() == 10)
573         {
574                 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
575
576                 if (!name.IsEmpty())
577                 {
578                         actualAppId.Append(L'.');
579                         actualAppId.Append(name);
580                 }
581         }
582
583         pArg->UpdateRequestId(req);
584
585         if (_AppImpl::GetInstance() != null)
586         {
587                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
588                 pArg->UpdateWindowHandle(handle);
589         }
590
591         int pid = -1;
592         bundle* kb = NULL;
593         String tempId;
594         actualAppId.SubString(0, 10, tempId);
595         tempId += L'.';
596         tempId += L"_AppControl";
597
598         // [INFO] Ugly solution for submode support
599         pArg->UpdateAppId(tempId);
600         kb = pArg->GetBundle();
601         
602         pid = appsvc_run_service(kb, req, LaunchResultCb, this);
603         if (pid >= 0)
604         {
605                 SysLog(NID_APP, "Submode launch successful");
606                 return E_SUCCESS;
607         }
608         else if (pid == APPSVC_RET_EINVAL)
609         {
610                 SysLog(NID_APP, "Argument overflow");
611                 return E_MAX_EXCEEDED;
612         }
613
614         pArg->UpdateAppId(actualAppId);
615
616         // retry for possible failure
617         int count = 0;
618         const int TRY_COUNT = 3;
619         const int TRY_SLEEP_TIME = 65;
620         do
621         {
622                 kb = pArg->GetBundle();
623                 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
624                 if (pid >= 0)
625                 {
626                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
627                         return E_SUCCESS;
628                 }
629                 else if (pid == APPSVC_RET_EINVAL)
630                 {
631                         SysLog(NID_APP, "Argument overflow");
632                         return E_MAX_EXCEEDED;
633                 }
634
635                 count++;
636                 SysLog(NID_APP, "Waiting %dth time.", count);
637                 Thread::Sleep(TRY_SLEEP_TIME);
638         }
639         while (count < TRY_COUNT);
640
641         result r = E_SUCCESS;
642         switch (pid)
643         {
644         case APPSVC_RET_EILLACC:
645                 r = E_ILLEGAL_ACCESS;
646                 break;
647         case APPSVC_RET_EINVAL:
648                 r = E_MAX_EXCEEDED;
649                 break;
650         default:
651                 r = E_SYSTEM;
652                 break;
653         }
654
655         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
656
657         return r;
658 }
659
660 static bool
661 _IsDefaultApplication(const AppId& packageId, const String& appId)
662 {
663         const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
664
665         int index = -1;
666         result r = appId.IndexOf(L'.', 0, index);
667         if (r != E_SUCCESS)
668         {
669                 return false;
670         }
671
672         String tmp;
673         appId.SubString(index + 1, tmp);
674         if (tmp == execName)
675         {
676                 SysLog(NID_APP, "Default application %ls", tmp.GetPointer());
677                 return true;
678         }
679
680         return false;
681 }
682
683
684 int
685 _AppControlManager::Launch(const _AppMessageImpl& msg, const AppId& aId, const String& oId, const String* pUriData, const String* pMimeType, AppSvcResFn pCb, void* pData)
686 {
687         SysLog(NID_APP, "Enter");
688
689         _AppArg arg;
690         arg.Construct(msg, oId, pUriData, pMimeType);
691
692         int pid = Launch(aId, &arg, pCb, pData, -1); 
693         SysTryReturn(NID_APP, pid >= 0, -1, GetLastResult(), "Launching(%ls) is failed", aId.GetPointer());
694
695         SysLog(NID_APP, "Exit");
696
697         return pid;
698 }
699
700
701 int
702 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
703 {
704         return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
705 }
706
707
708 int
709 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, AppSvcResFn pCb, void* pData, int req)
710 {
711         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Invalid launch argument");
712         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
713
714         String actualAppId = appId;
715         if (appId.GetLength() == 10)
716         {
717                 const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
718
719                 if (!execName.IsEmpty())
720                 {
721                         actualAppId.Append(L'.');
722                         actualAppId.Append(execName);
723                 }
724         }
725
726         pArg->UpdateRequestId(req);
727
728         if (_AppImpl::GetInstance() != null)
729         {
730                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
731                 pArg->UpdateWindowHandle(handle);
732         }
733
734         int pid = -1;
735         bundle* kb = NULL;
736         String tempId;
737
738         actualAppId.SubString(0, 10, tempId);
739
740         if (_IsDefaultApplication(tempId, appId))
741         {
742                 tempId += L'.';
743                 tempId += L"_AppControl";
744
745                 // [INFO] Ugly solution for submode support
746                 pArg->UpdateAppId(tempId);
747                 kb = pArg->GetBundle();
748
749                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
750                 if (pid >= 0)
751                 {
752                         SysLog(NID_APP, "Submode launch successful");
753                         return pid;
754                 }
755                 else if (pid == APPSVC_RET_EINVAL)
756                 {
757                         SetLastResult(E_MAX_EXCEEDED);
758                         return pid;
759                 }
760         }
761
762         pArg->UpdateAppId(actualAppId);
763
764         // retry for possible failure
765         int count = 0;
766         const int TRY_COUNT = 3;
767         const int TRY_SLEEP_TIME = 65;
768         do
769         {
770                 kb = pArg->GetBundle();
771                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
772                 if (pid >= 0)
773                 {
774                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
775                         return pid;
776                 }
777                 else if (pid == APPSVC_RET_EINVAL)
778                 {
779                         SetLastResult(E_MAX_EXCEEDED);
780                         return pid;
781                 }
782
783                 count++;
784                 SysLog(NID_APP, "Waiting %dth time with %d.", count, pid);
785                 Thread::Sleep(TRY_SLEEP_TIME);
786         }
787         while (count < TRY_COUNT);
788
789         result r = E_SUCCESS;
790         switch (pid)
791         {
792         case APPSVC_RET_EILLACC:
793                 r = E_ILLEGAL_ACCESS;
794                 break;
795         case APPSVC_RET_EINVAL:
796                 r = E_MAX_EXCEEDED;
797                 break;
798         default:
799                 r = E_SYSTEM;
800                 break;
801         }
802
803         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
804
805         SetLastResult(r);
806
807         return pid;
808 }
809
810 result
811 _AppControlManager::LaunchAppImplicit(_AppArg* pArg, int req)
812 {
813         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
814
815         result r = E_SUCCESS;
816         bundle* kb = pArg->GetBundle();
817
818         if (req >= 0)
819         {
820                 pArg->UpdateRequestId(req);
821                 _AppMessageImpl::AddData(kb, SELECTOR_NOTI_KEY, _AppInfo::GetApplicationId());
822         }
823
824         if (_AppImpl::GetInstance() != null)
825         {
826                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
827                 _AppArg::UpdateWindowHandle(kb, handle);
828         }
829
830         int pid = appsvc_run_service(kb, req, LaunchResultCb, this);
831         if (pid >= 0)
832         {
833                 if (pid == 0)
834                 {
835                         SysLog(NID_APP, "Sending local process again.");
836                         pid = getpid();
837                 }
838
839                 char pkgname[255] = {0, };
840                 aul_app_get_pkgname_bypid(pid, pkgname, 255);
841
842                 if (strncmp(pkgname, APP_SELECTOR, strlen(APP_SELECTOR)) != 0)
843                 {
844                         const char* pOperation = appsvc_get_operation(kb);
845
846                         SysLog(NID_APP, "Starting application without selector : (%s, %s).", pkgname, pOperation);
847
848                         SendAppControlStartResponse(req, pkgname, pOperation);
849                 }
850         }
851         else
852         {
853                 switch (pid)
854                 {
855                         case APPSVC_RET_EINVAL:
856                                 r = E_OBJ_NOT_FOUND;
857                                 break;
858                         case APPSVC_RET_ENOMATCH:
859                                 r = E_OBJ_NOT_FOUND;
860                                 break;
861                         case APPSVC_RET_EILLACC:
862                                 r = E_ILLEGAL_ACCESS;
863                                 break;
864                         case APPSVC_RET_ERROR:
865                                 // fall through
866                         case APPSVC_RET_ELAUNCH:
867                                 // fall through
868                         default:
869                                 r = E_SYSTEM;
870                                 break;
871                 }
872         }
873
874         SysLog(NID_APP, "[%s] Application(%d) launched with reqId(%d) and arg(0x%x).", GetErrorMessage(r), pid, req, pArg);
875
876         return r;
877 }
878
879 void
880 _AppControlManager::FinishAppControl(int reqId, int res, IMap* pMap)
881 {
882         SysLog(NID_APP, "req %d, res %d.", reqId, res);
883         _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap);
884         SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
885
886         SendAppControlEvent(*pArg);
887         SysLog(NID_APP, "Exit.");
888 }
889
890 const _AppArg*
891 _AppControlManager::FindResultRequest(int reqId) const
892 {
893         const _ResultInfo* pInfo = __resultManager.FindItem(reqId);
894         return (pInfo) ? &(pInfo->arg) : null;
895 }
896
897 int
898 _AppControlManager::AddLaunchRequest(_AppArg* pArg, LaunchCbType pCb, void* pData, int prop)
899 {
900         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Empty argument.");
901
902         _LaunchInfo* pItem = new (std::nothrow) _LaunchInfo(pArg, pCb, pData, prop);
903         SysTryReturn(NID_APP, pItem != null, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
904
905         SysLog(NID_APP, "Registering callback 0x%x, 0x%x", pCb, pData);
906
907         return __launchManager.InsertItem(pItem);
908 }
909
910 void
911 _AppControlManager::RemoveLaunchRequest(int req)
912 {
913         __launchManager.RemoveItem(req);
914 }
915
916 result
917 _AppControlManager::RegisterRequest(service_s* service, int& req, _AppHandler& handler)
918 {
919         bundle* b = _AppArg::GetBundleFromSvc(service);
920
921         _AppArg* pArg = new (std::nothrow) _AppArg();
922         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "ArrayList creation failure.");
923         pArg->Construct(b);
924
925         result r = E_SUCCESS;
926
927         // ownership is transfered to RequestManager
928         _ResultInfo* pItem = new (std::nothrow) _ResultInfo(*pArg);
929         SysTryCatch(NID_APP, pItem != null, , r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
930
931         req = __resultManager.InsertItem(pItem);
932         SysTryCatch(NID_APP, req != -1, , r = E_INVALID_STATE, "[E_INVALID_STATE] Invalid argument handling state.");
933
934         handler = _AppArg::GetHandler(b);
935
936         return E_SUCCESS;
937
938 CATCH:
939         delete pArg;
940
941         return r;
942 }
943
944
945 bool
946 _AppControlManager::IsAllowedAppControl(const char aTable[][2][96], int count, const String& aId, const String& oId)
947 {
948         for (int i = 0; i < count; i++)
949         {
950                 if (aId == aTable[i][0] && oId == aTable[i][1])
951                 {
952                         SysLog(NID_APP, "Found entry (%s, %s)", aTable[i][0], aTable[i][1]);
953                         return true;
954                 }
955         }
956
957         return false;
958 }
959
960
961 AppCtrlResult
962 _AppControlManager::ConvertAppControlResultCode(int resCode)
963 {
964         AppCtrlResult ret = APP_CTRL_RESULT_FAILED;
965
966         switch(resCode)
967         {
968                 case SERVICE_RESULT_SUCCEEDED:
969                         ret = APP_CTRL_RESULT_SUCCEEDED;
970                         break;
971                 case SERVICE_RESULT_FAILED:
972                         ret = APP_CTRL_RESULT_CANCELED;
973                         break;
974                 case SERVICE_RESULT_CANCELED:
975                         ret = APP_CTRL_RESULT_ABORTED;
976                         break;
977                 case APPSVC_OSP_RES_FAIL:
978                         ret = APP_CTRL_RESULT_FAILED;
979                         break;
980                 case APPSVC_OSP_RES_TERMINATE:
981                         ret = APP_CTRL_RESULT_TERMINATED;
982                         break;
983                 default:
984                         ret = APP_CTRL_RESULT_FAILED;
985                         break;
986         }
987
988         return ret;
989 }
990
991
992 void
993 _AppControlManager::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
994 {
995         const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
996
997         if (pEventArg != null)
998         {
999                 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
1000
1001                 if(pResponseListener != null)
1002                 {
1003                         if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_START)
1004                         {
1005                                 pResponseListener->OnAppControlStartResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetResult());
1006                                 SysLog(NID_APP, "OnAppControlStartResponseReceived called");
1007                         }
1008                         else
1009                         {
1010                                 pResponseListener->OnAppControlCompleteResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData());
1011                                 SysLog(NID_APP, "OnAppControlCompleteResponseReceived called");
1012
1013                                 _AppControlResponseEvent* pResponseEvent = null;
1014                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
1015                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
1016
1017                                 delete pResponseEvent;
1018                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
1019                         }
1020                 }
1021                 else
1022                 {
1023                         SysLog(NID_APP, "Invalid ResponseListener");
1024                 }
1025         }
1026         else
1027         {
1028                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
1029         }
1030 }
1031
1032 AppId
1033 _AppControlManager::GetAliasAppId(const AppId& appId)
1034 {
1035         return _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
1036 }
1037
1038 }} // Tizen::App