Merge "fix AppControl E_MAX_EXCEEDED result" 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                 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
648                 SysLog(NID_APP, "[%s] A system error has occurred.", GetErrorMessage(r));
649
650                 return r;
651         }
652
653         _reqId = req;
654
655         SysLog(NID_APP, "Exit");
656         return E_SUCCESS;
657
658 CATCH:
659         delete pLib;
660
661         switch (r)
662         {
663         case E_LIBRARY_NOT_FOUND:
664                 r = E_OBJ_NOT_FOUND;
665                 break;
666         default:
667                 r = E_SYSTEM;
668                 break;
669         }
670
671         return r;
672 }
673
674 result
675 _AppControlImpl::StartNative(const String* pUriData, const String* pMimeType, const IMap* pDataList, IAppControlResponseListener* pListener)
676 {
677         SysLog(NID_APP, "Enter");
678         _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
679         SysTryReturnResult(NID_APP, pInfo == null, E_IN_PROGRESS, "Request ID %d is already in progress.", _reqId);
680
681         int req = _REQ_ID_INVALID;
682         _LibraryImpl* pLib = null;
683
684         pLib = new (std::nothrow) _LibraryImpl;
685         SysTryReturnResult(NID_APP, pLib != null, E_OUT_OF_MEMORY, "Failed to allocate libraryimpl.");
686
687         unsigned long option = _LIBRARY_LOAD_OPTION_LAZY;
688         option |= _LIBRARY_LOAD_OPTION_NODELETE;
689
690         result r = pLib->Construct(_path, option);
691
692         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
693
694         if (pListener)
695         {
696                 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(_provider, _opId, _property, false, *pLib, pListener);
697                 if (pItem)
698                 {
699                         req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
700                 }
701
702                 if (_ThreadImpl::GetCurrentThreadImpl()->GetThreadType() == THREAD_TYPE_EVENT_DRIVEN)
703                 {
704                         _AppControlResponseEvent* pAppControlResponseEvent = new (std::nothrow) _AppControlResponseEvent();
705
706                         if (pAppControlResponseEvent != null)
707                         {
708                                 r = pAppControlResponseEvent->Construct();
709                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::Construct() is failed", GetErrorMessage(r));
710
711                                 r = pAppControlResponseEvent->AddListener(*this, true);
712                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::AddListener() is failed", GetErrorMessage(r));
713
714                                 IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = _AppControlManager::GetInstance()->GetAppControlResponseEventContainer();
715                                 if (pResponseEventContainer != null)
716                                 {
717                                         int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + req;
718                                         pResponseEventContainer->Add(responseEventRequestId, pAppControlResponseEvent);
719                                         __appControlResponseEventList.Add(responseEventRequestId);
720                                         SysLog(NID_APP, "pResponseEvent gets added. reqId(%d)", responseEventRequestId);
721                                 }
722                         }
723                 }
724         }
725         r = InvokeStartAppControl(*pLib, req, _provider, _opId, pUriData, pMimeType, pDataList);
726
727         if (pListener == null)
728         {
729                 delete pLib;
730         }
731
732         // after acquring request number, pLib should be managed from the list, not CATCH
733         if (IsFailed(r))
734         {
735                 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
736                 SysLog(NID_APP, "[%s] A system error has occurred.", GetErrorMessage(r));
737
738                 return r;
739         }
740
741         _reqId = req;
742         SysLog(NID_APP, "Exit");
743
744         return E_SUCCESS;
745
746 CATCH:
747         delete pLib;
748
749         switch (r)
750         {
751         case E_LIBRARY_NOT_FOUND:
752                 r = E_OBJ_NOT_FOUND;
753                 break;
754         default:
755                 r = E_SYSTEM;
756                 break;
757         }
758
759         return r;
760 }
761
762 result
763 _AppControlImpl::InvokeStartAppControl(_LibraryImpl& lib, int req, const String& appId, const String& oId, const IList* pList)
764 {
765         SysLog(NID_APP, "Legacy stuff for converting argument");
766
767         HashMap map(SingleObjectDeleter);
768         HashMap* pMap = null;
769         if (pList)
770         {
771                 map.Construct();
772
773                 _AppArg::FillMapFromList(&map, pList);
774
775                 pMap = &map;
776         }
777
778         return InvokeStartAppControl(lib, req, appId, oId, null, null, pMap);
779 }
780
781
782 result
783 _AppControlImpl::InvokeStartAppControl(_LibraryImpl& lib, int req, const String& appId, const String& oId, const String* pUri, const String* pMime, const IMap* pMap)
784 {
785         result (*pFunc)(int req, const String&, const String&, const String*, const String*, const IMap*) = null;
786
787         pFunc =
788                 reinterpret_cast<result (*)(int, const String&, const String&, const String*, const String*, const IMap*)>(lib.GetProcAddress(L"StartAppControl"));
789         SysTryReturnResult(NID_APP, pFunc != null, E_OBJ_NOT_FOUND, "Entry \"StartAppControl\" not found for %ls", appId.GetPointer());
790
791         const String* pActualUri = (pUri && !(pUri->IsEmpty())) ? pUri : null;
792         const String* pActualMime = (pMime && !(pMime->IsEmpty())) ? pMime : null;
793         return (*pFunc)(req, appId, oId, pActualUri, pActualMime, pMap);
794 }
795
796 static bool
797 IsValidAppControl(const String& appcontrolID)
798 {
799         return ((appcontrolID == L"osp.appcontrol.provider.audio")
800                 || (appcontrolID == L"osp.appcontrol.provider.bluetooth")
801                 || (appcontrolID == L"osp.appcontrol.provider.calendar")
802                 || (appcontrolID == L"osp.appcontrol.provider.camera")
803                 || (appcontrolID == L"osp.appcontrol.provider.contact")
804                 || (appcontrolID == L"osp.appcontrol.provider.certificatemanager")
805                 || (appcontrolID == L"osp.appcontrol.provider.email")
806                 || (appcontrolID == L"osp.appcontrol.provider.image")
807                 || (appcontrolID == L"osp.appcontrol.provider.media")
808                 || (appcontrolID == L"osp.appcontrol.provider.message")
809                 || (appcontrolID == L"osp.appcontrol.provider.video")
810                 || (appcontrolID == L"osp.appcontrol.provider.imageeditor")
811                 || (appcontrolID == L"osp.appcontrol.provider.allshare")
812                 || (appcontrolID == L"tizen.filemanager")
813                 || (appcontrolID == L"tizen.camera")
814                 || (appcontrolID == L"tizen.gallery")
815                 || (appcontrolID == L"tizen.imageviewer")
816                 || (appcontrolID == L"tizen.videoplayer")
817                 || (appcontrolID == L"tizen.memo")
818                 || (appcontrolID == L"tizen.contacts")
819                 || (appcontrolID == L"tizen.calendar")
820                 || (appcontrolID == L"tizen.todo")
821                 || (appcontrolID == L"tizen.email")
822                 || (appcontrolID == L"tizen.settings")
823                 || (appcontrolID == L"tizen.messages")
824                 || (appcontrolID == L"tizen.musicplayer")
825                 || (appcontrolID == L"tizen.bluetooth")
826                 || (appcontrolID == L"samsung.snote")
827                 || (appcontrolID == L"0pnxz8hbsr.MyFiles")
828                 || (appcontrolID == L"hdufar9ycj.Camera")
829                 || (appcontrolID == L"ijudt7w61q.Gallery")
830                 || (appcontrolID == L"jysyv9o1dc.ImageViewer")
831                 || (appcontrolID == L"npwf0scb88.VideoPlayer")
832                 || (appcontrolID == L"zunqjlsnce.Memo")
833                 || (appcontrolID == L"f9uev8hsyo.Contacts")
834                 || (appcontrolID == L"ph1vq2phrp.Calendar")
835                 || (appcontrolID == L"vxqbrefica.Email")
836                 || (appcontrolID == L"kto5jikgul.Settings")
837                 || (appcontrolID == L"8r4r5ddzzn.Messages")
838                 || (appcontrolID == L"dhrul6qzj3.MusicPlayer")
839                 || (appcontrolID == L"smemo-efl"));
840 }
841
842 result
843 _AppControlImpl::Stop(void)
844 {
845         const String appcontrolID(GetAppControlProviderId());
846         SysTryReturnResult(NID_APP, IsValidAppControl(appcontrolID), E_INVALID_OPERATION, "Invalid appcontrolID(%ls)", appcontrolID.GetPointer());
847
848         if (_property & _APPCONTROL_PROPERTY_SLP)
849         {       
850                 SysTryReturnResult(NID_APP, _reqId != _REQ_ID_INVALID, E_INVALID_OPERATION, "Invalid request ID .");
851
852                 _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
853                 SysTryReturnResult(NID_APP, pInfo != null, E_INVALID_OPERATION, "Request ID %d is not found.", _reqId);
854                 
855                 result (*pStop)(int req) = null;
856                 pStop = reinterpret_cast<result (*)(int)>(pInfo->pLib->GetProcAddress(L"TerminateAppControl"));
857                 SysTryReturnResult(NID_APP, pStop != null, E_SYSTEM, "No TerminateAppControl() function.");
858                 
859                 (*pStop)(_reqId);
860                 
861                 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(_reqId);
862                 
863                 _reqId = _REQ_ID_INVALID;
864         }
865         else if (_property & _APPCONTROL_PROPERTY_OSP)
866         {
867                 _Aul::TerminateApplicationByPid(_processId);
868         }
869
870         return E_SUCCESS;
871 }
872
873 String
874 _AppControlImpl::GetAppName(void)
875 {
876         if (_appName.IsEmpty())
877         {
878                 AppId appId = GetAppId();
879                 AppId aliasAppId = _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
880                 if (!aliasAppId.IsEmpty())
881                 {
882                         appId = aliasAppId;
883                 }
884
885                 std::unique_ptr<PackageAppInfo> pInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
886                 if (pInfo.get())
887                 {
888                         SysLog(NID_APP, "PackageInfo of appId(%ls) exists", appId.GetPointer());
889                         const String& name = pInfo->GetAppName();
890                         if (name == L"_AppControl")
891                         {
892                                 // workaround for special case: requery with actual appId
893                                 const PackageId& packageId = _PackageManagerImpl::GetPackageIdByAppId(appId);
894                                 const String& defaultName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
895
896                                 const String& convertedAppId = packageId + L'.' + defaultName;
897
898                                 std::unique_ptr<PackageAppInfo> pNewInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(convertedAppId));
899
900                                 if (pNewInfo.get())
901                                 {
902                                         _appName = pNewInfo->GetAppDisplayName();
903                                 }
904                                 else
905                                 {
906                                         SysLog(NID_APP, "No default applicaiton information, possible database error.");
907                                 }
908                         }
909                         else
910                         {
911                                 _appName = pInfo->GetAppDisplayName();
912                         }
913                 }
914                 else
915                 {
916                         SysLog(NID_APP, "PackageInfo of appId(%ls) does not exist", appId.GetPointer());
917                 }
918         }
919
920         return _appName;
921 }
922
923 String
924 _AppControlImpl::GetAppId(void) const
925 {
926         return (_property & _APPCONTROL_PROPERTY_OSP) ? _path : _provider;
927 }
928
929 const String&
930 _AppControlImpl::GetAppControlProviderId(void) const
931 {
932         return _provider;
933 }
934
935 const String&
936 _AppControlImpl::GetOperationId(void) const
937 {
938         return _opId;
939 }
940
941 IList*
942 _AppControlImpl::GetCategoryListN(void) const
943 {
944         AppId appId = GetAppId();
945         SysTryReturn(NID_APP, !appId.IsEmpty(), null, E_SYSTEM, "[E_SYSTEM] Empty appId.");
946
947         AppId aliasAppId = _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
948         if (!aliasAppId.IsEmpty())
949         {
950                 appId = aliasAppId;
951         }
952
953         SysLog(NID_APP, "Acquiring category for app %ls.", appId.GetPointer());
954
955         std::unique_ptr<PackageAppInfo> pAppInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
956         SysTryReturn(NID_APP, pAppInfo.get() != null, null, E_SYSTEM, "[E_SYSTEM] Getting PackageAppInfo failed.");
957
958         return pAppInfo->GetAppCategoryListN();
959 }
960
961 void
962 _AppControlImpl::StopAppControlResponseListener(IAppControlResponseListener* pListener)
963 {
964         _AppControlManager::GetInstance()->__listenerList.Add(pListener);
965 }
966
967 void
968 _AppControlImpl::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
969 {
970         const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
971
972         if (pEventArg != null)
973         {
974                 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
975
976                 if(pResponseListener != null)
977                 {
978                         if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_COMPLETE)
979                         {
980                                 pResponseListener->OnAppControlCompleteResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData());
981                                 SysLog(NID_APP, "OnAppControlCompleteResponseReceived called");
982
983                                 _AppControlResponseEvent* pResponseEvent = null;
984                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
985                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
986                                 delete pResponseEvent;
987                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
988                         }
989                         else
990                         {
991                                 SysLog(NID_APP, "Unexpected AppControlResponseType(%d)", pEventArg->GetType());
992                         }
993                 }
994                 else
995                 {
996                         SysLog(NID_APP, "Invalid ResponseListener");
997                 }
998         }
999         else
1000         {
1001                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
1002         }
1003
1004 }
1005 }}    //Tizen::App