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