Removed privacy data from syslog
[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 (%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                         SetLastResult(E_SUCCESS);
754                         return pid;
755                 }
756                 else if (pid == APPSVC_RET_EINVAL)
757                 {
758                         SetLastResult(E_MAX_EXCEEDED);
759                         return pid;
760                 }
761         }
762
763         pArg->UpdateAppId(actualAppId);
764
765         // retry for possible failure
766         int count = 0;
767         const int TRY_COUNT = 3;
768         const int TRY_SLEEP_TIME = 65;
769         do
770         {
771                 kb = pArg->GetBundle();
772                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
773                 if (pid >= 0)
774                 {
775                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
776                         SetLastResult(E_SUCCESS);
777                         return pid;
778                 }
779                 else if (pid == APPSVC_RET_EINVAL)
780                 {
781                         SetLastResult(E_MAX_EXCEEDED);
782                         return pid;
783                 }
784
785                 count++;
786                 SysLog(NID_APP, "Waiting %dth time with %d.", count, pid);
787                 Thread::Sleep(TRY_SLEEP_TIME);
788         }
789         while (count < TRY_COUNT);
790
791         result r = E_SUCCESS;
792         switch (pid)
793         {
794         case APPSVC_RET_EILLACC:
795                 r = E_ILLEGAL_ACCESS;
796                 break;
797         case APPSVC_RET_EINVAL:
798                 r = E_MAX_EXCEEDED;
799                 break;
800         default:
801                 r = E_SYSTEM;
802                 break;
803         }
804
805         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
806
807         SetLastResult(r);
808
809         return pid;
810 }
811
812 result
813 _AppControlManager::LaunchAppImplicit(_AppArg* pArg, int req)
814 {
815         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
816
817         result r = E_SUCCESS;
818         bundle* kb = pArg->GetBundle();
819
820         if (req >= 0)
821         {
822                 pArg->UpdateRequestId(req);
823                 _AppMessageImpl::AddData(kb, SELECTOR_NOTI_KEY, _AppInfo::GetApplicationId());
824         }
825
826         if (_AppImpl::GetInstance() != null)
827         {
828                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
829                 _AppArg::UpdateWindowHandle(kb, handle);
830         }
831
832         int pid = appsvc_run_service(kb, req, LaunchResultCb, this);
833         if (pid >= 0)
834         {
835                 if (pid == 0)
836                 {
837                         SysLog(NID_APP, "Sending local process again.");
838                         pid = getpid();
839                 }
840
841                 char pkgname[255] = {0, };
842                 aul_app_get_pkgname_bypid(pid, pkgname, 255);
843
844                 if (strncmp(pkgname, APP_SELECTOR, strlen(APP_SELECTOR)) != 0)
845                 {
846                         const char* pOperation = appsvc_get_operation(kb);
847
848                         SysLog(NID_APP, "Starting application without selector : (%s, %s).", pkgname, pOperation);
849
850                         SendAppControlStartResponse(req, pkgname, pOperation);
851                 }
852         }
853         else
854         {
855                 switch (pid)
856                 {
857                         case APPSVC_RET_EINVAL:
858                                 r = E_OBJ_NOT_FOUND;
859                                 break;
860                         case APPSVC_RET_ENOMATCH:
861                                 r = E_OBJ_NOT_FOUND;
862                                 break;
863                         case APPSVC_RET_EILLACC:
864                                 r = E_ILLEGAL_ACCESS;
865                                 break;
866                         case APPSVC_RET_ERROR:
867                                 // fall through
868                         case APPSVC_RET_ELAUNCH:
869                                 // fall through
870                         default:
871                                 r = E_SYSTEM;
872                                 break;
873                 }
874         }
875
876         SysLog(NID_APP, "[%s] Application(%d) launched with reqId(%d) and arg(0x%x).", GetErrorMessage(r), pid, req, pArg);
877
878         return r;
879 }
880
881 void
882 _AppControlManager::FinishAppControl(int reqId, int res, IMap* pMap)
883 {
884         SysLog(NID_APP, "req %d, res %d.", reqId, res);
885         _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap);
886         SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
887
888         SendAppControlEvent(*pArg);
889         SysLog(NID_APP, "Exit.");
890 }
891
892 const _AppArg*
893 _AppControlManager::FindResultRequest(int reqId) const
894 {
895         const _ResultInfo* pInfo = __resultManager.FindItem(reqId);
896         return (pInfo) ? &(pInfo->arg) : null;
897 }
898
899 int
900 _AppControlManager::AddLaunchRequest(_AppArg* pArg, LaunchCbType pCb, void* pData, int prop)
901 {
902         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Empty argument.");
903
904         _LaunchInfo* pItem = new (std::nothrow) _LaunchInfo(pArg, pCb, pData, prop);
905         SysTryReturn(NID_APP, pItem != null, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
906
907         SysLog(NID_APP, "Registering callback 0x%x, 0x%x", pCb, pData);
908
909         return __launchManager.InsertItem(pItem);
910 }
911
912 void
913 _AppControlManager::RemoveLaunchRequest(int req)
914 {
915         __launchManager.RemoveItem(req);
916 }
917
918 result
919 _AppControlManager::RegisterRequest(service_s* service, int& req, _AppHandler& handler)
920 {
921         bundle* b = _AppArg::GetBundleFromSvc(service);
922
923         _AppArg* pArg = new (std::nothrow) _AppArg();
924         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "ArrayList creation failure.");
925         pArg->Construct(b);
926
927         result r = E_SUCCESS;
928
929         // ownership is transfered to RequestManager
930         _ResultInfo* pItem = new (std::nothrow) _ResultInfo(*pArg);
931         SysTryCatch(NID_APP, pItem != null, , r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
932
933         req = __resultManager.InsertItem(pItem);
934         SysTryCatch(NID_APP, req != -1, , r = E_INVALID_STATE, "[E_INVALID_STATE] Invalid argument handling state.");
935
936         handler = _AppArg::GetHandler(b);
937
938         return E_SUCCESS;
939
940 CATCH:
941         delete pArg;
942
943         return r;
944 }
945
946
947 bool
948 _AppControlManager::IsAllowedAppControl(const char aTable[][2][96], int count, const String& aId, const String& oId)
949 {
950         for (int i = 0; i < count; i++)
951         {
952                 if (aId == aTable[i][0] && oId == aTable[i][1])
953                 {
954                         SysLog(NID_APP, "Found entry (%s, %s)", aTable[i][0], aTable[i][1]);
955                         return true;
956                 }
957         }
958
959         return false;
960 }
961
962
963 AppCtrlResult
964 _AppControlManager::ConvertAppControlResultCode(int resCode)
965 {
966         AppCtrlResult ret = APP_CTRL_RESULT_FAILED;
967
968         switch(resCode)
969         {
970                 case SERVICE_RESULT_SUCCEEDED:
971                         ret = APP_CTRL_RESULT_SUCCEEDED;
972                         break;
973                 case SERVICE_RESULT_FAILED:
974                         ret = APP_CTRL_RESULT_CANCELED;
975                         break;
976                 case SERVICE_RESULT_CANCELED:
977                         ret = APP_CTRL_RESULT_ABORTED;
978                         break;
979                 case APPSVC_OSP_RES_FAIL:
980                         ret = APP_CTRL_RESULT_FAILED;
981                         break;
982                 case APPSVC_OSP_RES_TERMINATE:
983                         ret = APP_CTRL_RESULT_TERMINATED;
984                         break;
985                 default:
986                         ret = APP_CTRL_RESULT_FAILED;
987                         break;
988         }
989
990         return ret;
991 }
992
993
994 void
995 _AppControlManager::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
996 {
997         const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
998
999         if (pEventArg != null)
1000         {
1001                 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
1002
1003                 if(pResponseListener != null)
1004                 {
1005                         if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_START)
1006                         {
1007                                 pResponseListener->OnAppControlStartResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetResult());
1008                                 SysLog(NID_APP, "OnAppControlStartResponseReceived called");
1009                         }
1010                         else
1011                         {
1012                                 pResponseListener->OnAppControlCompleteResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData());
1013                                 SysLog(NID_APP, "OnAppControlCompleteResponseReceived called");
1014
1015                                 _AppControlResponseEvent* pResponseEvent = null;
1016                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
1017                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
1018
1019                                 delete pResponseEvent;
1020                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
1021                         }
1022                 }
1023                 else
1024                 {
1025                         SysLog(NID_APP, "Invalid ResponseListener");
1026                 }
1027         }
1028         else
1029         {
1030                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
1031         }
1032 }
1033
1034 AppId
1035 _AppControlManager::GetAliasAppId(const AppId& appId)
1036 {
1037         return _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
1038 }
1039
1040 }} // Tizen::App