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