dfeb08276e5d64392f7ee5cc3fc1dc8984ec139a
[platform/framework/native/appfw.git] / src / app / FApp_AppControlImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file                FApp_AppControlImpl.cpp
20  * @brief               This is the implementation for the Application Control class.
21  */
22
23 #include <new>
24 #include <typeinfo>
25 #include <unique_ptr.h>
26
27 #include <appsvc/appsvc.h>
28
29 #include <FAppAppControl.h>
30 #include <FAppAppManager.h>
31 #include <FAppPkgPackageAppInfo.h>
32 #include <FAppIAppControlEventListener.h>
33 #include <FAppIAppControlResponseListener.h>
34 #include <FBaseColHashMap.h>
35 #include <FBaseSysLog.h>
36
37 #include <FBaseRt_LibraryImpl.h>
38 #include <FIo_DirectoryImpl.h>
39
40 #include "FApp_AppControlImpl.h"
41 #include "FApp_AppControlManager.h"
42 #include "FApp_AppArg.h"
43 #include "FApp_AppImpl.h"
44 #include "FApp_AppControlRegistry.h"
45 #include "FApp_AppMessageImpl.h"
46 #include "FApp_AppInfo.h"
47 #include "FAppPkg_PackageManagerImpl.h"
48 #include "FApp_Aul.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 const char TIZEN_APPCONTROL_DATA_LEGACY[] = "http://tizen.org/appcontrol/data/legacyresult";
69
70 _AppControlImpl::_AppControlImpl(const AppControl& value)
71         : _appControl(value)
72         , _reqId(_REQ_ID_INVALID)
73         , _property(_APPCONTROL_PROPERTY_NONE)
74         , _processId(_REQ_ID_INVALID)
75 {
76 }
77
78 _AppControlImpl::~_AppControlImpl(void)
79 {
80 }
81
82 AppControl*
83 _AppControlImpl::CreateN(const String& path, const String& aId, const String& oId, const String& name, int prop)
84 {
85         SysTryReturn(NID_APP, !path.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Path is empty.");
86         SysTryReturn(NID_APP, !aId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Provider Id is empty.");
87         SysTryReturn(NID_APP, !oId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Operation Id is empty.");
88
89         AppControl* pAc = new (std::nothrow) AppControl;
90         SysTryReturn(NID_APP, pAc != null, null, E_OUT_OF_MEMORY, "AppControl allocation failure.");
91
92         _AppControlImpl* pImpl = pAc->__pAppControlImpl;
93         SysTryReturn(NID_APP, pImpl != null, null, E_OUT_OF_MEMORY, "AppControlImpl instance must not be null.");
94
95         pImpl->_path = path;
96         pImpl->_provider = aId;
97         pImpl->_opId = oId;
98         // [FIXME] Proper App name setting
99         pImpl->_appName = name;
100         pImpl->_property = prop;
101
102         return pAc;
103 }
104
105 AppControl*
106 _AppControlImpl::CreateN(const AppId& appId, const String& operationId, bool changeAppId)
107 {
108         SysTryReturn(NID_APP, !appId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] appId is empty.");
109
110         AppControl* pAc = new (std::nothrow) AppControl;
111         SysTryReturn(NID_APP, pAc != null, null, E_OUT_OF_MEMORY, "AppControl allocation failure.");
112
113         _AppControlImpl* pImpl = pAc->__pAppControlImpl;
114         SysTryReturn(NID_APP, pImpl != null, null, E_OUT_OF_MEMORY, "AppControlImpl instance must not be null.");
115
116         pImpl->_path = appId;
117         pImpl->_provider = appId;
118         pImpl->_opId = operationId;
119         //pImpl->_appName = appId;
120         pImpl->_property |= (_APPCONTROL_PROPERTY_OSP | _APPCONTROL_PROPERTY_PUBLIC);
121
122         if (changeAppId)
123         {
124                 pImpl->_property |= _APPCONTROL_PROPERTY_APPID_CHANGE;
125         }
126
127         return pAc;
128 }
129
130 AppControl*
131 _AppControlImpl::CreateN(const AppControl& ac)
132 {
133         const _AppControlImpl* pImpl = GetInstance(ac);
134         SysTryReturn(NID_APP, pImpl != null, null, E_INVALID_STATE, "AppControlImpl instance must not be null.");
135
136         return CreateN(pImpl->_path, pImpl->_provider, pImpl->_opId, pImpl->_appName, pImpl->_property);
137 }
138
139 const _AppControlImpl*
140 _AppControlImpl::GetInstance(const AppControl& ac)
141 {
142         return ac.__pAppControlImpl;
143 }
144
145 _AppControlImpl*
146 _AppControlImpl::GetInstance(AppControl& ac)
147 {
148         return ac.__pAppControlImpl;
149 }
150
151 result
152 _AppControlImpl::Start(const IList* pDataList, IAppControlEventListener* pListener)
153 {
154         result r = E_SYSTEM;
155
156         if (_property & _APPCONTROL_PROPERTY_SLP)
157         {
158                 r = StartNative(pDataList, pListener);
159         }
160         else if (_property & _APPCONTROL_PROPERTY_OSP)
161         {
162                 r = StartOsp(pDataList, pListener);
163         }
164         else
165         {
166                 SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] Invalid AppControl type(property %d)", _property);
167         }
168
169         return r;
170 }
171
172 result
173 _AppControlImpl::Start(const String* pUriData, const String* pDataType, const IMap* pExtraData, IAppControlResponseListener* pListener)
174 {
175         result r = E_SYSTEM;
176
177         if (_property & _APPCONTROL_PROPERTY_SLP)
178         {
179                 r = StartNative(pUriData, pDataType, pExtraData, pListener);
180         }
181         else if (_property & _APPCONTROL_PROPERTY_OSP)
182         {
183                 r = StartOsp(pUriData, pDataType, pExtraData, pListener);
184         }
185         else
186         {
187                 SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] Invalid AppControl type(property %d)", _property);
188         }
189
190         return r;
191 }
192
193 result
194 _AppControlImpl::FindAndStart(const String& operationId, const String* pUriPattern, const String* pDataType, const String* pCategory, const IMap* pExtraData, IAppControlResponseListener* pListener)
195 {
196         // [FIXME] valid argument size checking required
197
198         std::unique_ptr<bundle, BundleDeleter> pBundle(bundle_create());
199         SysTryReturnResult(NID_APP, pBundle.get(), E_OUT_OF_MEMORY, "Bundle creation failure.");
200
201         _AppMessageImpl::SetOperation(pBundle.get(), operationId);
202
203         if (pUriPattern)
204         {
205                 _AppMessageImpl::SetUri(pBundle.get(), *pUriPattern);
206         }
207
208         if (pDataType)
209         {
210                 String mimeType = *pDataType;
211
212                 if ((*pDataType)[0] == L'.')
213                 {
214                         SysLog(NID_APP, "Extension to MIME conversion for %ls", pDataType->GetPointer());
215
216 #if 0
217                         String ext;
218                         pDataType->SubString(1, ext);
219
220                         result r = _AppControlManager::GetMimeFromExt(ext, mimeType);
221
222                         SysTryReturn(NID_APP, !IsFailed(r), null, r, "[%s] MIME type conversion failure for %ls.", GetErrorMessage(r), ext.GetPointer());
223
224                         pMimeType = &mimeType;
225
226                         SysLog(NID_APP, "Conversion : %ls -> %ls.", pDataType->GetPointer(), pMimeType->GetPointer());
227 #endif
228                 }
229
230                 _AppMessageImpl::SetMime(pBundle.get(), mimeType);
231         }
232
233         if (pCategory)
234         {
235                 _AppMessageImpl::SetCategory(pBundle.get(), *pCategory);
236         }
237
238         return StartImplicit(pBundle.get(), pExtraData, pListener);
239 }
240
241 result
242 _AppControlImpl::StartOsp(const IList* pDataList, IAppControlEventListener* pListener)
243 {
244         result r = E_SUCCESS;
245
246         _AppArg* pArg = new (std::nothrow) _AppArg;
247         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
248
249         pArg->Construct(*this, pDataList);
250
251         _AppControlManager* pImpl = _AppControlManager::GetInstance();
252         int req = _REQ_ID_INVALID;
253
254         if (pListener)
255         {
256                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCbLegacy, pListener, _property);
257                 req = reqObj.GetRequestNumber();
258
259                 _processId = pImpl->Launch(_path, pArg, req);
260
261                 if (_processId < 0)
262                 {
263                         reqObj.Invalidate();
264                         r = GetLastResult();
265                         SysLog(NID_APP, "[%s]Launching(%ls) is failed" , GetErrorMessage(r), _path.GetPointer());
266                         return r;
267                 }
268         }
269         else
270         {
271                 _processId = pImpl->Launch(_path, pArg);
272                 delete pArg;
273                 SysTryReturnResult(NID_APP, _processId >= 0, GetLastResult(), "Launching(%ls) is failed", _path.GetPointer());
274         }
275
276         return r;
277 }
278
279 result
280 _AppControlImpl::StartOsp(const String* pUriData, const String* pMimeType, const IMap* pDataList, IAppControlResponseListener* pListener)
281 {
282         result r = E_SUCCESS;
283
284         _AppArg* pArg = new (std::nothrow) _AppArg;
285         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
286
287         pArg->Construct(*this, pUriData, pMimeType, pDataList);
288
289         _AppControlManager* pImpl = _AppControlManager::GetInstance();
290         int req = _REQ_ID_INVALID;
291
292         if (pListener)
293         {
294                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCb, pListener, _property);
295                 req = reqObj.GetRequestNumber();
296
297                 _processId = pImpl->Launch(_path, pArg, req);           
298                 if (_processId < 0)
299                 {
300                         reqObj.Invalidate();
301                         r = GetLastResult();
302                         SysLog(NID_APP, "[%s]Launching(%ls) is failed" , GetErrorMessage(r), _path.GetPointer());
303                         return r;
304                 }
305         }
306         else
307         {
308                 _processId = pImpl->Launch(_path, pArg);
309                 delete pArg;
310                 SysTryReturnResult(NID_APP, _processId >= 0, GetLastResult(), "Launching(%ls) is failed", _path.GetPointer());
311         }
312
313         return r;
314 }
315
316 result
317 _AppControlImpl::StartImplicit(bundle* pBundle, const IList* pDataList, IAppControlEventListener* pListener)
318 {
319         result r = E_SUCCESS;
320
321         _AppArg* pArg = new (std::nothrow) _AppArg;
322         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
323
324         pArg->Construct(pBundle);
325
326         _AppMessageImpl::AddData(pArg->GetBundle(), pDataList);
327
328         _AppControlManager* pImpl = _AppControlManager::GetInstance();
329         int req = _REQ_ID_INVALID;
330
331         if (pListener)
332         {
333                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCbLegacy, pListener, _APPCONTROL_PROPERTY_NONE);
334                 req = reqObj.GetRequestNumber();
335
336                 r = pImpl->LaunchAppImplicit(pArg, req);
337                 SysTryCatch(NID_APP, r == E_SUCCESS, reqObj.Invalidate(), r, "[%s] Propagating." , GetErrorMessage(r));
338         }
339         else
340         {
341                 r = pImpl->LaunchAppImplicit(pArg, -1);
342                 delete pArg;
343         }
344
345         // [FIXME] launch registration is not working correctly
346
347 CATCH:
348         return r;
349 }
350
351 result
352 _AppControlImpl::StartImplicit(bundle* pBundle, const IMap* pData, IAppControlResponseListener* pListener)
353 {
354         result r = E_SUCCESS;
355
356         _AppArg* pArg = new (std::nothrow) _AppArg;
357         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
358
359         pArg->Construct(pBundle);
360
361         _AppArg::AddStrMap(pArg->GetBundle(), pData);
362
363         _AppControlManager* pImpl = _AppControlManager::GetInstance();
364         int req = _REQ_ID_INVALID;
365
366         if (pListener)
367         {
368                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCb, pListener, _APPCONTROL_PROPERTY_NONE);
369                 req = reqObj.GetRequestNumber();
370
371                 r = pImpl->LaunchAppImplicit(pArg, req);
372                 SysTryCatch(NID_APP, r == E_SUCCESS, reqObj.Invalidate(), r, "[%s] Propagating." , GetErrorMessage(r));
373         }
374         else
375         {
376                 r = pImpl->LaunchAppImplicit(pArg, -1);
377                 delete pArg;
378         }
379
380         // [FIXME] launch registration is not working correctly
381
382 CATCH:
383
384         return r;
385 }
386
387 result
388 _AppControlImpl::AppControlCbLegacy(void* data, _AppArg* pArg, _AppArg* pResArg, service_result_e res, int prop)
389 {
390         SysLog(NID_APP, "Result value %d", res);
391
392         SysTryReturnResult(NID_APP, data && pResArg && pArg, E_SYSTEM, "Invalid result (callback, result, arg) = (0x%x, 0x%x, 0x%x).",
393                                           data, pResArg,
394                                           pArg);
395
396         bundle* b = pResArg->GetBundle();
397         SysTryReturnResult(NID_APP, b != NULL, E_SYSTEM, "Invalid result bundle.");
398
399         IAppControlEventListener* pListener = static_cast<IAppControlEventListener*>(data);
400         SysTryReturnResult(NID_APP, typeid(pListener) == typeid(IAppControlEventListener*), E_SYSTEM, "Invalid result callback");
401
402         bundle* inb = pArg->GetBundle();
403         SysTryReturnResult(NID_APP, inb != NULL, E_SYSTEM, "Empty caller bundle.");
404
405         String oId;
406
407         AppId provider = pResArg->GetCalleeAppId();
408
409         const char* p = appsvc_get_operation(inb);
410         if (p)
411         {
412                 oId = p;
413         }
414
415         SysLog(NID_APP, "Invoking callback with (%ls, %ls)", provider.GetPointer(), oId.GetPointer());
416
417         if (prop & _APPCONTROL_PROPERTY_ALIAS)
418         {
419                 _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
420                 pEntry = _AppControlRegistry::GetInstance()->GetReverseAppControlAliasEntry(provider, oId);
421                 if (pEntry)
422                 {
423                         provider = pEntry->provider;
424                         oId = pEntry->operation;
425
426                         SysLog(NID_APP, "Legacy AppControl name (%ls, %ls).", provider.GetPointer(), oId.GetPointer());
427                 }
428         }
429
430         if (prop & _APPCONTROL_PROPERTY_APPID_CHANGE)
431         {
432                 String tmp = _AppControlRegistry::GetInstance()->GetReverseAliasAppId(provider);
433                 if (!tmp.IsEmpty())
434                 {
435                         SysLog(NID_APP, "AppId change (%ls -> %ls).", provider.GetPointer(), tmp.GetPointer());
436
437                         provider = tmp;
438                 }
439         }
440
441         std::unique_ptr<HashMap> pMap(pResArg->GetArgMapN());
442
443         ArrayList list(SingleObjectDeleter);
444         _AppArg::FillLegacyAppControlResult(list, res, pMap.get(), provider);
445
446         // proper callback invokation
447         pListener->OnAppControlCompleted(provider, oId, &list);
448
449         return E_SUCCESS;
450 }
451
452 result
453 _AppControlImpl::AppControlCb(void* data, _AppArg* pArg, _AppArg* pResArg, service_result_e res, int prop)
454 {
455         SysLog(NID_APP, "Result value %d", res);
456
457         SysTryReturnResult(NID_APP, data && pResArg && pArg, E_SYSTEM, "Invalid result (callback, result, arg) = (0x%x, 0x%x, 0x%x).",
458                                           data, pResArg,
459                                           pArg);
460
461         bundle* b = pResArg->GetBundle();
462         SysTryReturnResult(NID_APP, b != NULL, E_SYSTEM, "Invalid result bundle.");
463
464         IAppControlResponseListener* pListener = static_cast<IAppControlResponseListener*>(data);
465         SysTryReturnResult(NID_APP, typeid(pListener) == typeid(IAppControlResponseListener*), E_SYSTEM, "Invalid result callback");
466
467         bundle* inb = pArg->GetBundle();
468         SysTryReturnResult(NID_APP, inb != NULL, E_SYSTEM, "Empty caller bundle.");
469
470         String oId;
471
472         AppId provider = pResArg->GetCalleeAppId();
473
474         const char* p = appsvc_get_operation(inb);
475         if (p)
476         {
477                 oId = p;
478         }
479
480         SysLog(NID_APP, "Invoking callback with (%ls, %ls)", provider.GetPointer(), oId.GetPointer());
481
482         if (prop & _APPCONTROL_PROPERTY_ALIAS)
483         {
484                 _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
485                 pEntry = _AppControlRegistry::GetInstance()->GetReverseAppControlAliasEntry(provider, oId);
486                 if (pEntry)
487                 {
488                         provider = pEntry->provider;
489                         oId = pEntry->operation;
490
491                         SysLog(NID_APP, "Legacy AppControl name (%ls, %ls).", provider.GetPointer(), oId.GetPointer());
492                 }
493         }
494
495         if (prop & _APPCONTROL_PROPERTY_APPID_CHANGE)
496         {
497                 String tmp = _AppControlRegistry::GetInstance()->GetReverseAliasAppId(provider);
498                 if (!tmp.IsEmpty())
499                 {
500                         SysLog(NID_APP, "AppId change (%ls -> %ls).", provider.GetPointer(), tmp.GetPointer());
501
502                         provider = tmp;
503                 }
504         }
505
506         std::unique_ptr<HashMap> pMap(pResArg->GetArgMapN());
507
508         AppCtrlResult ret = APP_CTRL_RESULT_FAILED;
509         // to prevent enum overflow;
510         int resCode = res;
511         switch(resCode)
512         {
513         case SERVICE_RESULT_SUCCEEDED:
514                 ret = APP_CTRL_RESULT_SUCCEEDED;
515                 break;
516         case SERVICE_RESULT_FAILED:
517                 ret = APP_CTRL_RESULT_CANCELED;
518                 break;
519         case SERVICE_RESULT_CANCELED:
520                 ret = APP_CTRL_RESULT_ABORTED;
521                 break;
522         case APPSVC_OSP_RES_FAIL:
523                 ret = APP_CTRL_RESULT_FAILED;
524                 break;
525         case APPSVC_OSP_RES_TERMINATE:
526                 ret = APP_CTRL_RESULT_TERMINATED;
527                 break;
528         default:
529                 ret = APP_CTRL_RESULT_FAILED;
530                 break;
531         }
532
533         SysLog(NID_APP, "Result code : 0x%x.", ret);
534
535         // proper callback invokation
536         pListener->OnAppControlCompleteResponseReceived(provider, oId, ret, pMap.get());
537
538         return E_SUCCESS;
539 }
540
541 result
542 _AppControlImpl::StartNative(const IList* pDataList, IAppControlEventListener* pListener)
543 {
544         _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
545         SysTryReturnResult(NID_APP, pInfo == null, E_IN_PROGRESS, "Request ID %d is already in progress.", _reqId);
546
547         int req = _REQ_ID_INVALID;
548         _LibraryImpl* pLib = null;
549
550         pLib = new (std::nothrow) _LibraryImpl;
551         SysTryReturnResult(NID_APP, pLib != null, E_OUT_OF_MEMORY, "Failed to allocate libraryimpl.");
552
553         unsigned long option = _LIBRARY_LOAD_OPTION_LAZY;
554         option |= _LIBRARY_LOAD_OPTION_NODELETE;
555
556         result r = pLib->Construct(_path, option);
557         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
558
559         if (pListener)
560         {
561                 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(_provider, _opId, _property, true, *pLib, pListener);
562                 if (pItem)
563                 {
564                         req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
565                 }
566         }
567         r = InvokeStartAppControl(*pLib, req, _provider, _opId, pDataList);
568
569         if (pListener == null)
570         {
571                 delete pLib;
572         }
573
574         // after acquring request number, pLib should be managed from the list, not CATCH
575         if (IsFailed(r))
576         {
577                 SetLastResult(E_SYSTEM);
578                 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
579                 SysLog(NID_APP, "[E_SYSTEM] A system error has occurred with %s.", GetErrorMessage(r));
580
581                 return E_SYSTEM;
582         }
583
584         _reqId = req;
585
586         return E_SUCCESS;
587
588 CATCH:
589         delete pLib;
590
591         switch (r)
592         {
593         case E_LIBRARY_NOT_FOUND:
594                 r = E_OBJ_NOT_FOUND;
595                 break;
596         default:
597                 r = E_SYSTEM;
598                 break;
599         }
600
601         return r;
602 }
603
604 result
605 _AppControlImpl::StartNative(const String* pUriData, const String* pMimeType, const IMap* pDataList, IAppControlResponseListener* pListener)
606 {
607         _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
608         SysTryReturnResult(NID_APP, pInfo == null, E_IN_PROGRESS, "Request ID %d is already in progress.", _reqId);
609
610         int req = _REQ_ID_INVALID;
611         _LibraryImpl* pLib = null;
612
613         pLib = new (std::nothrow) _LibraryImpl;
614         SysTryReturnResult(NID_APP, pLib != null, E_OUT_OF_MEMORY, "Failed to allocate libraryimpl.");
615
616         unsigned long option = _LIBRARY_LOAD_OPTION_LAZY;
617         option |= _LIBRARY_LOAD_OPTION_NODELETE;
618
619         result r = pLib->Construct(_path, option);
620
621         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
622
623         if (pListener)
624         {
625                 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(_provider, _opId, _property, false, *pLib, pListener);
626                 if (pItem)
627                 {
628                         req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
629                 }
630         }
631         r = InvokeStartAppControl(*pLib, req, _provider, _opId, null, null, pDataList);
632
633         if (pListener == null)
634         {
635                 delete pLib;
636         }
637
638         // after acquring request number, pLib should be managed from the list, not CATCH
639         if (IsFailed(r))
640         {
641                 SetLastResult(E_SYSTEM);
642                 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
643                 SysLog(NID_APP, "[E_SYSTEM] A system error has occurred with %s.", GetErrorMessage(r));
644
645                 return E_SYSTEM;
646         }
647
648         _reqId = req;
649
650         return E_SUCCESS;
651
652 CATCH:
653         delete pLib;
654
655         switch (r)
656         {
657         case E_LIBRARY_NOT_FOUND:
658                 r = E_OBJ_NOT_FOUND;
659                 break;
660         default:
661                 r = E_SYSTEM;
662                 break;
663         }
664
665         return r;
666 }
667
668 result
669 _AppControlImpl::InvokeStartAppControl(_LibraryImpl& lib, int req, const String& appId, const String& oId, const IList* pList)
670 {
671         SysLog(NID_APP, "Legacy stuff for converting argument");
672
673         HashMap map(SingleObjectDeleter);
674         HashMap* pMap = null;
675         if (pList)
676         {
677                 map.Construct();
678
679                 _AppArg::FillMapFromList(&map, pList);
680
681                 pMap = &map;
682         }
683
684         return InvokeStartAppControl(lib, req, appId, oId, null, null, pMap);
685 }
686
687
688 result
689 _AppControlImpl::InvokeStartAppControl(_LibraryImpl& lib, int req, const String& appId, const String& oId, const String* pUri, const String* pMime, const IMap* pMap)
690 {
691         result (*pFunc)(int req, const String&, const String&, const String*, const String*, const IMap*) = null;
692
693         pFunc =
694                 reinterpret_cast<result (*)(int, const String&, const String&, const String*, const String*, const IMap*)>(lib.GetProcAddress(L"StartAppControl"));
695         SysTryReturnResult(NID_APP, pFunc != null, E_OBJ_NOT_FOUND, "Entry \"StartAppControl\" not found for %ls", appId.GetPointer());
696         return (*pFunc)(req, appId, oId, pUri, pMime, pMap);
697 }
698
699 static bool
700 IsValidAppControl(const String& appcontrolID)
701 {
702         return ((appcontrolID == L"osp.appcontrol.provider.audio")
703                 || (appcontrolID == L"osp.appcontrol.provider.bluetooth")
704                 || (appcontrolID == L"osp.appcontrol.provider.calendar")
705                 || (appcontrolID == L"osp.appcontrol.provider.camera")
706                 || (appcontrolID == L"osp.appcontrol.provider.contact")
707                 || (appcontrolID == L"osp.appcontrol.provider.certificatemanager")
708                 || (appcontrolID == L"osp.appcontrol.provider.email")
709                 || (appcontrolID == L"osp.appcontrol.provider.image")
710                 || (appcontrolID == L"osp.appcontrol.provider.media")
711                 || (appcontrolID == L"osp.appcontrol.provider.message")
712                 || (appcontrolID == L"osp.appcontrol.provider.video")
713                 || (appcontrolID == L"osp.appcontrol.provider.imageeditor")
714                 || (appcontrolID == L"osp.appcontrol.provider.allshare")
715                 || (appcontrolID == L"tizen.filemanager")
716                 || (appcontrolID == L"tizen.camera")
717                 || (appcontrolID == L"tizen.gallery")
718                 || (appcontrolID == L"tizen.imageviewer")
719                 || (appcontrolID == L"tizen.videoplayer")
720                 || (appcontrolID == L"tizen.memo")
721                 || (appcontrolID == L"tizen.contacts")
722                 || (appcontrolID == L"tizen.calendar")
723                 || (appcontrolID == L"tizen.events")
724                 || (appcontrolID == L"tizen.email")
725                 || (appcontrolID == L"tizen.settings")
726                 || (appcontrolID == L"tizen.messages")
727                 || (appcontrolID == L"tizen.musicplayer")
728                 || (appcontrolID == L"tizen.bluetooth")
729                 || (appcontrolID == L"samsung.snote")
730                 || (appcontrolID == L"0pnxz8hbsr.MyFiles")
731                 || (appcontrolID == L"hdufar9ycj.Camera")
732                 || (appcontrolID == L"ijudt7w61q.Gallery")
733                 || (appcontrolID == L"jysyv9o1dc.ImageViewer")
734                 || (appcontrolID == L"npwf0scb88.VideoPlayer")
735                 || (appcontrolID == L"zunqjlsnce.Memo")
736                 || (appcontrolID == L"f9uev8hsyo.Contacts")
737                 || (appcontrolID == L"ph1vq2phrp.Calendar")
738                 || (appcontrolID == L"vxqbrefica.Email")
739                 || (appcontrolID == L"kto5jikgul.Settings")
740                 || (appcontrolID == L"8r4r5ddzzn.Messages")
741                 || (appcontrolID == L"dhrul6qzj3.MusicPlayer")
742                 || (appcontrolID == L"smemo-efl"));
743 }
744
745 result
746 _AppControlImpl::Stop(void)
747 {
748         const String appcontrolID(GetAppControlProviderId());
749         SysTryReturnResult(NID_APP, IsValidAppControl(appcontrolID), E_INVALID_OPERATION, "Invalid appcontrolID(%ls)", appcontrolID.GetPointer());
750
751         if (_property & _APPCONTROL_PROPERTY_SLP)
752         {       
753                 SysTryReturnResult(NID_APP, _reqId != _REQ_ID_INVALID, E_INVALID_OPERATION, "Invalid request ID .");
754
755                 _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
756                 SysTryReturnResult(NID_APP, pInfo != null, E_INVALID_OPERATION, "Request ID %d is not found.", _reqId);
757                 
758                 result (*pStop)(int req) = null;
759                 pStop = reinterpret_cast<result (*)(int)>(pInfo->pLib->GetProcAddress(L"TerminateAppControl"));
760                 SysTryReturnResult(NID_APP, pStop != null, E_SYSTEM, "No TerminateAppControl() function.");
761                 
762                 (*pStop)(_reqId);
763                 
764                 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(_reqId);
765                 
766                 _reqId = _REQ_ID_INVALID;
767         }
768         else if (_property & _APPCONTROL_PROPERTY_OSP)
769         {
770                 _Aul::TerminateApplicationByPid(_processId);
771         }
772
773         return E_SUCCESS;
774 }
775
776 String
777 _AppControlImpl::GetAppName(void)
778 {
779         if ((_property & _APPCONTROL_PROPERTY_OSP) && _appName.IsEmpty())
780         {
781                 const AppId& appId = _path;
782
783                 std::unique_ptr<PackageAppInfo> pInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
784
785                 if (pInfo.get())
786                 {
787                         const String& name = pInfo->GetAppName();
788                         if (name == L"_AppControl")
789                         {
790                                 // workaround for special case: requery with actual appId
791                                 const PackageId& packageId = _PackageManagerImpl::GetPackageIdByAppId(appId);
792                                 const String& defaultName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
793
794                                 const String& convertedAppId = packageId + L'.' + defaultName;
795
796                                 std::unique_ptr<PackageAppInfo> pNewInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(convertedAppId));
797
798                                 if (pNewInfo.get())
799                                 {
800                                         _appName = pNewInfo->GetAppName();
801                                 }
802                                 else
803                                 {
804                                         SysLog(NID_APP, "No default applicaiton information, possible database error.");
805                                 }
806                         }
807                         else
808                         {
809                                 _appName = pInfo->GetAppName();
810                         }
811                         SysLog(NID_APP, "Initializing AppName(%ls) for %ls.", _appName.GetPointer(), appId.GetPointer());
812                 }
813         }
814
815         return _appName;
816 }
817
818 String
819 _AppControlImpl::GetAppId(void) const
820 {
821         return (_property & _APPCONTROL_PROPERTY_OSP) ? _path : _provider;
822 }
823
824 const String&
825 _AppControlImpl::GetAppControlProviderId(void) const
826 {
827         return _provider;
828 }
829
830 const String&
831 _AppControlImpl::GetOperationId(void) const
832 {
833         return _opId;
834 }
835
836 IList*
837 _AppControlImpl::GetCategoryListN(void) const
838 {
839         const AppId& appId = GetAppId();
840         SysTryReturn(NID_APP, !appId.IsEmpty(), null, E_SYSTEM, "[E_SYSTEM] Empty appId.");
841
842         SysLog(NID_APP, "Acquiring category for appId %ls.", appId.GetPointer());
843
844         std::unique_ptr<PackageAppInfo> pAppInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
845         SysTryReturn(NID_APP, pAppInfo.get() != null, null, E_SYSTEM, "[E_SYSTEM] Getting PackageAppInfo failed.");
846
847         return pAppInfo->GetAppCategoryListN();
848 }
849
850 void
851 _AppControlImpl::StopAppControlResponseListener(IAppControlResponseListener* pListener)
852 {
853         _AppControlManager::GetInstance()->__listenerList.Add(pListener);
854 }
855
856 }}    //Tizen::App