N_SE-53194 : fix AppControl::Stop() without listener
[platform/framework/native/appfw.git] / src / app / FApp_AppControlImpl.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_AppControlImpl.cpp
19  * @brief               This is the implementation for the Application Control class.
20  */
21
22 #include <new>
23 #include <typeinfo>
24 #include <unique_ptr.h>
25
26 #include <appsvc/appsvc.h>
27
28 #include <FBaseColHashMap.h>
29 #include <FBaseSysLog.h>
30 #include <FAppAppControl.h>
31 #include <FAppAppManager.h>
32 #include <FAppPkgPackageAppInfo.h>
33 #include <FAppIAppControlEventListener.h>
34 #include <FAppIAppControlResponseListener.h>
35
36 #include <FIo_DirectoryImpl.h>
37
38 #include "FApp_AppControlImpl.h"
39 #include "FApp_AppControlManager.h"
40 #include "FApp_AppArg.h"
41 #include "FApp_AppControlRegistry.h"
42 #include "FApp_AppMessageImpl.h"
43 #include "FApp_AppInfo.h"
44 #include "FAppPkg_PackageManagerImpl.h"
45 #include "FApp_Aul.h"
46 #include "FApp_AppControlEventArg.h"
47 #include "FApp_AppControlResponseEvent.h"
48 #include "FBaseRt_ThreadImpl.h"
49
50 using namespace Tizen::Base;
51 using namespace Tizen::Base::Collection;
52 using namespace Tizen::Base::Runtime;
53 using namespace Tizen::App;
54 using namespace Tizen::App::Package;
55 using namespace Tizen::Io;
56
57 namespace
58 {
59
60 static const int _REQ_ID_INVALID = -1;
61
62 }
63
64 namespace Tizen { namespace App
65 {
66
67 const wchar_t TIZEN_OPERATION_MAIN[] = L"http://tizen.org/appcontrol/operation/main";
68
69 _AppControlImpl::_AppControlImpl(const AppControl& value)
70         : _appControl(value)
71         , _reqId(_REQ_ID_INVALID)
72         , _property(_APPCONTROL_PROPERTY_NONE)
73         , _processId(_REQ_ID_INVALID)
74 {
75         __appControlResponseEventList.Construct();
76 }
77
78 _AppControlImpl::~_AppControlImpl(void)
79 {
80         IEnumeratorT<int>* pEnum = __appControlResponseEventList.GetEnumeratorN();
81         IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = null;
82         if(pEnum != null)
83         {
84                 pResponseEventContainer = _AppControlManager::GetInstance()->GetAppControlResponseEventContainer();
85         }
86
87         while(pEnum->MoveNext() == E_SUCCESS)
88         {
89                 int reqId;
90                 pEnum->GetCurrent(reqId);
91                 if (pResponseEventContainer != null)
92                 {
93                         _AppControlResponseEvent* pResponseEvent = null;
94                         pResponseEventContainer->GetValue(reqId, pResponseEvent);
95                         delete pResponseEvent;
96
97                         pResponseEventContainer->Remove(reqId);
98                         SysLog(NID_APP, "pResponseEvent gets deleted. reqId(%d)", reqId);
99                 }
100         }
101         delete pEnum;
102 }
103
104 AppControl*
105 _AppControlImpl::CreateN(const String& path, const String& aId, const String& oId, const String& name, int prop)
106 {
107         SysTryReturn(NID_APP, !path.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Path is empty.");
108         SysTryReturn(NID_APP, !aId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Provider Id is empty.");
109         SysTryReturn(NID_APP, !oId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Operation Id is empty.");
110
111         AppControl* pAc = new (std::nothrow) AppControl;
112         SysTryReturn(NID_APP, pAc != null, null, E_OUT_OF_MEMORY, "AppControl allocation failure.");
113
114         _AppControlImpl* pImpl = pAc->__pAppControlImpl;
115         SysTryReturn(NID_APP, pImpl != null, null, E_OUT_OF_MEMORY, "AppControlImpl instance must not be null.");
116
117         pImpl->_path = path;
118         pImpl->_provider = aId;
119         pImpl->_opId = oId;
120         // [FIXME] Proper App name setting
121         pImpl->_appName = name;
122         pImpl->_property = prop;
123
124         return pAc;
125 }
126
127 AppControl*
128 _AppControlImpl::CreateN(const AppId& appId, const String& operationId, bool changeAppId)
129 {
130         SysTryReturn(NID_APP, !appId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] appId is empty.");
131
132         AppControl* pAc = new (std::nothrow) AppControl;
133         SysTryReturn(NID_APP, pAc != null, null, E_OUT_OF_MEMORY, "AppControl allocation failure.");
134
135         _AppControlImpl* pImpl = pAc->__pAppControlImpl;
136         SysTryReturn(NID_APP, pImpl != null, null, E_OUT_OF_MEMORY, "AppControlImpl instance must not be null.");
137
138         pImpl->_path = appId;
139         pImpl->_provider = appId;
140         pImpl->_opId = operationId;
141         //pImpl->_appName = appId;
142         pImpl->_property |= (_APPCONTROL_PROPERTY_OSP | _APPCONTROL_PROPERTY_PUBLIC);
143
144         if (changeAppId)
145         {
146                 pImpl->_property |= _APPCONTROL_PROPERTY_APPID_CHANGE;
147         }
148
149         return pAc;
150 }
151
152 AppControl*
153 _AppControlImpl::CreateN(const AppControl& ac)
154 {
155         const _AppControlImpl* pImpl = GetInstance(ac);
156         SysTryReturn(NID_APP, pImpl != null, null, E_INVALID_STATE, "AppControlImpl instance must not be null.");
157
158         return CreateN(pImpl->_path, pImpl->_provider, pImpl->_opId, pImpl->_appName, pImpl->_property);
159 }
160
161 const _AppControlImpl*
162 _AppControlImpl::GetInstance(const AppControl& ac)
163 {
164         return ac.__pAppControlImpl;
165 }
166
167 _AppControlImpl*
168 _AppControlImpl::GetInstance(AppControl& ac)
169 {
170         return ac.__pAppControlImpl;
171 }
172
173 result
174 _AppControlImpl::Start(const IList* pDataList, IAppControlEventListener* pListener)
175 {
176         SysLog(NID_APP, "Enter");
177         result r = E_SYSTEM;
178
179         if (_property & _APPCONTROL_PROPERTY_SLP)
180         {
181                 r = StartNative(pDataList, pListener);
182         }
183         else if (_property & _APPCONTROL_PROPERTY_OSP)
184         {
185                 r = StartOsp(pDataList, pListener);
186         }
187         else
188         {
189                 SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] Invalid AppControl type(property %d)", _property);
190         }
191         SysLog(NID_APP, "Exit");
192
193         return r;
194 }
195
196 result
197 _AppControlImpl::Start(const String* pUriData, const String* pDataType, const IMap* pExtraData, IAppControlResponseListener* pListener)
198 {
199         SysLog(NID_APP, "Enter");
200         result r = E_SYSTEM;
201
202         if (_property & _APPCONTROL_PROPERTY_SLP)
203         {
204                 r = StartNative(pUriData, pDataType, pExtraData, pListener);
205         }
206         else if (_property & _APPCONTROL_PROPERTY_OSP)
207         {
208                 r = StartOsp(pUriData, pDataType, pExtraData, pListener);
209         }
210         else
211         {
212                 SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] Invalid AppControl type(property %d)", _property);
213         }
214         SysLog(NID_APP, "Exit");
215
216         return r;
217 }
218
219 result
220 _AppControlImpl::FindAndStart(const String& operationId, const String* pUriPattern, const String* pDataType, const String* pCategory, const IMap* pExtraData, IAppControlResponseListener* pListener)
221 {
222         // [FIXME] valid argument size checking required
223         SysLog(NID_APP, "Enter");
224
225         std::unique_ptr<bundle, BundleDeleter> pBundle(bundle_create());
226         SysTryReturnResult(NID_APP, pBundle.get(), E_OUT_OF_MEMORY, "Bundle creation failure.");
227
228         _AppMessageImpl::SetOperation(pBundle.get(), operationId);
229
230         if (pUriPattern)
231         {
232                 _AppMessageImpl::SetUri(pBundle.get(), *pUriPattern);
233         }
234
235         if (pDataType)
236         {
237                 String mimeType = *pDataType;
238
239                 if ((*pDataType)[0] == L'.')
240                 {
241                         SysLog(NID_APP, "Extension to MIME conversion for %ls", pDataType->GetPointer());
242
243 #if 0
244                         String ext;
245                         pDataType->SubString(1, ext);
246
247                         result r = _AppControlManager::GetMimeFromExt(ext, mimeType);
248
249                         SysTryReturn(NID_APP, !IsFailed(r), null, r, "[%s] MIME type conversion failure for %ls.", GetErrorMessage(r), ext.GetPointer());
250
251                         pMimeType = &mimeType;
252
253                         SysLog(NID_APP, "Conversion : %ls -> %ls.", pDataType->GetPointer(), pMimeType->GetPointer());
254 #endif
255                 }
256
257                 _AppMessageImpl::SetMime(pBundle.get(), mimeType);
258         }
259
260         if (pCategory)
261         {
262                 _AppMessageImpl::SetCategory(pBundle.get(), *pCategory);
263         }
264
265         return StartImplicit(pBundle.get(), pExtraData, pListener);
266 }
267
268 result
269 _AppControlImpl::StartOsp(const IList* pDataList, IAppControlEventListener* pListener)
270 {
271         SysLog(NID_APP, "Enter");
272         result r = E_SUCCESS;
273
274         _AppArg* pArg = new (std::nothrow) _AppArg;
275         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
276
277         pArg->Construct(*this, pDataList);
278
279         _AppControlManager* pImpl = _AppControlManager::GetInstance();
280         int req = _REQ_ID_INVALID;
281
282         if (pListener)
283         {
284                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCbLegacy, pListener, _property);
285                 req = reqObj.GetRequestNumber();
286
287                 _processId = pImpl->Launch(_path, pArg, req);
288
289                 if (_processId < 0)
290                 {
291                         reqObj.Invalidate();
292                         r = GetLastResult();
293                         SysLog(NID_APP, "[%s]Launching(%ls) is failed" , GetErrorMessage(r), _path.GetPointer());
294                         return r;
295                 }
296         }
297         else
298         {
299                 _processId = pImpl->Launch(_path, pArg);
300                 delete pArg;
301                 SysTryReturnResult(NID_APP, _processId >= 0, GetLastResult(), "Launching(%ls) is failed", _path.GetPointer());
302         }
303         SysLog(NID_APP, "Exit");
304
305         return r;
306 }
307
308 result
309 _AppControlImpl::StartOsp(const String* pUriData, const String* pMimeType, const IMap* pDataList, IAppControlResponseListener* pListener)
310 {
311         SysLog(NID_APP, "Enter");
312         result r = E_SUCCESS;
313
314         _AppArg* pArg = new (std::nothrow) _AppArg;
315         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
316
317         pArg->Construct(*this, pUriData, pMimeType, pDataList);
318
319         _AppControlManager* pImpl = _AppControlManager::GetInstance();
320         int req = _REQ_ID_INVALID;
321
322         if (pListener)
323         {
324                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCb, pListener, _property);
325                 req = reqObj.GetRequestNumber();
326
327                 if (_ThreadImpl::GetCurrentThreadImpl()->GetThreadType() == THREAD_TYPE_EVENT_DRIVEN)
328                 {
329                         _AppControlResponseEvent* pAppControlResponseEvent = new (std::nothrow) _AppControlResponseEvent();
330                         if (pAppControlResponseEvent != null)
331                         {
332                                 r = pAppControlResponseEvent->Construct();
333                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::Construct() is failed", GetErrorMessage(r));
334
335                                 r = pAppControlResponseEvent->AddListener(*this, true);
336                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::AddListener() is failed", GetErrorMessage(r));
337
338                                 IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = pImpl->GetAppControlResponseEventContainer();
339                                 if (pResponseEventContainer != null)
340                                 {
341                                         pResponseEventContainer->Add(req, pAppControlResponseEvent);
342                                         __appControlResponseEventList.Add(req);
343                                         SysLog(NID_APP, "pResponseEvent gets added. reqId(%d)", req);
344                                 }
345                         }
346                 }
347
348                 _processId = pImpl->Launch(_path, pArg, req);           
349                 if (_processId < 0)
350                 {
351                         reqObj.Invalidate();
352                         r = GetLastResult();
353                         SysLog(NID_APP, "[%s]Launching(%ls) is failed" , GetErrorMessage(r), _path.GetPointer());
354                         return r;
355                 }
356         }
357         else
358         {
359                 _processId = pImpl->Launch(_path, pArg);
360                 delete pArg;
361                 SysTryReturnResult(NID_APP, _processId >= 0, GetLastResult(), "Launching(%ls) is failed", _path.GetPointer());
362         }
363         SysLog(NID_APP, "Exit");
364
365         return r;
366 }
367
368 result
369 _AppControlImpl::StartImplicit(bundle* pBundle, const IList* pDataList, IAppControlEventListener* pListener)
370 {
371         SysLog(NID_APP, "Enter");
372         result r = E_SUCCESS;
373
374         _AppArg* pArg = new (std::nothrow) _AppArg;
375         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
376
377         pArg->Construct(pBundle);
378
379         _AppMessageImpl::AddData(pArg->GetBundle(), pDataList);
380
381         _AppControlManager* pImpl = _AppControlManager::GetInstance();
382         int req = _REQ_ID_INVALID;
383
384         if (pListener)
385         {
386                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCbLegacy, pListener, _APPCONTROL_PROPERTY_NONE);
387                 req = reqObj.GetRequestNumber();
388
389                 r = pImpl->LaunchAppImplicit(pArg, req);
390                 SysTryCatch(NID_APP, r == E_SUCCESS, reqObj.Invalidate(), r, "[%s] Propagating." , GetErrorMessage(r));
391         }
392         else
393         {
394                 r = pImpl->LaunchAppImplicit(pArg, -1);
395                 delete pArg;
396         }
397
398         // [FIXME] launch registration is not working correctly
399         SysLog(NID_APP, "Exit");
400
401 CATCH:
402         return r;
403 }
404
405 result
406 _AppControlImpl::StartImplicit(bundle* pBundle, const IMap* pData, IAppControlResponseListener* pListener)
407 {
408         SysLog(NID_APP, "Enter");
409         result r = E_SUCCESS;
410
411         _AppArg* pArg = new (std::nothrow) _AppArg;
412         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
413
414         pArg->Construct(pBundle);
415
416         _AppArg::AddStrMap(pArg->GetBundle(), pData);
417
418         _AppControlManager* pImpl = _AppControlManager::GetInstance();
419         int req = _REQ_ID_INVALID;
420
421         if (pListener)
422         {
423                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCb, pListener, _APPCONTROL_PROPERTY_NONE);
424                 req = reqObj.GetRequestNumber();
425
426                 if (_ThreadImpl::GetCurrentThreadImpl()->GetThreadType() == THREAD_TYPE_EVENT_DRIVEN)
427                 {
428                         _AppControlResponseEvent* pAppControlResponseEvent = new (std::nothrow) _AppControlResponseEvent();
429
430                         if (pAppControlResponseEvent != null)
431                         {
432                                 r = pAppControlResponseEvent->Construct();
433                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::Construct() is failed", GetErrorMessage(r));
434
435                                 r = pAppControlResponseEvent->AddListener(*pImpl, true);
436                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::AddListener() is failed", GetErrorMessage(r));
437
438                                 IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = pImpl->GetAppControlResponseEventContainer();
439                                 if (pResponseEventContainer != null)
440                                 {
441                                         pResponseEventContainer->Add(req, pAppControlResponseEvent);
442                                         SysLog(NID_APP, "pResponseEvent gets added. reqId(%d)", req);
443                                 }
444                         }
445                 }
446                 r = pImpl->LaunchAppImplicit(pArg, req);
447                 SysTryCatch(NID_APP, r == E_SUCCESS, reqObj.Invalidate(), r, "[%s] Propagating." , GetErrorMessage(r));
448         }
449         else
450         {
451                 r = pImpl->LaunchAppImplicit(pArg, -1);
452                 delete pArg;
453         }
454         SysLog(NID_APP, "Exit");
455
456         // [FIXME] launch registration is not working correctly
457
458 CATCH:
459
460         return r;
461 }
462
463 result
464 _AppControlImpl::AppControlCbLegacy(void* data, _AppArg* pArg, _AppArg* pResArg, service_result_e res, int prop, int reqId)
465 {
466         SysLog(NID_APP, "Result value %d", res);
467
468         SysTryReturnResult(NID_APP, data && pResArg && pArg, E_SYSTEM, "Invalid result (callback, result, arg) = (0x%x, 0x%x, 0x%x).",
469                                           data, pResArg,
470                                           pArg);
471
472         bundle* b = pResArg->GetBundle();
473         SysTryReturnResult(NID_APP, b != NULL, E_SYSTEM, "Invalid result bundle.");
474
475         IAppControlEventListener* pListener = static_cast<IAppControlEventListener*>(data);
476         SysTryReturnResult(NID_APP, pListener == null || typeid(pListener) == typeid(IAppControlEventListener*), E_SYSTEM, "Invalid result callback");
477
478         bundle* inb = pArg->GetBundle();
479         SysTryReturnResult(NID_APP, inb != NULL, E_SYSTEM, "Empty caller bundle.");
480
481         String oId;
482
483         AppId provider = pResArg->GetCalleeAppId();
484
485         const char* p = appsvc_get_operation(inb);
486         if (p)
487         {
488                 oId = p;
489         }
490
491         SysLog(NID_APP, "Invoking callback with (%ls, %ls)", provider.GetPointer(), oId.GetPointer());
492
493         if (prop & _APPCONTROL_PROPERTY_ALIAS)
494         {
495                 const _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
496                 pEntry = _AppControlRegistry::GetInstance()->GetReverseAppControlAliasEntry(provider, oId);
497                 if (pEntry)
498                 {
499                         provider = pEntry->provider;
500                         oId = pEntry->operation;
501
502                         SysLog(NID_APP, "Legacy AppControl(%ls, %ls).", provider.GetPointer(), oId.GetPointer());
503                 }
504         }
505
506         if (prop & _APPCONTROL_PROPERTY_APPID_CHANGE)
507         {
508                 String tmp = _AppControlRegistry::GetInstance()->GetReverseAliasAppId(provider);
509                 if (!tmp.IsEmpty())
510                 {
511                         SysLog(NID_APP, "App change (%ls -> %ls).", provider.GetPointer(), tmp.GetPointer());
512
513                         provider = tmp;
514                 }
515         }
516
517         const bool isSubMode = _AppArg::IsSubMode(b);
518         const bool isServiceCallee = _AppArg::IsServiceApp(b);
519
520         std::unique_ptr<HashMap> pMap(pResArg->GetArgMapN());
521
522         ArrayList list(SingleObjectDeleter);
523         _AppArg::FillLegacyAppControlResult(list, res, pMap.get(), provider);
524
525         _AppControlManager::InvokeLegacyAppControlCompleteListener(*pListener, provider, oId, &list, isSubMode | isServiceCallee);
526
527         return E_SUCCESS;
528 }
529
530 result
531 _AppControlImpl::AppControlCb(void* data, _AppArg* pArg, _AppArg* pResArg, service_result_e res, int prop, int reqId)
532 {
533         SysLog(NID_APP, "Result value : %d, property : 0x%x", res, prop);
534
535         SysTryReturnResult(NID_APP, data && pResArg && pArg, E_SYSTEM, "Invalid result (callback, result, arg) = (0x%x, 0x%x, 0x%x).",
536                                           data, pResArg,
537                                           pArg);
538
539         bundle* b = pResArg->GetBundle();
540         SysTryReturnResult(NID_APP, b != NULL, E_SYSTEM, "Invalid result bundle.");
541
542         IAppControlResponseListener* pListener = static_cast<IAppControlResponseListener*>(data);
543         SysTryReturnResult(NID_APP, pListener == null || typeid(pListener) == typeid(IAppControlResponseListener*), E_SYSTEM, "Invalid result callback");
544
545         bundle* inb = pArg->GetBundle();
546         SysTryReturnResult(NID_APP, inb != NULL, E_SYSTEM, "Empty caller bundle.");
547
548         String oId;
549
550         AppId provider = pResArg->GetCalleeAppId();
551
552         const char* p = appsvc_get_operation(inb);
553         if (p)
554         {
555                 oId = p;
556         }
557
558         SysLog(NID_APP, "Invoking callback with (%ls, %ls)", provider.GetPointer(), oId.GetPointer());
559
560         if (prop & _APPCONTROL_PROPERTY_ALIAS)
561         {
562                 const _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
563                 pEntry = _AppControlRegistry::GetInstance()->GetReverseRuntimeAliasEntry(provider, oId);
564                 if (pEntry)
565                 {
566                         provider = pEntry->provider;
567                         oId = pEntry->operation;
568
569                         SysLog(NID_APP, "Original AppControl(%ls, %ls).", provider.GetPointer(), oId.GetPointer());
570                 }
571         }
572
573         if (prop & _APPCONTROL_PROPERTY_APPID_CHANGE)
574         {
575                 String tmp = _AppControlRegistry::GetInstance()->GetReverseAliasAppId(provider);
576                 if (!tmp.IsEmpty())
577                 {
578                         SysLog(NID_APP, "App change (%ls -> %ls).", provider.GetPointer(), tmp.GetPointer());
579
580                         provider = tmp;
581                 }
582         }
583
584         const bool isSubMode = _AppArg::IsSubMode(b);
585         const bool isServiceCallee = _AppArg::IsServiceApp(b);
586
587         std::unique_ptr<HashMap> pMap(pResArg->GetArgMapN());
588
589         AppCtrlResult ret = _AppControlManager::ConvertAppControlResultCode(res);
590
591         SysLog(NID_APP, "Result code : 0x%x.", ret);
592
593         // proper callback invokation
594         _AppControlResponseEvent* pResponseEvent = null;
595         _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(reqId, pResponseEvent);
596
597         if (pResponseEvent != null)
598         {
599                 _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_COMPLETE, provider, oId, E_SUCCESS, ret, pMap.release(), reqId, isSubMode | isServiceCallee);
600                 pResponseEvent->Fire(*pResponseEventArg);
601                 SysLog(NID_APP, "OnAppControlCompleteResponseReceived, pResponseEvent is Fired");
602         }
603         else
604         {
605                 _AppControlManager::InvokeAppControlCompleteListener(*pListener, provider, oId, ret, pMap.get(), isSubMode | isServiceCallee);
606         }
607
608         return E_SUCCESS;
609 }
610
611 result
612 _AppControlImpl::StartNative(const IList* pDataList, IAppControlEventListener* pListener)
613 {
614         SysLog(NID_APP, "Enter");
615         _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
616         SysTryReturnResult(NID_APP, pInfo == null, E_IN_PROGRESS, "Request ID %d is already in progress.", _reqId);
617
618         int req = _REQ_ID_INVALID;
619         _LibraryImpl* pLib = null;
620
621         pLib = new (std::nothrow) _LibraryImpl;
622         SysTryReturnResult(NID_APP, pLib != null, E_OUT_OF_MEMORY, "Failed to allocate libraryimpl.");
623
624         result r = pLib->Construct(_path, _LIBRARY_OPTION);
625         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
626
627         if (pListener)
628         {
629                 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(_provider, _opId, _property, true, *pLib, pListener);
630                 if (pItem)
631                 {
632                         req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
633                 }
634         }
635         r = InvokeStartAppControl(*pLib, req, _provider, _opId, pDataList);
636
637         if (pListener == null)
638         {
639                 delete pLib;
640         }
641
642         // after acquring request number, pLib should be managed from the list, not CATCH
643         if (IsFailed(r))
644         {
645                 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
646                 SysLog(NID_APP, "[%s] A system error has occurred.", GetErrorMessage(r));
647
648                 return r;
649         }
650
651         _reqId = req;
652
653         SysLog(NID_APP, "Exit %d", req);
654         return E_SUCCESS;
655
656 CATCH:
657         delete pLib;
658
659         switch (r)
660         {
661         case E_LIBRARY_NOT_FOUND:
662                 r = E_OBJ_NOT_FOUND;
663                 break;
664         default:
665                 r = E_SYSTEM;
666                 break;
667         }
668
669         return r;
670 }
671
672 result
673 _AppControlImpl::StartNative(const String* pUriData, const String* pMimeType, const IMap* pDataList, IAppControlResponseListener* pListener)
674 {
675         SysLog(NID_APP, "Enter");
676         _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
677         SysTryReturnResult(NID_APP, pInfo == null, E_IN_PROGRESS, "Request ID %d is already in progress.", _reqId);
678
679         int req = _REQ_ID_INVALID;
680         _LibraryImpl* pLib = null;
681
682         pLib = new (std::nothrow) _LibraryImpl;
683         SysTryReturnResult(NID_APP, pLib != null, E_OUT_OF_MEMORY, "Failed to allocate libraryimpl.");
684
685         result r = pLib->Construct(_path, _LIBRARY_OPTION);
686
687         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
688
689         if (pListener)
690         {
691                 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(_provider, _opId, _property, false, *pLib, pListener);
692                 if (pItem)
693                 {
694                         req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
695                 }
696
697                 if (_ThreadImpl::GetCurrentThreadImpl()->GetThreadType() == THREAD_TYPE_EVENT_DRIVEN)
698                 {
699                         _AppControlResponseEvent* pAppControlResponseEvent = new (std::nothrow) _AppControlResponseEvent();
700
701                         if (pAppControlResponseEvent != null)
702                         {
703                                 r = pAppControlResponseEvent->Construct();
704                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::Construct() is failed", GetErrorMessage(r));
705
706                                 r = pAppControlResponseEvent->AddListener(*this, true);
707                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::AddListener() is failed", GetErrorMessage(r));
708
709                                 IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = _AppControlManager::GetInstance()->GetAppControlResponseEventContainer();
710                                 if (pResponseEventContainer != null)
711                                 {
712                                         int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + req;
713                                         pResponseEventContainer->Add(responseEventRequestId, pAppControlResponseEvent);
714                                         __appControlResponseEventList.Add(responseEventRequestId);
715                                         SysLog(NID_APP, "pResponseEvent gets added. reqId(%d)", responseEventRequestId);
716                                 }
717                         }
718                 }
719         }
720         r = InvokeStartAppControl(*pLib, req, _provider, _opId, pUriData, pMimeType, pDataList);
721
722         if (pListener == null)
723         {
724                 delete pLib;
725         }
726
727         // after acquring request number, pLib should be managed from the list, not CATCH
728         if (IsFailed(r))
729         {
730                 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
731                 SysLog(NID_APP, "[%s] A system error has occurred.", GetErrorMessage(r));
732
733                 return r;
734         }
735
736         _reqId = req;
737         SysLog(NID_APP, "Exit %d", req);
738
739         return E_SUCCESS;
740
741 CATCH:
742         delete pLib;
743
744         switch (r)
745         {
746         case E_LIBRARY_NOT_FOUND:
747                 r = E_OBJ_NOT_FOUND;
748                 break;
749         default:
750                 r = E_SYSTEM;
751                 break;
752         }
753
754         return r;
755 }
756
757 result
758 _AppControlImpl::InvokeStartAppControl(_LibraryImpl& lib, int req, const String& appId, const String& oId, const IList* pList)
759 {
760         SysLog(NID_APP, "Legacy stuff for converting argument");
761
762         HashMap map(SingleObjectDeleter);
763         HashMap* pMap = null;
764         if (pList)
765         {
766                 map.Construct();
767
768                 _AppArg::FillMapFromList(&map, pList);
769
770                 pMap = &map;
771         }
772
773         return InvokeStartAppControl(lib, req, appId, oId, null, null, pMap);
774 }
775
776
777 result
778 _AppControlImpl::InvokeStartAppControl(_LibraryImpl& lib, int req, const String& appId, const String& oId, const String* pUri, const String* pMime, const IMap* pMap)
779 {
780         result (*pFunc)(int req, const String&, const String&, const String*, const String*, const IMap*) = null;
781
782         pFunc =
783                 reinterpret_cast<result (*)(int, const String&, const String&, const String*, const String*, const IMap*)>(lib.GetProcAddress(L"StartAppControl"));
784         SysTryReturnResult(NID_APP, pFunc != null, E_OBJ_NOT_FOUND, "Entry \"StartAppControl\" not found for %ls", appId.GetPointer());
785
786         const String* pActualUri = (pUri && !(pUri->IsEmpty())) ? pUri : null;
787         const String* pActualMime = (pMime && !(pMime->IsEmpty())) ? pMime : null;
788         return (*pFunc)(req, appId, oId, pActualUri, pActualMime, pMap);
789 }
790
791 static bool
792 IsValidAppControl(const String& appcontrolID)
793 {
794         return ((appcontrolID == L"osp.appcontrol.provider.audio")
795                 || (appcontrolID == L"osp.appcontrol.provider.bluetooth")
796                 || (appcontrolID == L"osp.appcontrol.provider.calendar")
797                 || (appcontrolID == L"osp.appcontrol.provider.camera")
798                 || (appcontrolID == L"osp.appcontrol.provider.contact")
799                 || (appcontrolID == L"osp.appcontrol.provider.certificatemanager")
800                 || (appcontrolID == L"osp.appcontrol.provider.email")
801                 || (appcontrolID == L"osp.appcontrol.provider.image")
802                 || (appcontrolID == L"osp.appcontrol.provider.media")
803                 || (appcontrolID == L"osp.appcontrol.provider.message")
804                 || (appcontrolID == L"osp.appcontrol.provider.video")
805                 || (appcontrolID == L"osp.appcontrol.provider.imageeditor")
806                 || (appcontrolID == L"osp.appcontrol.provider.allshare")
807                 || (appcontrolID == L"tizen.filemanager")
808                 || (appcontrolID == L"tizen.camera")
809                 || (appcontrolID == L"tizen.gallery")
810                 || (appcontrolID == L"tizen.imageviewer")
811                 || (appcontrolID == L"tizen.videoplayer")
812                 || (appcontrolID == L"tizen.memo")
813                 || (appcontrolID == L"tizen.contacts")
814                 || (appcontrolID == L"tizen.calendar")
815                 || (appcontrolID == L"tizen.todo")
816                 || (appcontrolID == L"tizen.email")
817                 || (appcontrolID == L"tizen.settings")
818                 || (appcontrolID == L"tizen.messages")
819                 || (appcontrolID == L"tizen.musicplayer")
820                 || (appcontrolID == L"tizen.bluetooth")
821                 || (appcontrolID == L"samsung.snote")
822                 || (appcontrolID == L"0pnxz8hbsr.MyFiles")
823                 || (appcontrolID == L"hdufar9ycj.Camera")
824                 || (appcontrolID == L"ijudt7w61q.Gallery")
825                 || (appcontrolID == L"jysyv9o1dc.ImageViewer")
826                 || (appcontrolID == L"npwf0scb88.VideoPlayer")
827                 || (appcontrolID == L"zunqjlsnce.Memo")
828                 || (appcontrolID == L"f9uev8hsyo.Contacts")
829                 || (appcontrolID == L"ph1vq2phrp.Calendar")
830                 || (appcontrolID == L"vxqbrefica.Email")
831                 || (appcontrolID == L"kto5jikgul.Settings")
832                 || (appcontrolID == L"8r4r5ddzzn.Messages")
833                 || (appcontrolID == L"dhrul6qzj3.MusicPlayer")
834                 || (appcontrolID == L"smemo-efl"));
835 }
836
837 result
838 _AppControlImpl::Stop(void)
839 {
840         const String appcontrolID(GetAppControlProviderId());
841         SysTryReturnResult(NID_APP, IsValidAppControl(appcontrolID), E_INVALID_OPERATION, "Invalid appcontrolID(%ls)", appcontrolID.GetPointer());
842
843         if (_property & _APPCONTROL_PROPERTY_SLP)
844         {
845                 result (*pStop)(int req) = null;
846
847                 if (_reqId != _REQ_ID_INVALID)
848                 {
849                         _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
850                         SysTryReturnResult(NID_APP, pInfo != null, E_INVALID_OPERATION, "Request ID %d is not found.", _reqId);
851
852                         pStop = reinterpret_cast<result (*)(int)>(pInfo->pLib->GetProcAddress(L"TerminateAppControl"));
853                         SysTryReturnResult(NID_APP, pStop != null, E_SYSTEM, "No TerminateAppControl() function.");
854
855                         (*pStop)(_reqId);
856
857                         _AppControlManager::GetInstance()->__inAppManager.RemoveItem(_reqId);
858
859                         _reqId = _REQ_ID_INVALID;
860                 }
861                 else
862                 {
863                         _LibraryImpl lib;
864                         result r = lib.Construct(_path, _LIBRARY_OPTION);
865                         if (r == E_SUCCESS)
866                         {
867                                 pStop = reinterpret_cast<result (*)(int)>(lib.GetProcAddress(L"TerminateAppControl"));
868                                 SysTryReturnResult(NID_APP, pStop != null, E_SYSTEM, "No TerminateAppControl() function.");
869
870                                 (*pStop)(_reqId);
871                         }
872                 }
873         }
874         else if (_property & _APPCONTROL_PROPERTY_OSP)
875         {
876                 _Aul::TerminateApplicationByPid(_processId);
877         }
878
879         return E_SUCCESS;
880 }
881
882 String
883 _AppControlImpl::GetAppName(void)
884 {
885         if (_appName.IsEmpty())
886         {
887                 AppId appId = GetAppId();
888                 AppId aliasAppId = _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
889                 if (!aliasAppId.IsEmpty())
890                 {
891                         appId = aliasAppId;
892                 }
893
894                 std::unique_ptr<PackageAppInfo> pInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
895                 if (pInfo.get())
896                 {
897                         SysLog(NID_APP, "PackageInfo of appId(%ls) exists", appId.GetPointer());
898                         const String& name = pInfo->GetAppName();
899                         if (name == L"_AppControl")
900                         {
901                                 // workaround for special case: requery with actual appId
902                                 const PackageId& packageId = _PackageManagerImpl::GetPackageIdByAppId(appId);
903                                 const String& defaultName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
904
905                                 const String& convertedAppId = packageId + L'.' + defaultName;
906
907                                 std::unique_ptr<PackageAppInfo> pNewInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(convertedAppId));
908
909                                 if (pNewInfo.get())
910                                 {
911                                         _appName = pNewInfo->GetAppDisplayName();
912                                 }
913                                 else
914                                 {
915                                         SysLog(NID_APP, "No default applicaiton information, possible database error.");
916                                 }
917                         }
918                         else
919                         {
920                                 _appName = pInfo->GetAppDisplayName();
921                         }
922                 }
923                 else
924                 {
925                         SysLog(NID_APP, "PackageInfo of appId(%ls) does not exist", appId.GetPointer());
926                 }
927         }
928
929         return _appName;
930 }
931
932 String
933 _AppControlImpl::GetAppId(void) const
934 {
935         return (_property & _APPCONTROL_PROPERTY_OSP) ? _path : _provider;
936 }
937
938 const String&
939 _AppControlImpl::GetAppControlProviderId(void) const
940 {
941         return _provider;
942 }
943
944 const String&
945 _AppControlImpl::GetOperationId(void) const
946 {
947         return _opId;
948 }
949
950 IList*
951 _AppControlImpl::GetCategoryListN(void) const
952 {
953         AppId appId = GetAppId();
954         SysTryReturn(NID_APP, !appId.IsEmpty(), null, E_SYSTEM, "[E_SYSTEM] Empty appId.");
955
956         AppId aliasAppId = _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
957         if (!aliasAppId.IsEmpty())
958         {
959                 appId = aliasAppId;
960         }
961
962         SysLog(NID_APP, "Acquiring category for app %ls.", appId.GetPointer());
963
964         std::unique_ptr<PackageAppInfo> pAppInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
965         SysTryReturn(NID_APP, pAppInfo.get() != null, null, E_SYSTEM, "[E_SYSTEM] Getting PackageAppInfo failed.");
966
967         return pAppInfo->GetAppCategoryListN();
968 }
969
970 void
971 _AppControlImpl::StopAppControlResponseListener(IAppControlResponseListener* pListener)
972 {
973         _AppControlManager::GetInstance()->__listenerList.Add(pListener);
974 }
975
976 void
977 _AppControlImpl::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
978 {
979         const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
980
981         if (pEventArg != null)
982         {
983                 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
984
985                 if(pResponseListener != null)
986                 {
987                         if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_COMPLETE)
988                         {
989                                 _AppControlManager::InvokeAppControlCompleteListener(*pResponseListener, pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData(), pEventArg->IsSubMode());
990
991                                 _AppControlResponseEvent* pResponseEvent = null;
992                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
993                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
994                                 delete pResponseEvent;
995                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
996                         }
997                         else
998                         {
999                                 SysLog(NID_APP, "Unexpected AppControlResponseType(%d)", pEventArg->GetType());
1000                         }
1001                 }
1002                 else
1003                 {
1004                         SysLog(NID_APP, "Invalid ResponseListener");
1005                 }
1006         }
1007         else
1008         {
1009                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
1010         }
1011
1012 }
1013 }}    //Tizen::App