Merge "[2.2.1] Modify String::Replace() which shared buffer even when the whole strin...
[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 <FBaseRt_LibraryImpl.h>
50 #include <FIo_DataControlResultSetImpl.h>
51
52 #include "FApp_AppArg.h"
53 #include "FApp_AppControlEventArg.h"
54 #include "FApp_AppControlRegistry.h"
55 #include "FApp_AppControlImpl.h"
56 #include "FApp_AppImpl.h"
57 #include "FApp_AppInfo.h"
58 #include "FApp_Aul.h"
59 #include "FApp_AppControlManager.h"
60 #include "FApp_AppManagerProxy.h"
61 #include "FApp_ConditionManagerProxy.h"
62 #include "FApp_MapDataControlImpl.h"
63 #include "FApp_SqlDataControlImpl.h"
64 #include "FAppPkg_PackageManagerImpl.h"
65 #include "FAppPkg_PackageInfoImpl.h"
66 #include "FApp_AppMessageImpl.h"
67 #include "FApp_AppManagerImpl.h"
68 #include "FApp_AppControlResponseEvent.h"
69
70 using namespace Tizen::App::Package;
71 using namespace Tizen::Base;
72 using namespace Tizen::Base::Collection;
73 using namespace Tizen::Base::Runtime;
74 using namespace Tizen::Base::Utility;
75 using namespace Tizen::Io;
76
77 namespace
78 {
79 const char SELECTOR_NOTI_KEY[] = "__APP_SVC_CALLER_NOTI__";
80 }
81
82 namespace Tizen { namespace App
83 {
84 const wchar_t TIZEN_OPERATION_PICK[] = L"http://tizen.org/appcontrol/operation/pick";
85
86
87 _AppControlManager::_AppControlManager(void)
88 {
89         SysLog(NID_APP, "");
90
91         // AppControl event handling is expected to be performed in the main thread.
92         __appControlEvent.Construct();
93         __appControlEvent.AddListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
94         __listenerList.Construct();
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 && (!__listenerList.Contains(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 && (!__listenerList.Contains(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         result (* pFunc)(int req) = null;
349         pFunc = reinterpret_cast<result (*)(int)>(pInfo->pLib->GetProcAddress(L"TerminateAppControl"));
350         if (pFunc)
351         {
352                 (*pFunc)(pInfo->reqId);
353         }
354         else
355         {
356                 SysLogException(NID_APP, E_SYSTEM, "No TerminateAppControl() function.");
357         }
358
359         // remove from list and unload dll
360         __inAppManager.RemoveItem(reqId);
361 }
362
363
364 result
365 _AppControlManager::SendAppControlEvent(IEventArg& arg)
366 {
367         return __appControlEvent.FireAsync(arg);
368 }
369
370 Tizen::Base::Collection::IMapT<int,_AppControlResponseEvent*>*
371 _AppControlManager::GetAppControlResponseEventContainer(void)
372 {
373         return &__appControlResponseEventContainer;
374 }
375
376
377 // generic launch callback
378 static void
379 LaunchResultCb(bundle* b, int request_code, appsvc_result_val res, void* data)
380 {
381         SysLog(NID_APP, "SLP callee result: %d", res);
382
383         _AppControlManager* pImpl = static_cast<_AppControlManager*>(data);
384         if (pImpl == null)
385         {
386                 return;
387         }
388
389         _AppArg* pAppArg = new (std::nothrow) _AppArg;
390         SysTryReturnVoidResult(NID_APP, pAppArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
391
392         _AppControlEventArg* pArg = null;
393         result r = pAppArg->Construct(b);
394         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] AppControl event argument creation failure.", GetErrorMessage(r));
395
396         pArg = new (std::nothrow) _AppControlEventArg(request_code, pAppArg, res);
397         SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, r, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
398
399         //_AppArg::Print(b);
400         pImpl->SendAppControlEvent(*pArg);
401
402         return;
403
404 CATCH:
405         delete pAppArg;
406 }
407
408
409 result
410 _AppControlManager::SendAppControlStartResponse(int req, const char* pValue, const char* pOp)
411 {
412         _AppControlStartEventArg* pArg = new (std::nothrow) _AppControlStartEventArg(req, AppId(pValue), String(pOp));
413         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "AppControl start event creation failure.");
414
415         SendAppControlEvent(*pArg);
416
417         return E_SUCCESS;
418 }
419
420
421 result
422 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
423 {
424         bundle* kb = msg.GetBundle();
425         SysTryReturnResult(NID_APP, kb != NULL, E_OUT_OF_MEMORY, "Bundle allocation failure.");
426
427         if (pkg_name)
428         {
429                 appsvc_set_pkgname(kb, pkg_name);
430         }
431
432         appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
433
434         if (mime)
435         {
436                 appsvc_set_mime(kb, mime);
437         }
438
439         if (uri)
440         {
441                 appsvc_set_uri(kb, uri);
442         }
443
444         if (_AppImpl::GetInstance() != null)
445         {
446                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
447                 _AppArg::UpdateWindowHandle(kb, handle);
448         }
449
450         SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
451         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
452
453         result r = E_SUCCESS;
454         if (pid < 0)
455         {
456                 switch (pid)
457                 {
458                 case APPSVC_RET_EILLACC:
459                         r = E_ILLEGAL_ACCESS;
460                         break;
461                 case APPSVC_RET_EINVAL:
462                         r = E_MAX_EXCEEDED;
463                         break;
464                 default:
465                         r = E_SYSTEM;
466                         break;
467                 }
468                 SysLog(NID_APP, "[%s] Launching service %s failure", GetErrorMessage(r), pkg_name);
469         }
470
471         return r;
472 }
473
474
475 int
476 _AppControlManager::Launch(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
477 {
478         bundle* kb = msg.GetBundle();
479         SysTryReturn(NID_APP, kb != NULL, -1, E_OUT_OF_MEMORY, "Bundle allocation failure.");
480
481         if (pkg_name)
482         {
483                 appsvc_set_pkgname(kb, pkg_name);
484         }
485
486         appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
487
488         if (mime)
489         {
490                 appsvc_set_mime(kb, mime);
491         }
492
493         if (uri)
494         {
495                 appsvc_set_uri(kb, uri);
496         }
497
498         if (_AppImpl::GetInstance() != null)
499         {
500                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
501                 _AppArg::UpdateWindowHandle(kb, handle);
502         }
503
504         SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
505         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
506
507         result r = E_SUCCESS;
508         if (pid < 0)
509         {
510                 switch (pid)
511                 {
512                 case APPSVC_RET_EILLACC:
513                         r = E_ILLEGAL_ACCESS;
514                         break;
515                 case APPSVC_RET_EINVAL:
516                         r = E_MAX_EXCEEDED;
517                         break;
518                 default:
519                         r = E_SYSTEM;
520                         break;
521                 }
522                 SysLog(NID_APP, "[%s]Launching service %s failure", GetErrorMessage(r), pkg_name);
523         }
524         SetLastResult(r);
525
526         return pid;
527 }
528
529
530 int
531 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const AppId& appId, const String& opId, const String* pUri, const String* pMime, AppSvcResFn pCb, void* data)
532 {
533         std::unique_ptr<char[]> pPackage(_StringConverter::CopyToCharArrayN(appId));
534         std::unique_ptr<char[]> pOperation(_StringConverter::CopyToCharArrayN(opId));
535
536         const char* pUriData = null;
537         if (pUri)
538         {
539                 pUriData =  _StringConverter::CopyToCharArrayN(*pUri);
540         }
541
542         const char* pMimeData = null;
543         if (pMime)
544         {
545                 pMimeData = _StringConverter::CopyToCharArrayN(*pMime);
546         }
547
548         int pid = Launch(msg, pPackage.get(), pOperation.get(), pMimeData, pUriData, pCb, data);
549
550         delete [] pUriData;
551         delete [] pMimeData;
552
553         return pid;
554 }
555
556
557 result
558 _AppControlManager::LaunchPkg(const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
559 {
560         _AppMessageImpl msg;
561
562         return LaunchPkg(msg, pkg_name, op, mime, uri, pCb, data);
563 }
564
565 result
566 _AppControlManager::LaunchAppWithCondition(const AppId& appId, const String& condition, IList* pArrayArgs)
567 {
568         result r = E_SUCCESS;
569         _AppArg * pArg = new (std::nothrow) _AppArg();
570         SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]");
571
572         r = pArg->ConstructForAppLaunchCondition(condition, pArrayArgs);
573         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] ConstructForAppLaunchCondition(%ls, .. ) fails", GetErrorMessage(r), condition.GetPointer());
574
575         r = _AppControlManager::LaunchApp(appId, pArg);
576 CATCH:
577         delete pArg;
578         return r;
579 }
580
581 result
582 _AppControlManager::LaunchApp(const AppId& appId, _AppArg* pArg, int req)
583 {
584         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
585         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
586
587         String actualAppId = appId;
588         if (appId.GetLength() == 10)
589         {
590                 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
591
592                 if (!name.IsEmpty())
593                 {
594                         actualAppId.Append(L'.');
595                         actualAppId.Append(name);
596                 }
597         }
598
599         pArg->UpdateRequestId(req);
600
601         if (_AppImpl::GetInstance() != null)
602         {
603                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
604                 pArg->UpdateWindowHandle(handle);
605         }
606
607         int pid = -1;
608         bundle* kb = NULL;
609         String tempId;
610         actualAppId.SubString(0, 10, tempId);
611         tempId += L'.';
612         tempId += L"_AppControl";
613
614         // [INFO] Ugly solution for submode support
615         pArg->UpdateAppId(tempId);
616         kb = pArg->GetBundle();
617         
618         pid = appsvc_run_service(kb, req, LaunchResultCb, this);
619         if (pid >= 0)
620         {
621                 SysLog(NID_APP, "Submode launch successful");
622                 return E_SUCCESS;
623         }
624         else if (pid == APPSVC_RET_EINVAL)
625         {
626                 SysLog(NID_APP, "Argument overflow");
627                 return E_MAX_EXCEEDED;
628         }
629
630         pArg->UpdateAppId(actualAppId);
631
632         // retry for possible failure
633         int count = 0;
634         const int TRY_COUNT = 3;
635         const int TRY_SLEEP_TIME = 65;
636         do
637         {
638                 kb = pArg->GetBundle();
639                 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
640                 if (pid >= 0)
641                 {
642                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
643                         return E_SUCCESS;
644                 }
645                 else if (pid == APPSVC_RET_EINVAL)
646                 {
647                         SysLog(NID_APP, "Argument overflow");
648                         return E_MAX_EXCEEDED;
649                 }
650
651                 count++;
652                 SysLog(NID_APP, "Waiting %dth time.", count);
653                 Thread::Sleep(TRY_SLEEP_TIME);
654         }
655         while (count < TRY_COUNT);
656
657         result r = E_SUCCESS;
658         switch (pid)
659         {
660         case APPSVC_RET_EILLACC:
661                 r = E_ILLEGAL_ACCESS;
662                 break;
663         default:
664                 r = E_SYSTEM;
665                 break;
666         }
667
668         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
669
670         return r;
671 }
672
673 static bool
674 _IsDefaultApplication(const AppId& packageId, const String& appId)
675 {
676         const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
677
678         int index = -1;
679         result r = appId.IndexOf(L'.', 0, index);
680         if (r != E_SUCCESS)
681         {
682                 return false;
683         }
684
685         String tmp;
686         appId.SubString(index + 1, tmp);
687         if (tmp == execName)
688         {
689                 SysLog(NID_APP, "Default application %ls", tmp.GetPointer());
690                 return true;
691         }
692
693         return false;
694 }
695
696
697 int
698 _AppControlManager::Launch(const _AppMessageImpl& msg, const AppId& aId, const String& oId, const String* pUriData, const String* pMimeType, AppSvcResFn pCb, void* pData)
699 {
700         SysLog(NID_APP, "Enter");
701
702         _AppArg arg;
703         arg.Construct(msg, oId, pUriData, pMimeType);
704
705         int pid = Launch(aId, &arg, pCb, pData, -1); 
706         SysTryReturn(NID_APP, pid >= 0, -1, GetLastResult(), "Launching(%ls) is failed", aId.GetPointer());
707
708         SysLog(NID_APP, "Exit");
709
710         return pid;
711 }
712
713
714 int
715 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
716 {
717         return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
718 }
719
720
721 int
722 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, AppSvcResFn pCb, void* pData, int req)
723 {
724         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Invalid launch argument");
725         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
726
727         String actualAppId = appId;
728 #if 0
729         if (appId.GetLength() == 10)
730         {
731                 const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
732
733                 if (!execName.IsEmpty())
734                 {
735                         actualAppId.Append(L'.');
736                         actualAppId.Append(execName);
737                 }
738         }
739 #endif
740
741         pArg->UpdateRequestId(req);
742
743         if (_AppImpl::GetInstance() != null)
744         {
745                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
746                 pArg->UpdateWindowHandle(handle);
747         }
748
749         int pid = -1;
750         bundle* kb = NULL;
751         String tempId;
752
753         actualAppId.SubString(0, 10, tempId);
754
755         const int type = _AppInfo::GetAppType();
756         if ((!(type & _APP_TYPE_SERVICE_APP)) && _IsDefaultApplication(tempId, appId))
757         {
758                 tempId += L'.';
759                 tempId += L"_AppControl";
760
761                 // [INFO] Ugly solution for submode support
762                 pArg->UpdateAppId(tempId);
763                 kb = pArg->GetBundle();
764
765                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
766                 if (pid >= 0)
767                 {
768                         SysLog(NID_APP, "Submode launch successful");
769                         SetLastResult(E_SUCCESS);
770                         return pid;
771                 }
772                 else if (pid == APPSVC_RET_EINVAL)
773                 {
774                         SetLastResult(E_MAX_EXCEEDED);
775                         return pid;
776                 }
777         }
778
779         pArg->UpdateAppId(actualAppId);
780
781         // retry for possible failure
782         int count = 0;
783         const int TRY_COUNT = 3;
784         const int TRY_SLEEP_TIME = 65;
785         do
786         {
787                 kb = pArg->GetBundle();
788                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
789                 if (pid >= 0)
790                 {
791                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
792                         SetLastResult(E_SUCCESS);
793                         return pid;
794                 }
795                 else if (pid == APPSVC_RET_EINVAL)
796                 {
797                         SetLastResult(E_MAX_EXCEEDED);
798                         return pid;
799                 }
800
801                 count++;
802                 SysLog(NID_APP, "Waiting %dth time with %d.", count, pid);
803                 Thread::Sleep(TRY_SLEEP_TIME);
804         }
805         while (count < TRY_COUNT);
806
807         result r = E_SUCCESS;
808         switch (pid)
809         {
810         case APPSVC_RET_EILLACC:
811                 r = E_ILLEGAL_ACCESS;
812                 break;
813         default:
814                 r = E_SYSTEM;
815                 break;
816         }
817
818         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
819
820         SetLastResult(r);
821
822         return pid;
823 }
824
825 result
826 _AppControlManager::LaunchAppImplicit(_AppArg* pArg, int req)
827 {
828         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
829
830         result r = E_SUCCESS;
831         bundle* kb = pArg->GetBundle();
832
833         if (req >= 0)
834         {
835                 pArg->UpdateRequestId(req);
836                 appsvc_add_data(kb, SELECTOR_NOTI_KEY, appinfo_get_appid());
837         }
838
839         if (_AppImpl::GetInstance() != null)
840         {
841                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
842                 _AppArg::UpdateWindowHandle(kb, handle);
843         }
844
845         int pid = appsvc_run_service(kb, req, LaunchResultCb, this);
846         if (pid >= 0)
847         {
848                 if (pid == 0)
849                 {
850                         SysLog(NID_APP, "Sending local process again.");
851                         pid = getpid();
852                 }
853
854                 char pkgname[255] = {0, };
855                 if (aul_app_get_pkgname_bypid(pid, pkgname, 255) != AUL_R_OK)
856                 {
857                         SysLog(NID_APP, "Fail to get package name by pid : (%d).", pid);
858                         return E_SYSTEM;
859                 }
860
861                 if (strncmp(pkgname, APP_SELECTOR, strlen(APP_SELECTOR)) != 0)
862                 {
863                         const char* pOperation = appsvc_get_operation(kb);
864
865                         SysLog(NID_APP, "Starting application without selector : (%s, %s).", pkgname, pOperation);
866
867                         SendAppControlStartResponse(req, pkgname, pOperation);
868                 }
869         }
870         else
871         {
872                 switch (pid)
873                 {
874                         case APPSVC_RET_EINVAL:
875                                 r = E_OBJ_NOT_FOUND;
876                                 break;
877                         case APPSVC_RET_ENOMATCH:
878                                 r = E_OBJ_NOT_FOUND;
879                                 break;
880                         case APPSVC_RET_EILLACC:
881                                 r = E_ILLEGAL_ACCESS;
882                                 break;
883                         case APPSVC_RET_ERROR:
884                                 // fall through
885                         case APPSVC_RET_ELAUNCH:
886                                 // fall through
887                         default:
888                                 r = E_SYSTEM;
889                                 break;
890                 }
891         }
892
893         SysLog(NID_APP, "[%s] Application(%d) launched with reqId(%d) and arg(0x%x).", GetErrorMessage(r), pid, req, pArg);
894
895         return r;
896 }
897
898 void
899 _AppControlManager::FinishAppControl(int reqId, int res, IMap* pMap)
900 {
901         SysLog(NID_APP, "req %d, res %d.", reqId, res);
902         _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap, _APPCONTROL_PROPERTY_SUBMODE);
903         SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
904
905         SendAppControlEvent(*pArg);
906         SysLog(NID_APP, "Exit.");
907 }
908
909 void
910 _AppControlManager::RemoveResultRequest(int reqId)
911 {
912         __resultManager.RemoveItem(reqId);
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