AppControl launch logic refactoring
[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 #include <appinfo.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 <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_Aul.h"
58 #include "FApp_AppControlManager.h"
59 #include "FApp_AppManagerProxy.h"
60 #include "FApp_ConditionManagerProxy.h"
61 #include "FApp_MapDataControlImpl.h"
62 #include "FApp_SqlDataControlImpl.h"
63 #include "FAppPkg_PackageManagerImpl.h"
64 #include "FAppPkg_PackageInfoImpl.h"
65 #include "FApp_AppMessageImpl.h"
66 #include "FApp_AppManagerImpl.h"
67 #include "FApp_AppControlResponseEvent.h"
68 #include "FApp_IAppControlPluginProvider.h"
69
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
79 {
80 const char SELECTOR_NOTI_KEY[] = "__APP_SVC_CALLER_NOTI__";
81 }
82
83 namespace Tizen { namespace App
84 {
85 const wchar_t TIZEN_OPERATION_PICK[] = L"http://tizen.org/appcontrol/operation/pick";
86
87
88 _AppControlManager::_AppControlManager(void)
89 {
90         SysLog(NID_APP, "");
91
92         // AppControl event handling is expected to be performed in the main thread.
93         __appControlEvent.Construct();
94         __appControlEvent.AddListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
95         __appControlResponseEventContainer.Construct();
96         __appControlResponseEventList.Construct();
97 }
98
99 _AppControlManager::~_AppControlManager(void)
100 {
101         SysLog(NID_APP, "");
102         __appControlEvent.RemoveListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
103         IEnumeratorT<int>* pEnum = __appControlResponseEventList.GetEnumeratorN();
104
105         if (pEnum != null)
106         {
107                 while(pEnum->MoveNext() == E_SUCCESS)
108                 {
109                         int reqId;
110                         pEnum->GetCurrent(reqId);
111                         _AppControlResponseEvent* pResponseEvent = null;
112                         __appControlResponseEventContainer.GetValue(reqId, pResponseEvent);
113                         delete pResponseEvent;
114
115                         __appControlResponseEventContainer.Remove(reqId);
116                         SysLog(NID_APP, "pResponseEvent gets deleted. reqId(%d)", reqId);
117                 }
118         }
119         delete pEnum;
120 }
121
122 _AppControlManager*
123 _AppControlManager::GetInstance(void)
124 {
125         static _AppControlManager inst;
126
127         return &inst;
128 }
129
130 result
131 _AppControlManager::GetMimeFromExt(const String& ext, String& out)
132 {
133         std::unique_ptr<char[]> pExtension(_StringConverter::CopyToCharArrayN(ext));
134         SysTryReturnResult(NID_APP, pExtension != null, E_OUT_OF_MEMORY, "String allocation failure.");
135
136         char* mime = NULL;
137         mime_type_get_mime_type(pExtension.get(), &mime);
138
139         SysTryReturnResult(NID_APP, mime != NULL, E_UNSUPPORTED_FORMAT, "MIME type conversion failure for %ls.", ext.GetPointer());
140
141         out = mime;
142         free(mime);
143
144         return E_SUCCESS;
145 }
146
147 void
148 _AppControlManager::OnAppControlEventReceivedN(int reqId, _AppArg* pAppArg, int res)
149 {
150         SysLog(NID_APP, "Received request Id %d, arg 0x%x", reqId, pAppArg);
151
152         //_AppArg::Print(b);
153         // get launch info from request Id
154         _LaunchInfo* pInfo = __launchManager.FindItem(reqId);
155         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with response %d", reqId,
156                                         res);
157
158         // invoke callback
159         if (pInfo->launchCb)
160         {
161                 if (pInfo->magic == LAUNCH_INFO_MAGIC)
162                 {
163                         SysLog(NID_APP, "Invoking callback 0x%x", pInfo->launchCb);
164                         //pAppArg->Print();
165
166                         if (pInfo->pUserData)
167                         {
168                                 (*pInfo->launchCb)(pInfo->pUserData, pInfo->pArg, pAppArg, static_cast<service_result_e>(res), pInfo->property, reqId);
169                         }
170                 }
171                 else
172                 {
173                         SysLogException(NID_APP, E_SYSTEM, "Corrupted data structure.");
174                 }
175         }
176
177         // clean up argument
178         __launchManager.RemoveItem(reqId);
179 }
180
181
182 // callback for out-of-process AppControl start event
183 void
184 _AppControlManager::OnAppControlEventReceivedN(int reqId, const AppId& appId, const String& operationId)
185 {
186         SysLog(NID_APP, "Received request Id %d, app %ls, operationId %ls", reqId, appId.GetPointer(), operationId.GetPointer());
187
188         // get launch info from request Id
189         _LaunchInfo* pInfo = __launchManager.FindItem(reqId);
190         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found.", reqId);
191
192         // at least listener
193         IAppControlResponseListener* pListener = static_cast<IAppControlResponseListener*>(pInfo->pUserData);
194         SysTryReturnVoidResult(NID_APP, typeid(pListener) == typeid(IAppControlResponseListener*), E_SYSTEM, "[E_SYSTEM] Invalid result callback.");
195
196         if (pListener)
197         {
198                 result r = E_SUCCESS;
199                 AppId actualAppId = appId;
200                 if (appId == L'c')
201                 {
202                         actualAppId.Clear();
203                         r = E_OPERATION_CANCELED;
204                 }
205                 SysLog(NID_APP, "Invoking callback 0x%x.", pListener);
206
207                 _AppControlResponseEvent* pResponseEvent = null;
208                 __appControlResponseEventContainer.GetValue(reqId, pResponseEvent);
209                 SysLog(NID_APP, "StartResponseReceived Request Id(%d), ResponseEvent 0x%x.", reqId, pResponseEvent);
210                 if (pResponseEvent != null)
211                 {
212                         String oId(operationId);
213                         _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_START, actualAppId, oId, r, APP_CTRL_RESULT_SUCCEEDED, null, reqId, false);
214
215                         if (pResponseEventArg != null)
216                         {
217                                 pResponseEvent->Fire(*pResponseEventArg);
218                                 SysLog(NID_APP, "pResponseEvent is Fired");
219                         }
220                 }
221                 else
222                 {
223                         pListener->OnAppControlStartResponseReceived(actualAppId, operationId, r);
224                         SysLog(NID_APP, "OnAppControlStartResponseReceived called directly");
225                 }
226         }
227         else
228         {
229                 SysLog(NID_APP, "No listener registered.");
230         }
231 }
232
233
234 void
235 _AppControlManager::InvokeAppControlCompleteListener(IAppControlResponseListener& listener, const AppId& appId, const String& op, AppCtrlResult res, const IMap* pExtraData, bool noRaise)
236 {
237         listener.OnAppControlCompleteResponseReceived(appId, op, res, pExtraData);
238
239         if (!noRaise)
240         {
241                 _AppImpl::GetInstance()->SendUserEvent(_APP_EVENT_RAISE, null, false);
242         }
243
244         SysLog(NID_APP, "AppControl response finished.");
245 }
246
247
248 void
249 _AppControlManager::InvokeLegacyAppControlCompleteListener(IAppControlEventListener& listener, const AppId& appId, const String& op, const IList* pList, bool noRaise)
250 {
251         listener.OnAppControlCompleted(appId, op, pList);
252
253         if (!noRaise)
254         {
255                 _AppImpl::GetInstance()->SendUserEvent(_APP_EVENT_RAISE, null, false);
256         }
257
258         SysLog(NID_APP, "Legacy AppControl response finished.");
259 }
260
261
262 // callback for in-process event handling
263 void
264 _AppControlManager::OnAppControlEventReceivedN(int reqId, int res, const IMap* pArgs, int property)
265 {
266         SysLog(NID_APP, "Received request Id %d, res %d, args 0x%x", reqId, res, pArgs);
267
268         // process proper callback
269         _InProcessInfo* pInfo = __inAppManager.FindItem(reqId);
270         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with args 0x%x", reqId,
271                                         pArgs);
272
273         if (pInfo->pListener)
274         {
275                 String aId = pInfo->providerId;
276                 String oId = pInfo->operationId;
277
278                 SysLog(NID_APP, "Invoking callback 0x%x for (%ls, %ls).", pInfo->pListener, aId.GetPointer(), oId.GetPointer());
279
280                 if (pInfo->property & _APPCONTROL_PROPERTY_ALIAS)
281                 {
282                         const _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
283                         pEntry = _AppControlRegistry::GetInstance()->GetReverseAppControlAliasEntry(aId, oId);
284                         if (pEntry)
285                         {
286                                 aId = pEntry->provider;
287                                 oId = pEntry->operation;
288
289                                 SysLog(NID_APP, "Legacy AppControl (%ls, %ls).", aId.GetPointer(), oId.GetPointer());
290                         }
291                 }
292
293                 const bool isSubMode = (property & _APPCONTROL_PROPERTY_SUBMODE);
294                 const bool isServiceCallee = (property & _APPCONTROL_PROPERTY_SERVICE_CALLEE);
295
296                 if (pInfo->isLegacy)
297                 {
298                         IAppControlEventListener* pListener = dynamic_cast<IAppControlEventListener*>(pInfo->pListener);
299                         if (pListener)
300                         {
301                                 ArrayList list(SingleObjectDeleter);
302                                 _AppArg::FillLegacyAppControlResult(list, res, pArgs, aId);
303
304                                 InvokeLegacyAppControlCompleteListener(*pListener, aId, oId, &list, isSubMode | isServiceCallee);
305                         }
306                         else
307                         {
308                                 SysLog(NID_APP, "Wrong AppControl listener type.");
309                         }
310                 }
311                 else
312                 {
313                         IAppControlResponseListener* pListener = dynamic_cast<IAppControlResponseListener*>(pInfo->pListener);
314                         if (pListener)
315                         {
316                                 _AppControlResponseEvent* pResponseEvent = null;
317                                 int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + reqId;
318                                 __appControlResponseEventContainer.GetValue(responseEventRequestId, pResponseEvent);
319
320                                 if (pResponseEvent != null)
321                                 {
322                                         _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_COMPLETE, aId, oId, E_SUCCESS, static_cast<AppCtrlResult>(res), const_cast<IMap*> (pArgs), responseEventRequestId, isSubMode);
323                                         if (pResponseEventArg != null)
324                                         {
325                                                 pResponseEvent->Fire(*pResponseEventArg);
326                                                 SysLog(NID_APP, "pResponseEvent is Fired");
327                                         }
328                                 }
329                                 else
330                                 {
331                                         InvokeAppControlCompleteListener(*pListener, aId, oId, ConvertAppControlResultCode(res), pArgs, isSubMode | isServiceCallee);
332                                         SysLog(NID_APP, "Listener called directly");
333                                         delete pArgs;
334                                 }
335                         }
336                         else
337                         {
338                                 SysLog(NID_APP, "Wrong AppControl listener type.");
339                         }
340                 }
341         }
342         else
343         {
344                 SysLogException(NID_APP, E_SYSTEM, "Invalid AppControl listener.");
345         }
346
347         // call TerminateAppControl
348         if (pInfo->pProvider)
349         {
350                 pInfo->pProvider->StopAppControlPlugin(pInfo->reqId);
351                 SysLog(NID_APP, "AppControl stopped for req %d.", pInfo->reqId);
352         }
353
354         // remove from list and unload dll
355         __inAppManager.RemoveItem(reqId);
356 }
357
358
359 result
360 _AppControlManager::SendAppControlEvent(IEventArg& arg)
361 {
362         return __appControlEvent.FireAsync(arg);
363 }
364
365 Tizen::Base::Collection::IMapT<int,_AppControlResponseEvent*>*
366 _AppControlManager::GetAppControlResponseEventContainer(void)
367 {
368         return &__appControlResponseEventContainer;
369 }
370
371
372 static bool
373 IsMatchingProcListener(const _InProcessInfo& info, IEventListener* pListener)
374 {
375         return (info.pListener == pListener);
376 }
377
378 static bool
379 IsMatchingLaunchListener(const _LaunchInfo& info, IEventListener* pListener)
380 {
381         return (info.pUserData == pListener);
382 }
383
384 void
385 _AppControlManager::StopAppControlResponseListener(IAppControlResponseListener* pListener)
386 {
387         // __inAppManager, __launchManager
388         _InProcessInfo* pProcInfo = __inAppManager.FindItemWithListener(IsMatchingProcListener, pListener);
389         if (pProcInfo)
390         {
391                 __inAppManager.RemoveItem(pProcInfo);
392                 SysLog(NID_APP, "Listener 0x%x is removed from in-process stub list.", pListener);
393         }
394
395         _LaunchInfo* pLaunchInfo = __launchManager.FindItemWithListener(IsMatchingLaunchListener, pListener);
396         if (pLaunchInfo)
397         {
398                 __launchManager.RemoveItem(pLaunchInfo);
399                 SysLog(NID_APP, "Listener 0x%x is removed from launch request list.", pListener);
400         }
401
402 }
403
404
405 // generic launch callback
406 static void
407 LaunchResultCb(bundle* b, int request_code, appsvc_result_val res, void* data)
408 {
409         SysLog(NID_APP, "SLP callee result: %d", res);
410
411         _AppControlManager* pImpl = static_cast<_AppControlManager*>(data);
412         if (pImpl == null)
413         {
414                 return;
415         }
416
417         _AppArg* pAppArg = new (std::nothrow) _AppArg;
418         SysTryReturnVoidResult(NID_APP, pAppArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
419
420         _AppControlEventArg* pArg = null;
421         result r = pAppArg->Construct(b);
422         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] AppControl event argument creation failure.", GetErrorMessage(r));
423
424         pArg = new (std::nothrow) _AppControlEventArg(request_code, pAppArg, res);
425         SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, r, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
426
427         //_AppArg::Print(b);
428         pImpl->SendAppControlEvent(*pArg);
429
430         return;
431
432 CATCH:
433         delete pAppArg;
434 }
435
436
437 result
438 _AppControlManager::SendAppControlStartResponse(int req, const char* pValue, const char* pOp)
439 {
440         _AppControlStartEventArg* pArg = new (std::nothrow) _AppControlStartEventArg(req, AppId(pValue), String(pOp));
441         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "AppControl start event creation failure.");
442
443         SendAppControlEvent(*pArg);
444
445         return E_SUCCESS;
446 }
447
448
449 result
450 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
451 {
452         bundle* kb = msg.GetBundle();
453         SysTryReturnResult(NID_APP, kb != NULL, E_OUT_OF_MEMORY, "Bundle allocation failure.");
454
455         if (pkg_name)
456         {
457                 appsvc_set_pkgname(kb, pkg_name);
458         }
459
460         appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
461
462         if (mime)
463         {
464                 appsvc_set_mime(kb, mime);
465         }
466
467         if (uri)
468         {
469                 appsvc_set_uri(kb, uri);
470         }
471
472         if (_AppImpl::GetInstance() != null)
473         {
474                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
475                 _AppArg::UpdateWindowHandle(kb, handle);
476         }
477
478         SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
479         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
480
481         result r = E_SUCCESS;
482         if (pid < 0)
483         {
484                 switch (pid)
485                 {
486                 case APPSVC_RET_EILLACC:
487                         r = E_ILLEGAL_ACCESS;
488                         break;
489                 case APPSVC_RET_EINVAL:
490                         r = E_MAX_EXCEEDED;
491                         break;
492                 default:
493                         r = E_SYSTEM;
494                         break;
495                 }
496                 SysLog(NID_APP, "[%s] Launching service %s failure", GetErrorMessage(r), pkg_name);
497         }
498
499         return r;
500 }
501
502
503 int
504 _AppControlManager::Launch(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
505 {
506         bundle* kb = msg.GetBundle();
507         SysTryReturn(NID_APP, kb != NULL, -1, E_OUT_OF_MEMORY, "Bundle allocation failure.");
508
509         if (pkg_name)
510         {
511                 appsvc_set_pkgname(kb, pkg_name);
512         }
513
514         appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
515
516         if (mime)
517         {
518                 appsvc_set_mime(kb, mime);
519         }
520
521         if (uri)
522         {
523                 appsvc_set_uri(kb, uri);
524         }
525
526         if (_AppImpl::GetInstance() != null)
527         {
528                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
529                 _AppArg::UpdateWindowHandle(kb, handle);
530         }
531
532         SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
533         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
534
535         result r = E_SUCCESS;
536         if (pid < 0)
537         {
538                 switch (pid)
539                 {
540                 case APPSVC_RET_EILLACC:
541                         r = E_ILLEGAL_ACCESS;
542                         break;
543                 case APPSVC_RET_EINVAL:
544                         r = E_MAX_EXCEEDED;
545                         break;
546                 default:
547                         r = E_SYSTEM;
548                         break;
549                 }
550                 SysLog(NID_APP, "[%s]Launching service %s failure", GetErrorMessage(r), pkg_name);
551         }
552         SetLastResult(r);
553
554         return pid;
555 }
556
557
558 int
559 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, AppSvcResFn pCb, void* data)
560 {
561         bundle* kb = msg.GetBundle();
562         SysTryReturn(NID_APP, kb != NULL, -1, E_OUT_OF_MEMORY, "Bundle allocation failure.");
563
564         if (_AppImpl::GetInstance() != null)
565         {
566                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
567                 _AppArg::UpdateWindowHandle(kb, handle);
568         }
569
570         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
571
572         result r = E_SUCCESS;
573         if (pid < 0)
574         {
575                 switch (pid)
576                 {
577                 case APPSVC_RET_EILLACC:
578                         r = E_ILLEGAL_ACCESS;
579                         break;
580                 case APPSVC_RET_EINVAL:
581                         r = E_MAX_EXCEEDED;
582                         break;
583                 default:
584                         r = E_SYSTEM;
585                         break;
586                 }
587                 SysLog(NID_APP, "[%s] Launching service %s failure", GetErrorMessage(r), appsvc_get_appid(kb));
588         }
589         SetLastResult(r);
590
591         return pid;
592 }
593
594
595 int
596 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const AppId& appId, const String& opId, const String* pUri, const String* pMime, AppSvcResFn pCb, void* data)
597 {
598         std::unique_ptr<char[]> pPackage(_StringConverter::CopyToCharArrayN(appId));
599         std::unique_ptr<char[]> pOperation(_StringConverter::CopyToCharArrayN(opId));
600
601         const char* pUriData = null;
602         if (pUri)
603         {
604                 pUriData =  _StringConverter::CopyToCharArrayN(*pUri);
605         }
606
607         const char* pMimeData = null;
608         if (pMime)
609         {
610                 pMimeData = _StringConverter::CopyToCharArrayN(*pMime);
611         }
612
613         int pid = Launch(msg, pPackage.get(), pOperation.get(), pMimeData, pUriData, pCb, data);
614
615         delete [] pUriData;
616         delete [] pMimeData;
617
618         return pid;
619 }
620
621
622 result
623 _AppControlManager::LaunchPkg(const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
624 {
625         _AppMessageImpl msg;
626
627         return LaunchPkg(msg, pkg_name, op, mime, uri, pCb, data);
628 }
629
630 result
631 _AppControlManager::LaunchAppWithCondition(const AppId& appId, const String& condition, IList* pArrayArgs)
632 {
633         result r = E_SUCCESS;
634         _AppArg * pArg = new (std::nothrow) _AppArg();
635         SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]");
636
637         r = pArg->ConstructForAppLaunchCondition(condition, pArrayArgs);
638         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] ConstructForAppLaunchCondition(%ls, .. ) fails", GetErrorMessage(r), condition.GetPointer());
639
640         r = _AppControlManager::LaunchApp(appId, pArg);
641 CATCH:
642         delete pArg;
643         return r;
644 }
645
646 result
647 _AppControlManager::LaunchApp(const AppId& appId, _AppArg* pArg, int req)
648 {
649         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
650         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
651
652         String actualAppId = appId;
653         if (appId.GetLength() == 10)
654         {
655                 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
656
657                 if (!name.IsEmpty())
658                 {
659                         actualAppId.Append(L'.');
660                         actualAppId.Append(name);
661                 }
662         }
663
664         pArg->UpdateRequestId(req);
665
666         if (_AppImpl::GetInstance() != null)
667         {
668                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
669                 pArg->UpdateWindowHandle(handle);
670         }
671
672         int pid = -1;
673         bundle* kb = NULL;
674         String tempId;
675         actualAppId.SubString(0, 10, tempId);
676         tempId += L'.';
677         tempId += L"_AppControl";
678
679         // [INFO] Ugly solution for submode support
680         pArg->UpdateAppId(tempId);
681         kb = pArg->GetBundle();
682         
683         pid = appsvc_run_service(kb, req, LaunchResultCb, this);
684         if (pid >= 0)
685         {
686                 SysLog(NID_APP, "Submode launch successful");
687                 return E_SUCCESS;
688         }
689         else if (pid == APPSVC_RET_EINVAL)
690         {
691                 SysLog(NID_APP, "Argument overflow");
692                 return E_MAX_EXCEEDED;
693         }
694
695         pArg->UpdateAppId(actualAppId);
696
697         // retry for possible failure
698         int count = 0;
699         const int TRY_COUNT = 3;
700         const int TRY_SLEEP_TIME = 65;
701         do
702         {
703                 kb = pArg->GetBundle();
704                 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
705                 if (pid >= 0)
706                 {
707                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
708                         return E_SUCCESS;
709                 }
710                 else if (pid == APPSVC_RET_EINVAL)
711                 {
712                         SysLog(NID_APP, "Argument overflow");
713                         return E_MAX_EXCEEDED;
714                 }
715
716                 count++;
717                 SysLog(NID_APP, "Waiting %dth time.", count);
718                 Thread::Sleep(TRY_SLEEP_TIME);
719         }
720         while (count < TRY_COUNT);
721
722         result r = E_SUCCESS;
723         switch (pid)
724         {
725         case APPSVC_RET_EILLACC:
726                 r = E_ILLEGAL_ACCESS;
727                 break;
728         default:
729                 r = E_SYSTEM;
730                 break;
731         }
732
733         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
734
735         return r;
736 }
737
738 static bool
739 _IsDefaultApplication(const AppId& packageId, const String& appId)
740 {
741         const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
742
743         int index = -1;
744         result r = appId.IndexOf(L'.', 0, index);
745         if (r != E_SUCCESS)
746         {
747                 return false;
748         }
749
750         String tmp;
751         appId.SubString(index + 1, tmp);
752         if (tmp == execName)
753         {
754                 SysLog(NID_APP, "Default application %ls", tmp.GetPointer());
755                 return true;
756         }
757
758         return false;
759 }
760
761
762 int
763 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
764 {
765         return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
766 }
767
768
769 int
770 _AppControlManager::Launch(const _AppMessageImpl& msg, AppSvcResFn pCb, void* pData)
771 {
772         const bundle* pBundle = msg.GetBundle();
773
774         _AppArg arg;
775         arg.Construct(pBundle);
776
777         return Launch(_AppMessageImpl::GetApplicationId(pBundle), &arg, pCb, pData, -1);
778 }
779
780
781 int
782 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, AppSvcResFn pCb, void* pData, int req)
783 {
784         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Invalid launch argument");
785         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
786
787         String actualAppId = appId;
788 #if 0
789         if (appId.GetLength() == 10)
790         {
791                 const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
792
793                 if (!execName.IsEmpty())
794                 {
795                         actualAppId.Append(L'.');
796                         actualAppId.Append(execName);
797                 }
798         }
799 #endif
800
801         pArg->UpdateRequestId(req);
802
803         if (_AppImpl::GetInstance() != null)
804         {
805                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
806                 pArg->UpdateWindowHandle(handle);
807         }
808
809         int pid = -1;
810         bundle* kb = NULL;
811         String tempId;
812
813         actualAppId.SubString(0, 10, tempId);
814
815         const int type = _AppInfo::GetAppType();
816         if ((!(type & _APP_TYPE_SERVICE_APP)) && _IsDefaultApplication(tempId, appId))
817         {
818                 tempId += L'.';
819                 tempId += L"_AppControl";
820
821                 // [INFO] Ugly solution for submode support
822                 pArg->UpdateAppId(tempId);
823                 kb = pArg->GetBundle();
824
825                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
826                 if (pid >= 0)
827                 {
828                         SysLog(NID_APP, "Submode launch successful");
829                         SetLastResult(E_SUCCESS);
830                         return pid;
831                 }
832                 else if (pid == APPSVC_RET_EINVAL)
833                 {
834                         SetLastResult(E_MAX_EXCEEDED);
835                         return pid;
836                 }
837         }
838
839         pArg->UpdateAppId(actualAppId);
840
841         // retry for possible failure
842         int count = 0;
843         const int TRY_COUNT = 3;
844         const int TRY_SLEEP_TIME = 65;
845         do
846         {
847                 kb = pArg->GetBundle();
848                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
849                 if (pid >= 0)
850                 {
851                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
852                         SetLastResult(E_SUCCESS);
853                         return pid;
854                 }
855                 else if (pid == APPSVC_RET_EINVAL)
856                 {
857                         SetLastResult(E_MAX_EXCEEDED);
858                         return pid;
859                 }
860
861                 count++;
862                 SysLog(NID_APP, "Waiting %dth time with %d.", count, pid);
863                 Thread::Sleep(TRY_SLEEP_TIME);
864         }
865         while (count < TRY_COUNT);
866
867         result r = E_SUCCESS;
868         switch (pid)
869         {
870         case APPSVC_RET_EILLACC:
871                 r = E_ILLEGAL_ACCESS;
872                 break;
873         default:
874                 r = E_SYSTEM;
875                 break;
876         }
877
878         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
879
880         SetLastResult(r);
881
882         return pid;
883 }
884
885 result
886 _AppControlManager::LaunchAppImplicit(_AppArg* pArg, int req)
887 {
888         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
889
890         result r = E_SUCCESS;
891         bundle* kb = pArg->GetBundle();
892
893         if (req >= 0)
894         {
895                 pArg->UpdateRequestId(req);
896                 appsvc_add_data(kb, SELECTOR_NOTI_KEY, appinfo_get_appid());
897         }
898
899         if (_AppImpl::GetInstance() != null)
900         {
901                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
902                 _AppArg::UpdateWindowHandle(kb, handle);
903         }
904
905         int pid = appsvc_run_service(kb, req, LaunchResultCb, this);
906         if (pid >= 0)
907         {
908                 if (pid == 0)
909                 {
910                         SysLog(NID_APP, "Sending local process again.");
911                         pid = getpid();
912                 }
913
914                 char pkgname[255] = {0, };
915                 if (aul_app_get_pkgname_bypid(pid, pkgname, 255) != AUL_R_OK)
916                 {
917                         SysLog(NID_APP, "Fail to get package name by pid : (%d).", pid);
918                         return E_SYSTEM;
919                 }
920
921                 if (strncmp(pkgname, APP_SELECTOR, strlen(APP_SELECTOR)) != 0)
922                 {
923                         const char* pOperation = appsvc_get_operation(kb);
924
925                         SysLog(NID_APP, "Starting application without selector : (%s, %s).", pkgname, pOperation);
926
927                         SendAppControlStartResponse(req, pkgname, pOperation);
928                 }
929         }
930         else
931         {
932                 switch (pid)
933                 {
934                         case APPSVC_RET_EINVAL:
935                                 r = E_OBJ_NOT_FOUND;
936                                 break;
937                         case APPSVC_RET_ENOMATCH:
938                                 r = E_OBJ_NOT_FOUND;
939                                 break;
940                         case APPSVC_RET_EILLACC:
941                                 r = E_ILLEGAL_ACCESS;
942                                 break;
943                         case APPSVC_RET_ERROR:
944                                 // fall through
945                         case APPSVC_RET_ELAUNCH:
946                                 // fall through
947                         default:
948                                 r = E_SYSTEM;
949                                 break;
950                 }
951         }
952
953         SysLog(NID_APP, "[%s] Application(%d) launched with reqId(%d) and arg(0x%x).", GetErrorMessage(r), pid, req, pArg);
954
955         return r;
956 }
957
958 void
959 _AppControlManager::FinishAppControl(int reqId, int res, IMap* pMap)
960 {
961         SysLog(NID_APP, "req %d, res %d.", reqId, res);
962         _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap, _APPCONTROL_PROPERTY_SUBMODE);
963         SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
964
965         SendAppControlEvent(*pArg);
966         SysLog(NID_APP, "Exit.");
967 }
968
969 void
970 _AppControlManager::RemoveResultRequest(int reqId)
971 {
972         __resultManager.RemoveItem(reqId);
973 }
974
975 const _AppArg*
976 _AppControlManager::FindResultRequest(int reqId) const
977 {
978         const _ResultInfo* pInfo = __resultManager.FindItem(reqId);
979         return (pInfo) ? &(pInfo->arg) : null;
980 }
981
982 int
983 _AppControlManager::AddLaunchRequest(_AppArg* pArg, LaunchCbType pCb, void* pData, int prop)
984 {
985         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Empty argument.");
986
987         _LaunchInfo* pItem = new (std::nothrow) _LaunchInfo(pArg, pCb, pData, prop);
988         SysTryReturn(NID_APP, pItem != null, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
989
990         SysLog(NID_APP, "Registering callback 0x%x, 0x%x", pCb, pData);
991
992         return __launchManager.InsertItem(pItem);
993 }
994
995 void
996 _AppControlManager::RemoveLaunchRequest(int req)
997 {
998         __launchManager.RemoveItem(req);
999 }
1000
1001 result
1002 _AppControlManager::RegisterRequest(service_s* service, int& req, _AppHandler& handler)
1003 {
1004         bundle* b = _AppArg::GetBundleFromSvc(service);
1005
1006         _AppArg* pArg = new (std::nothrow) _AppArg();
1007         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "ArrayList creation failure.");
1008         pArg->Construct(b);
1009
1010         result r = E_SUCCESS;
1011
1012         // ownership is transfered to RequestManager
1013         _ResultInfo* pItem = new (std::nothrow) _ResultInfo(*pArg);
1014         SysTryCatch(NID_APP, pItem != null, , r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
1015
1016         req = __resultManager.InsertItem(pItem);
1017         SysTryCatch(NID_APP, req != -1, , r = E_INVALID_STATE, "[E_INVALID_STATE] Invalid argument handling state.");
1018
1019         handler = _AppArg::GetHandler(b);
1020
1021         return E_SUCCESS;
1022
1023 CATCH:
1024         delete pArg;
1025
1026         return r;
1027 }
1028
1029
1030 AppCtrlResult
1031 _AppControlManager::ConvertAppControlResultCode(int resCode)
1032 {
1033         AppCtrlResult ret = APP_CTRL_RESULT_FAILED;
1034
1035         switch(resCode)
1036         {
1037                 case SERVICE_RESULT_SUCCEEDED:
1038                         ret = APP_CTRL_RESULT_SUCCEEDED;
1039                         break;
1040                 case SERVICE_RESULT_FAILED:
1041                         ret = APP_CTRL_RESULT_CANCELED;
1042                         break;
1043                 case SERVICE_RESULT_CANCELED:
1044                         ret = APP_CTRL_RESULT_ABORTED;
1045                         break;
1046                 case APPSVC_OSP_RES_FAIL:
1047                         ret = APP_CTRL_RESULT_FAILED;
1048                         break;
1049                 case APPSVC_OSP_RES_TERMINATE:
1050                         ret = APP_CTRL_RESULT_TERMINATED;
1051                         break;
1052                 default:
1053                         ret = APP_CTRL_RESULT_FAILED;
1054                         break;
1055         }
1056
1057         return ret;
1058 }
1059
1060
1061 void
1062 _AppControlManager::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
1063 {
1064         const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
1065
1066         if (pEventArg != null)
1067         {
1068                 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
1069
1070                 if(pResponseListener != null)
1071                 {
1072                         if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_START)
1073                         {
1074                                 pResponseListener->OnAppControlStartResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetResult());
1075                                 SysLog(NID_APP, "OnAppControlStartResponseReceived called");
1076                         }
1077                         else
1078                         {
1079                                 InvokeAppControlCompleteListener(*pResponseListener, pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData(), pEventArg->IsSubMode());
1080                                 SysLog(NID_APP, "Listener called");
1081
1082                                 _AppControlResponseEvent* pResponseEvent = null;
1083                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
1084                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
1085
1086                                 delete pResponseEvent;
1087                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
1088                         }
1089                 }
1090                 else
1091                 {
1092                         SysLog(NID_APP, "Invalid ResponseListener");
1093                 }
1094         }
1095         else
1096         {
1097                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
1098         }
1099 }
1100
1101 }} // Tizen::App