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