Merge "Add a _LocalizedNumParser class and 4 static functions" 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 void
249 _AppControlManager::InvokeAppControlCompleteListener(IAppControlResponseListener& listener, const AppId& appId, const String& op, AppCtrlResult res, const IMap* pExtraData)
250 {
251         listener.OnAppControlCompleteResponseReceived(appId, op, res, pExtraData);
252
253         _AppImpl::GetInstance()->RaiseWindow();
254
255         SysLog(NID_APP, "AppControl response finished.");
256 }
257
258
259 void
260 _AppControlManager::InvokeLegacyAppControlCompleteListener(IAppControlEventListener& listener, const AppId& appId, const String& op, const IList* pList)
261 {
262         listener.OnAppControlCompleted(appId, op, pList);
263
264         _AppImpl::GetInstance()->RaiseWindow();
265         SysLog(NID_APP, "Legacy AppControl response finished.");
266 }
267
268
269 // callback for in-process event handling
270 void
271 _AppControlManager::OnAppControlEventReceivedN(int reqId, int res, const IMap* pArgs)
272 {
273         SysLog(NID_APP, "Received request Id %d, res %d, args 0x%x", reqId, res, pArgs);
274
275         // process proper callback
276         _InProcessInfo* pInfo = __inAppManager.FindItem(reqId);
277         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with args 0x%x", reqId,
278                                         pArgs);
279
280         if (pInfo->pListener)
281         {
282                 String aId = pInfo->providerId;
283                 String oId = pInfo->operationId;
284
285                 SysLog(NID_APP, "Invoking callback 0x%x for (%ls, %ls).", pInfo->pListener, aId.GetPointer(), oId.GetPointer());
286
287                 if (pInfo->property & _APPCONTROL_PROPERTY_ALIAS)
288                 {
289                         const _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
290                         pEntry = _AppControlRegistry::GetInstance()->GetReverseAppControlAliasEntry(aId, oId);
291                         if (pEntry)
292                         {
293                                 aId = pEntry->provider;
294                                 oId = pEntry->operation;
295
296                                 SysLog(NID_APP, "Legacy AppControl (%ls, %ls).", aId.GetPointer(), oId.GetPointer());
297                         }
298                 }
299
300                 if (pInfo->isLegacy)
301                 {
302                         IAppControlEventListener* pListener = dynamic_cast<IAppControlEventListener*>(pInfo->pListener);
303                         if (pListener)
304                         {
305                                 ArrayList list(SingleObjectDeleter);
306                                 _AppArg::FillLegacyAppControlResult(list, res, pArgs, aId);
307
308                                 InvokeLegacyAppControlCompleteListener(*pListener, aId, oId, &list);
309                         }
310                         else
311                         {
312                                 SysLog(NID_APP, "Wrong AppControl listener type.");
313                         }
314                 }
315                 else
316                 {
317                         IAppControlResponseListener* pListener = dynamic_cast<IAppControlResponseListener*>(pInfo->pListener);
318                         if (pListener && (!__listenerList.Contains(pInfo->pListener)))
319                         {
320                                 _AppControlResponseEvent* pResponseEvent = null;
321                                 int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + reqId;
322                                 __pAppControlResponseEventContainer->GetValue(responseEventRequestId, pResponseEvent);
323
324                                 if (pResponseEvent != null)
325                                 {
326                                         _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_COMPLETE, aId, oId, E_SUCCESS, static_cast<AppCtrlResult>(res), const_cast<IMap*> (pArgs), responseEventRequestId);
327                                         if (pResponseEventArg != null)
328                                         {
329                                                 pResponseEvent->Fire(*pResponseEventArg);
330                                                 SysLog(NID_APP, "pResponseEvent is Fired");
331                                         }
332                                 }
333                                 else
334                                 {
335                                         InvokeAppControlCompleteListener(*pListener, aId, oId, ConvertAppControlResultCode(res), pArgs);
336                                         SysLog(NID_APP, "Listener called directly");
337                                         delete pArgs;
338                                 }
339                         }
340                         else
341                         {
342                                 SysLog(NID_APP, "Wrong AppControl listener type.");
343                         }
344                 }
345         }
346         else
347         {
348                 SysLogException(NID_APP, E_SYSTEM, "Invalid AppControl listener.");
349         }
350
351         // call TerminateAppControl
352         result (* pFunc)(int req) = null;
353         pFunc = reinterpret_cast<result (*)(int)>(pInfo->pLib->GetProcAddress(L"TerminateAppControl"));
354         if (pFunc)
355         {
356                 (*pFunc)(pInfo->reqId);
357         }
358         else
359         {
360                 SysLogException(NID_APP, E_SYSTEM, "No TerminateAppControl() function.");
361         }
362
363         // remove from list and unload dll
364         __inAppManager.RemoveItem(reqId);
365 }
366
367
368 result
369 _AppControlManager::SendAppControlEvent(IEventArg& arg)
370 {
371         return __appControlEvent.FireAsync(arg);
372 }
373
374 Tizen::Base::Collection::IMapT<int,_AppControlResponseEvent*>*
375 _AppControlManager::GetAppControlResponseEventContainer(void)
376 {
377         return __pAppControlResponseEventContainer;
378 }
379
380
381 // generic launch callback
382 static void
383 LaunchResultCb(bundle* b, int request_code, appsvc_result_val res, void* data)
384 {
385         SysLog(NID_APP, "SLP callee result: %d", res);
386
387         _AppControlManager* pImpl = static_cast<_AppControlManager*>(data);
388         if (pImpl == null)
389         {
390                 return;
391         }
392
393         _AppArg* pAppArg = new (std::nothrow) _AppArg;
394         SysTryReturnVoidResult(NID_APP, pAppArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
395
396         _AppControlEventArg* pArg = null;
397         result r = pAppArg->Construct(b);
398         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] AppControl event argument creation failure.", GetErrorMessage(r));
399
400         pArg = new (std::nothrow) _AppControlEventArg(request_code, pAppArg, res);
401         SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, r, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
402
403         //_AppArg::Print(b);
404         pImpl->SendAppControlEvent(*pArg);
405
406         return;
407
408 CATCH:
409         delete pAppArg;
410 }
411
412
413 result
414 _AppControlManager::SendAppControlStartResponse(int req, const char* pValue, const char* pOp)
415 {
416         _AppControlStartEventArg* pArg = new (std::nothrow) _AppControlStartEventArg(req, AppId(pValue), String(pOp));
417         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "AppControl start event creation failure.");
418
419         SendAppControlEvent(*pArg);
420
421         return E_SUCCESS;
422 }
423
424
425 result
426 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
427 {
428         bundle* kb = msg.GetBundle();
429         SysTryReturnResult(NID_APP, kb != NULL, E_OUT_OF_MEMORY, "Bundle allocation failure.");
430
431         if (pkg_name)
432         {
433                 appsvc_set_pkgname(kb, pkg_name);
434         }
435
436         appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
437
438         if (mime)
439         {
440                 appsvc_set_mime(kb, mime);
441         }
442
443         if (uri)
444         {
445                 appsvc_set_uri(kb, uri);
446         }
447
448         if (_AppImpl::GetInstance() != null)
449         {
450                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
451                 _AppArg::UpdateWindowHandle(kb, handle);
452         }
453
454         SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
455         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
456
457         result r = E_SUCCESS;
458         if (pid < 0)
459         {
460                 switch (pid)
461                 {
462                 case APPSVC_RET_EILLACC:
463                         r = E_ILLEGAL_ACCESS;
464                         break;
465                 case APPSVC_RET_EINVAL:
466                         r = E_MAX_EXCEEDED;
467                         break;
468                 default:
469                         r = E_SYSTEM;
470                         break;
471                 }
472                 SysLog(NID_APP, "[%s] Launching service %s failure", GetErrorMessage(r), pkg_name);
473         }
474
475         return r;
476 }
477
478
479 int
480 _AppControlManager::Launch(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
481 {
482         bundle* kb = msg.GetBundle();
483         SysTryReturn(NID_APP, kb != NULL, -1, E_OUT_OF_MEMORY, "Bundle allocation failure.");
484
485         if (pkg_name)
486         {
487                 appsvc_set_pkgname(kb, pkg_name);
488         }
489
490         appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
491
492         if (mime)
493         {
494                 appsvc_set_mime(kb, mime);
495         }
496
497         if (uri)
498         {
499                 appsvc_set_uri(kb, uri);
500         }
501
502         if (_AppImpl::GetInstance() != null)
503         {
504                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
505                 _AppArg::UpdateWindowHandle(kb, handle);
506         }
507
508         SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
509         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
510
511         result r = E_SUCCESS;
512         if (pid < 0)
513         {
514                 switch (pid)
515                 {
516                 case APPSVC_RET_EILLACC:
517                         r = E_ILLEGAL_ACCESS;
518                         break;
519                 case APPSVC_RET_EINVAL:
520                         r = E_MAX_EXCEEDED;
521                         break;
522                 default:
523                         r = E_SYSTEM;
524                         break;
525                 }
526                 SysLog(NID_APP, "[%s]Launching service %s failure", GetErrorMessage(r), pkg_name);
527         }
528         SetLastResult(r);
529
530         return pid;
531 }
532
533
534 int
535 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const AppId& appId, const String& opId, const String* pUri, const String* pMime, AppSvcResFn pCb, void* data)
536 {
537         std::unique_ptr<char[]> pPackage(_StringConverter::CopyToCharArrayN(appId));
538         std::unique_ptr<char[]> pOperation(_StringConverter::CopyToCharArrayN(opId));
539
540         const char* pUriData = null;
541         if (pUri)
542         {
543                 pUriData =  _StringConverter::CopyToCharArrayN(*pUri);
544         }
545
546         const char* pMimeData = null;
547         if (pMime)
548         {
549                 pMimeData = _StringConverter::CopyToCharArrayN(*pMime);
550         }
551
552         int pid = Launch(msg, pPackage.get(), pOperation.get(), pMimeData, pUriData, pCb, data);
553
554         delete [] pUriData;
555         delete [] pMimeData;
556
557         return pid;
558 }
559
560
561 result
562 _AppControlManager::LaunchPkg(const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
563 {
564         _AppMessageImpl msg;
565
566         return LaunchPkg(msg, pkg_name, op, mime, uri, pCb, data);
567 }
568
569 result
570 _AppControlManager::LaunchAppWithCondition(const AppId& appId, const String& condition, IList* pArrayArgs)
571 {
572         result r = E_SUCCESS;
573         _AppArg * pArg = new (std::nothrow) _AppArg();
574         SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]");
575
576         r = pArg->ConstructForAppLaunchCondition(condition, pArrayArgs);
577         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] ConstructForAppLaunchCondition(%ls, .. ) fails", GetErrorMessage(r), condition.GetPointer());
578
579         r = _AppControlManager::LaunchApp(appId, pArg);
580 CATCH:
581         delete pArg;
582         return r;
583 }
584
585 result
586 _AppControlManager::LaunchApp(const AppId& appId, _AppArg* pArg, int req)
587 {
588         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
589         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
590
591         String actualAppId = appId;
592         if (appId.GetLength() == 10)
593         {
594                 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
595
596                 if (!name.IsEmpty())
597                 {
598                         actualAppId.Append(L'.');
599                         actualAppId.Append(name);
600                 }
601         }
602
603         pArg->UpdateRequestId(req);
604
605         if (_AppImpl::GetInstance() != null)
606         {
607                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
608                 pArg->UpdateWindowHandle(handle);
609         }
610
611         int pid = -1;
612         bundle* kb = NULL;
613         String tempId;
614         actualAppId.SubString(0, 10, tempId);
615         tempId += L'.';
616         tempId += L"_AppControl";
617
618         // [INFO] Ugly solution for submode support
619         pArg->UpdateAppId(tempId);
620         kb = pArg->GetBundle();
621         
622         pid = appsvc_run_service(kb, req, LaunchResultCb, this);
623         if (pid >= 0)
624         {
625                 SysLog(NID_APP, "Submode launch successful");
626                 return E_SUCCESS;
627         }
628         else if (pid == APPSVC_RET_EINVAL)
629         {
630                 SysLog(NID_APP, "Argument overflow");
631                 return E_MAX_EXCEEDED;
632         }
633
634         pArg->UpdateAppId(actualAppId);
635
636         // retry for possible failure
637         int count = 0;
638         const int TRY_COUNT = 3;
639         const int TRY_SLEEP_TIME = 65;
640         do
641         {
642                 kb = pArg->GetBundle();
643                 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
644                 if (pid >= 0)
645                 {
646                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
647                         return E_SUCCESS;
648                 }
649                 else if (pid == APPSVC_RET_EINVAL)
650                 {
651                         SysLog(NID_APP, "Argument overflow");
652                         return E_MAX_EXCEEDED;
653                 }
654
655                 count++;
656                 SysLog(NID_APP, "Waiting %dth time.", count);
657                 Thread::Sleep(TRY_SLEEP_TIME);
658         }
659         while (count < TRY_COUNT);
660
661         result r = E_SUCCESS;
662         switch (pid)
663         {
664         case APPSVC_RET_EILLACC:
665                 r = E_ILLEGAL_ACCESS;
666                 break;
667         default:
668                 r = E_SYSTEM;
669                 break;
670         }
671
672         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
673
674         return r;
675 }
676
677 static bool
678 _IsDefaultApplication(const AppId& packageId, const String& appId)
679 {
680         const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
681
682         int index = -1;
683         result r = appId.IndexOf(L'.', 0, index);
684         if (r != E_SUCCESS)
685         {
686                 return false;
687         }
688
689         String tmp;
690         appId.SubString(index + 1, tmp);
691         if (tmp == execName)
692         {
693                 SysLog(NID_APP, "Default application %ls", tmp.GetPointer());
694                 return true;
695         }
696
697         return false;
698 }
699
700
701 int
702 _AppControlManager::Launch(const _AppMessageImpl& msg, const AppId& aId, const String& oId, const String* pUriData, const String* pMimeType, AppSvcResFn pCb, void* pData)
703 {
704         SysLog(NID_APP, "Enter");
705
706         _AppArg arg;
707         arg.Construct(msg, oId, pUriData, pMimeType);
708
709         int pid = Launch(aId, &arg, pCb, pData, -1); 
710         SysTryReturn(NID_APP, pid >= 0, -1, GetLastResult(), "Launching(%ls) is failed", aId.GetPointer());
711
712         SysLog(NID_APP, "Exit");
713
714         return pid;
715 }
716
717
718 int
719 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
720 {
721         return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
722 }
723
724
725 int
726 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, AppSvcResFn pCb, void* pData, int req)
727 {
728         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Invalid launch argument");
729         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
730
731         String actualAppId = appId;
732         if (appId.GetLength() == 10)
733         {
734                 const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
735
736                 if (!execName.IsEmpty())
737                 {
738                         actualAppId.Append(L'.');
739                         actualAppId.Append(execName);
740                 }
741         }
742
743         pArg->UpdateRequestId(req);
744
745         if (_AppImpl::GetInstance() != null)
746         {
747                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
748                 pArg->UpdateWindowHandle(handle);
749         }
750
751         int pid = -1;
752         bundle* kb = NULL;
753         String tempId;
754
755         actualAppId.SubString(0, 10, tempId);
756
757         if (_IsDefaultApplication(tempId, appId))
758         {
759                 tempId += L'.';
760                 tempId += L"_AppControl";
761
762                 // [INFO] Ugly solution for submode support
763                 pArg->UpdateAppId(tempId);
764                 kb = pArg->GetBundle();
765
766                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
767                 if (pid >= 0)
768                 {
769                         SysLog(NID_APP, "Submode launch successful");
770                         SetLastResult(E_SUCCESS);
771                         return pid;
772                 }
773                 else if (pid == APPSVC_RET_EINVAL)
774                 {
775                         SetLastResult(E_MAX_EXCEEDED);
776                         return pid;
777                 }
778         }
779
780         pArg->UpdateAppId(actualAppId);
781
782         // retry for possible failure
783         int count = 0;
784         const int TRY_COUNT = 3;
785         const int TRY_SLEEP_TIME = 65;
786         do
787         {
788                 kb = pArg->GetBundle();
789                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
790                 if (pid >= 0)
791                 {
792                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
793                         SetLastResult(E_SUCCESS);
794                         return pid;
795                 }
796                 else if (pid == APPSVC_RET_EINVAL)
797                 {
798                         SetLastResult(E_MAX_EXCEEDED);
799                         return pid;
800                 }
801
802                 count++;
803                 SysLog(NID_APP, "Waiting %dth time with %d.", count, pid);
804                 Thread::Sleep(TRY_SLEEP_TIME);
805         }
806         while (count < TRY_COUNT);
807
808         result r = E_SUCCESS;
809         switch (pid)
810         {
811         case APPSVC_RET_EILLACC:
812                 r = E_ILLEGAL_ACCESS;
813                 break;
814         default:
815                 r = E_SYSTEM;
816                 break;
817         }
818
819         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
820
821         SetLastResult(r);
822
823         return pid;
824 }
825
826 result
827 _AppControlManager::LaunchAppImplicit(_AppArg* pArg, int req)
828 {
829         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
830
831         result r = E_SUCCESS;
832         bundle* kb = pArg->GetBundle();
833
834         if (req >= 0)
835         {
836                 pArg->UpdateRequestId(req);
837                 _AppMessageImpl::AddData(kb, SELECTOR_NOTI_KEY, _AppInfo::GetApplicationId());
838         }
839
840         if (_AppImpl::GetInstance() != null)
841         {
842                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
843                 _AppArg::UpdateWindowHandle(kb, handle);
844         }
845
846         int pid = appsvc_run_service(kb, req, LaunchResultCb, this);
847         if (pid >= 0)
848         {
849                 if (pid == 0)
850                 {
851                         SysLog(NID_APP, "Sending local process again.");
852                         pid = getpid();
853                 }
854
855                 char pkgname[255] = {0, };
856                 aul_app_get_pkgname_bypid(pid, pkgname, 255);
857
858                 if (strncmp(pkgname, APP_SELECTOR, strlen(APP_SELECTOR)) != 0)
859                 {
860                         const char* pOperation = appsvc_get_operation(kb);
861
862                         SysLog(NID_APP, "Starting application without selector : (%s, %s).", pkgname, pOperation);
863
864                         SendAppControlStartResponse(req, pkgname, pOperation);
865                 }
866         }
867         else
868         {
869                 switch (pid)
870                 {
871                         case APPSVC_RET_EINVAL:
872                                 r = E_OBJ_NOT_FOUND;
873                                 break;
874                         case APPSVC_RET_ENOMATCH:
875                                 r = E_OBJ_NOT_FOUND;
876                                 break;
877                         case APPSVC_RET_EILLACC:
878                                 r = E_ILLEGAL_ACCESS;
879                                 break;
880                         case APPSVC_RET_ERROR:
881                                 // fall through
882                         case APPSVC_RET_ELAUNCH:
883                                 // fall through
884                         default:
885                                 r = E_SYSTEM;
886                                 break;
887                 }
888         }
889
890         SysLog(NID_APP, "[%s] Application(%d) launched with reqId(%d) and arg(0x%x).", GetErrorMessage(r), pid, req, pArg);
891
892         return r;
893 }
894
895 void
896 _AppControlManager::FinishAppControl(int reqId, int res, IMap* pMap)
897 {
898         SysLog(NID_APP, "req %d, res %d.", reqId, res);
899         _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap);
900         SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
901
902         SendAppControlEvent(*pArg);
903         SysLog(NID_APP, "Exit.");
904 }
905
906 const _AppArg*
907 _AppControlManager::FindResultRequest(int reqId) const
908 {
909         const _ResultInfo* pInfo = __resultManager.FindItem(reqId);
910         return (pInfo) ? &(pInfo->arg) : null;
911 }
912
913 int
914 _AppControlManager::AddLaunchRequest(_AppArg* pArg, LaunchCbType pCb, void* pData, int prop)
915 {
916         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Empty argument.");
917
918         _LaunchInfo* pItem = new (std::nothrow) _LaunchInfo(pArg, pCb, pData, prop);
919         SysTryReturn(NID_APP, pItem != null, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
920
921         SysLog(NID_APP, "Registering callback 0x%x, 0x%x", pCb, pData);
922
923         return __launchManager.InsertItem(pItem);
924 }
925
926 void
927 _AppControlManager::RemoveLaunchRequest(int req)
928 {
929         __launchManager.RemoveItem(req);
930 }
931
932 result
933 _AppControlManager::RegisterRequest(service_s* service, int& req, _AppHandler& handler)
934 {
935         bundle* b = _AppArg::GetBundleFromSvc(service);
936
937         _AppArg* pArg = new (std::nothrow) _AppArg();
938         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "ArrayList creation failure.");
939         pArg->Construct(b);
940
941         result r = E_SUCCESS;
942
943         // ownership is transfered to RequestManager
944         _ResultInfo* pItem = new (std::nothrow) _ResultInfo(*pArg);
945         SysTryCatch(NID_APP, pItem != null, , r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
946
947         req = __resultManager.InsertItem(pItem);
948         SysTryCatch(NID_APP, req != -1, , r = E_INVALID_STATE, "[E_INVALID_STATE] Invalid argument handling state.");
949
950         handler = _AppArg::GetHandler(b);
951
952         return E_SUCCESS;
953
954 CATCH:
955         delete pArg;
956
957         return r;
958 }
959
960
961 bool
962 _AppControlManager::IsAllowedAppControl(const char aTable[][2][96], int count, const String& aId, const String& oId)
963 {
964         for (int i = 0; i < count; i++)
965         {
966                 if (aId == aTable[i][0] && oId == aTable[i][1])
967                 {
968                         SysLog(NID_APP, "Found entry (%s, %s)", aTable[i][0], aTable[i][1]);
969                         return true;
970                 }
971         }
972
973         return false;
974 }
975
976
977 AppCtrlResult
978 _AppControlManager::ConvertAppControlResultCode(int resCode)
979 {
980         AppCtrlResult ret = APP_CTRL_RESULT_FAILED;
981
982         switch(resCode)
983         {
984                 case SERVICE_RESULT_SUCCEEDED:
985                         ret = APP_CTRL_RESULT_SUCCEEDED;
986                         break;
987                 case SERVICE_RESULT_FAILED:
988                         ret = APP_CTRL_RESULT_CANCELED;
989                         break;
990                 case SERVICE_RESULT_CANCELED:
991                         ret = APP_CTRL_RESULT_ABORTED;
992                         break;
993                 case APPSVC_OSP_RES_FAIL:
994                         ret = APP_CTRL_RESULT_FAILED;
995                         break;
996                 case APPSVC_OSP_RES_TERMINATE:
997                         ret = APP_CTRL_RESULT_TERMINATED;
998                         break;
999                 default:
1000                         ret = APP_CTRL_RESULT_FAILED;
1001                         break;
1002         }
1003
1004         return ret;
1005 }
1006
1007
1008 void
1009 _AppControlManager::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
1010 {
1011         const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
1012
1013         if (pEventArg != null)
1014         {
1015                 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
1016
1017                 if(pResponseListener != null)
1018                 {
1019                         if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_START)
1020                         {
1021                                 pResponseListener->OnAppControlStartResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetResult());
1022                                 SysLog(NID_APP, "OnAppControlStartResponseReceived called");
1023                         }
1024                         else
1025                         {
1026                                 InvokeAppControlCompleteListener(*pResponseListener, pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData());
1027                                 SysLog(NID_APP, "Listener called");
1028
1029                                 _AppControlResponseEvent* pResponseEvent = null;
1030                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
1031                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
1032
1033                                 delete pResponseEvent;
1034                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
1035                         }
1036                 }
1037                 else
1038                 {
1039                         SysLog(NID_APP, "Invalid ResponseListener");
1040                 }
1041         }
1042         else
1043         {
1044                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
1045         }
1046 }
1047
1048 AppId
1049 _AppControlManager::GetAliasAppId(const AppId& appId)
1050 {
1051         return _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
1052 }
1053
1054 }} // Tizen::App