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