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