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