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