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