Merge "Add readlink failure case of timezone" into tizen_2.2
[platform/framework/native/appfw.git] / src / app / FApp_AppControlImpl.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file                FApp_AppControlImpl.cpp
19  * @brief               This is the implementation for the Application Control class.
20  */
21
22 #include <new>
23 #include <typeinfo>
24 #include <unique_ptr.h>
25
26 #include <appsvc/appsvc.h>
27
28 #include <FBaseColHashMap.h>
29 #include <FBaseSysLog.h>
30 #include <FAppAppControl.h>
31 #include <FAppAppManager.h>
32 #include <FAppPkgPackageAppInfo.h>
33 #include <FAppIAppControlEventListener.h>
34 #include <FAppIAppControlResponseListener.h>
35
36 #include <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_AppControlRegistry.h"
43 #include "FApp_AppMessageImpl.h"
44 #include "FApp_AppInfo.h"
45 #include "FAppPkg_PackageManagerImpl.h"
46 #include "FApp_Aul.h"
47 #include "FApp_AppControlEventArg.h"
48 #include "FApp_AppControlResponseEvent.h"
49 #include "FBaseRt_ThreadImpl.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
70 _AppControlImpl::_AppControlImpl(const AppControl& value)
71         : _appControl(value)
72         , _reqId(_REQ_ID_INVALID)
73         , _property(_APPCONTROL_PROPERTY_NONE)
74         , _processId(_REQ_ID_INVALID)
75 {
76         __appControlResponseEventList.Construct();
77 }
78
79 _AppControlImpl::~_AppControlImpl(void)
80 {
81         IEnumeratorT<int>* pEnum = __appControlResponseEventList.GetEnumeratorN();
82         IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = null;
83         if(pEnum != null)
84         {
85                 pResponseEventContainer = _AppControlManager::GetInstance()->GetAppControlResponseEventContainer();
86         }
87
88         while(pEnum->MoveNext() == E_SUCCESS)
89         {
90                 int reqId;
91                 pEnum->GetCurrent(reqId);
92                 if (pResponseEventContainer != null)
93                 {
94                         _AppControlResponseEvent* pResponseEvent = null;
95                         pResponseEventContainer->GetValue(reqId, pResponseEvent);
96                         delete pResponseEvent;
97
98                         pResponseEventContainer->Remove(reqId);
99                         SysLog(NID_APP, "pResponseEvent gets deleted. reqId(%d)", reqId);
100                 }
101         }
102         delete pEnum;
103 }
104
105 AppControl*
106 _AppControlImpl::CreateN(const String& path, const String& aId, const String& oId, const String& name, int prop)
107 {
108         SysTryReturn(NID_APP, !path.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Path is empty.");
109         SysTryReturn(NID_APP, !aId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Provider Id is empty.");
110         SysTryReturn(NID_APP, !oId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Operation Id is empty.");
111
112         AppControl* pAc = new (std::nothrow) AppControl;
113         SysTryReturn(NID_APP, pAc != null, null, E_OUT_OF_MEMORY, "AppControl allocation failure.");
114
115         _AppControlImpl* pImpl = pAc->__pAppControlImpl;
116         SysTryReturn(NID_APP, pImpl != null, null, E_OUT_OF_MEMORY, "AppControlImpl instance must not be null.");
117
118         pImpl->_path = path;
119         pImpl->_provider = aId;
120         pImpl->_opId = oId;
121         // [FIXME] Proper App name setting
122         pImpl->_appName = name;
123         pImpl->_property = prop;
124
125         return pAc;
126 }
127
128 AppControl*
129 _AppControlImpl::CreateN(const AppId& appId, const String& operationId, bool changeAppId)
130 {
131         SysTryReturn(NID_APP, !appId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] appId is empty.");
132
133         AppControl* pAc = new (std::nothrow) AppControl;
134         SysTryReturn(NID_APP, pAc != null, null, E_OUT_OF_MEMORY, "AppControl allocation failure.");
135
136         _AppControlImpl* pImpl = pAc->__pAppControlImpl;
137         SysTryReturn(NID_APP, pImpl != null, null, E_OUT_OF_MEMORY, "AppControlImpl instance must not be null.");
138
139         pImpl->_path = appId;
140         pImpl->_provider = appId;
141         pImpl->_opId = operationId;
142         //pImpl->_appName = appId;
143         pImpl->_property |= (_APPCONTROL_PROPERTY_OSP | _APPCONTROL_PROPERTY_PUBLIC);
144
145         if (changeAppId)
146         {
147                 pImpl->_property |= _APPCONTROL_PROPERTY_APPID_CHANGE;
148         }
149
150         return pAc;
151 }
152
153 AppControl*
154 _AppControlImpl::CreateN(const AppControl& ac)
155 {
156         const _AppControlImpl* pImpl = GetInstance(ac);
157         SysTryReturn(NID_APP, pImpl != null, null, E_INVALID_STATE, "AppControlImpl instance must not be null.");
158
159         return CreateN(pImpl->_path, pImpl->_provider, pImpl->_opId, pImpl->_appName, pImpl->_property);
160 }
161
162 const _AppControlImpl*
163 _AppControlImpl::GetInstance(const AppControl& ac)
164 {
165         return ac.__pAppControlImpl;
166 }
167
168 _AppControlImpl*
169 _AppControlImpl::GetInstance(AppControl& ac)
170 {
171         return ac.__pAppControlImpl;
172 }
173
174 result
175 _AppControlImpl::Start(const IList* pDataList, IAppControlEventListener* pListener)
176 {
177         SysLog(NID_APP, "Enter");
178         result r = E_SYSTEM;
179
180         if (_property & _APPCONTROL_PROPERTY_SLP)
181         {
182                 r = StartNative(pDataList, pListener);
183         }
184         else if (_property & _APPCONTROL_PROPERTY_OSP)
185         {
186                 r = StartOsp(pDataList, pListener);
187         }
188         else
189         {
190                 SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] Invalid AppControl type(property %d)", _property);
191         }
192         SysLog(NID_APP, "Exit");
193
194         return r;
195 }
196
197 result
198 _AppControlImpl::Start(const String* pUriData, const String* pDataType, const IMap* pExtraData, IAppControlResponseListener* pListener)
199 {
200         SysLog(NID_APP, "Enter");
201         result r = E_SYSTEM;
202
203         if (_property & _APPCONTROL_PROPERTY_SLP)
204         {
205                 r = StartNative(pUriData, pDataType, pExtraData, pListener);
206         }
207         else if (_property & _APPCONTROL_PROPERTY_OSP)
208         {
209                 r = StartOsp(pUriData, pDataType, pExtraData, pListener);
210         }
211         else
212         {
213                 SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] Invalid AppControl type(property %d)", _property);
214         }
215         SysLog(NID_APP, "Exit");
216
217         return r;
218 }
219
220 result
221 _AppControlImpl::FindAndStart(const String& operationId, const String* pUriPattern, const String* pDataType, const String* pCategory, const IMap* pExtraData, IAppControlResponseListener* pListener)
222 {
223         // [FIXME] valid argument size checking required
224         SysLog(NID_APP, "Enter");
225
226         std::unique_ptr<bundle, BundleDeleter> pBundle(bundle_create());
227         SysTryReturnResult(NID_APP, pBundle.get(), E_OUT_OF_MEMORY, "Bundle creation failure.");
228
229         _AppMessageImpl::SetOperation(pBundle.get(), operationId);
230
231         if (pUriPattern)
232         {
233                 _AppMessageImpl::SetUri(pBundle.get(), *pUriPattern);
234         }
235
236         if (pDataType)
237         {
238                 String mimeType = *pDataType;
239
240                 if ((*pDataType)[0] == L'.')
241                 {
242                         SysLog(NID_APP, "Extension to MIME conversion for %ls", pDataType->GetPointer());
243
244 #if 0
245                         String ext;
246                         pDataType->SubString(1, ext);
247
248                         result r = _AppControlManager::GetMimeFromExt(ext, mimeType);
249
250                         SysTryReturn(NID_APP, !IsFailed(r), null, r, "[%s] MIME type conversion failure for %ls.", GetErrorMessage(r), ext.GetPointer());
251
252                         pMimeType = &mimeType;
253
254                         SysLog(NID_APP, "Conversion : %ls -> %ls.", pDataType->GetPointer(), pMimeType->GetPointer());
255 #endif
256                 }
257
258                 _AppMessageImpl::SetMime(pBundle.get(), mimeType);
259         }
260
261         if (pCategory)
262         {
263                 _AppMessageImpl::SetCategory(pBundle.get(), *pCategory);
264         }
265
266         return StartImplicit(pBundle.get(), pExtraData, pListener);
267 }
268
269 result
270 _AppControlImpl::StartOsp(const IList* pDataList, IAppControlEventListener* pListener)
271 {
272         SysLog(NID_APP, "Enter");
273         result r = E_SUCCESS;
274
275         _AppArg* pArg = new (std::nothrow) _AppArg;
276         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
277
278         pArg->Construct(*this, pDataList);
279
280         _AppControlManager* pImpl = _AppControlManager::GetInstance();
281         int req = _REQ_ID_INVALID;
282
283         if (pListener)
284         {
285                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCbLegacy, pListener, _property);
286                 req = reqObj.GetRequestNumber();
287
288                 _processId = pImpl->Launch(_path, pArg, req);
289
290                 if (_processId < 0)
291                 {
292                         reqObj.Invalidate();
293                         r = GetLastResult();
294                         SysLog(NID_APP, "[%s]Launching(%ls) is failed" , GetErrorMessage(r), _path.GetPointer());
295                         return r;
296                 }
297         }
298         else
299         {
300                 _processId = pImpl->Launch(_path, pArg);
301                 delete pArg;
302                 SysTryReturnResult(NID_APP, _processId >= 0, GetLastResult(), "Launching(%ls) is failed", _path.GetPointer());
303         }
304         SysLog(NID_APP, "Exit");
305
306         return r;
307 }
308
309 result
310 _AppControlImpl::StartOsp(const String* pUriData, const String* pMimeType, const IMap* pDataList, IAppControlResponseListener* pListener)
311 {
312         SysLog(NID_APP, "Enter");
313         result r = E_SUCCESS;
314
315         _AppArg* pArg = new (std::nothrow) _AppArg;
316         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
317
318         pArg->Construct(*this, pUriData, pMimeType, pDataList);
319
320         _AppControlManager* pImpl = _AppControlManager::GetInstance();
321         int req = _REQ_ID_INVALID;
322
323         if (pListener)
324         {
325                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCb, pListener, _property);
326                 req = reqObj.GetRequestNumber();
327
328                 if (_ThreadImpl::GetCurrentThreadImpl()->GetThreadType() == THREAD_TYPE_EVENT_DRIVEN)
329                 {
330                         _AppControlResponseEvent* pAppControlResponseEvent = new (std::nothrow) _AppControlResponseEvent();
331                         if (pAppControlResponseEvent != null)
332                         {
333                                 r = pAppControlResponseEvent->Construct();
334                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::Construct() is failed", GetErrorMessage(r));
335
336                                 r = pAppControlResponseEvent->AddListener(*this, true);
337                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::AddListener() is failed", GetErrorMessage(r));
338
339                                 IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = pImpl->GetAppControlResponseEventContainer();
340                                 if (pResponseEventContainer != null)
341                                 {
342                                         pResponseEventContainer->Add(req, pAppControlResponseEvent);
343                                         __appControlResponseEventList.Add(req);
344                                         SysLog(NID_APP, "pResponseEvent gets added. reqId(%d)", req);
345                                 }
346                         }
347                 }
348
349                 _processId = pImpl->Launch(_path, pArg, req);           
350                 if (_processId < 0)
351                 {
352                         reqObj.Invalidate();
353                         r = GetLastResult();
354                         SysLog(NID_APP, "[%s]Launching(%ls) is failed" , GetErrorMessage(r), _path.GetPointer());
355                         return r;
356                 }
357         }
358         else
359         {
360                 _processId = pImpl->Launch(_path, pArg);
361                 delete pArg;
362                 SysTryReturnResult(NID_APP, _processId >= 0, GetLastResult(), "Launching(%ls) is failed", _path.GetPointer());
363         }
364         SysLog(NID_APP, "Exit");
365
366         return r;
367 }
368
369 result
370 _AppControlImpl::StartImplicit(bundle* pBundle, const IList* pDataList, IAppControlEventListener* pListener)
371 {
372         SysLog(NID_APP, "Enter");
373         result r = E_SUCCESS;
374
375         _AppArg* pArg = new (std::nothrow) _AppArg;
376         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
377
378         pArg->Construct(pBundle);
379
380         _AppMessageImpl::AddData(pArg->GetBundle(), pDataList);
381
382         _AppControlManager* pImpl = _AppControlManager::GetInstance();
383         int req = _REQ_ID_INVALID;
384
385         if (pListener)
386         {
387                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCbLegacy, pListener, _APPCONTROL_PROPERTY_NONE);
388                 req = reqObj.GetRequestNumber();
389
390                 r = pImpl->LaunchAppImplicit(pArg, req);
391                 SysTryCatch(NID_APP, r == E_SUCCESS, reqObj.Invalidate(), r, "[%s] Propagating." , GetErrorMessage(r));
392         }
393         else
394         {
395                 r = pImpl->LaunchAppImplicit(pArg, -1);
396                 delete pArg;
397         }
398
399         // [FIXME] launch registration is not working correctly
400         SysLog(NID_APP, "Exit");
401
402 CATCH:
403         return r;
404 }
405
406 result
407 _AppControlImpl::StartImplicit(bundle* pBundle, const IMap* pData, IAppControlResponseListener* pListener)
408 {
409         SysLog(NID_APP, "Enter");
410         result r = E_SUCCESS;
411
412         _AppArg* pArg = new (std::nothrow) _AppArg;
413         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Argument allocation failure.");
414
415         pArg->Construct(pBundle);
416
417         _AppArg::AddStrMap(pArg->GetBundle(), pData);
418
419         _AppControlManager* pImpl = _AppControlManager::GetInstance();
420         int req = _REQ_ID_INVALID;
421
422         if (pListener)
423         {
424                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pImpl, pArg, AppControlCb, pListener, _APPCONTROL_PROPERTY_NONE);
425                 req = reqObj.GetRequestNumber();
426
427                 if (_ThreadImpl::GetCurrentThreadImpl()->GetThreadType() == THREAD_TYPE_EVENT_DRIVEN)
428                 {
429                         _AppControlResponseEvent* pAppControlResponseEvent = new (std::nothrow) _AppControlResponseEvent();
430
431                         if (pAppControlResponseEvent != null)
432                         {
433                                 r = pAppControlResponseEvent->Construct();
434                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::Construct() is failed", GetErrorMessage(r));
435
436                                 r = pAppControlResponseEvent->AddListener(*pImpl, true);
437                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::AddListener() is failed", GetErrorMessage(r));
438
439                                 IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = pImpl->GetAppControlResponseEventContainer();
440                                 if (pResponseEventContainer != null)
441                                 {
442                                         pResponseEventContainer->Add(req, pAppControlResponseEvent);
443                                         SysLog(NID_APP, "pResponseEvent gets added. reqId(%d)", req);
444                                 }
445                         }
446                 }
447                 r = pImpl->LaunchAppImplicit(pArg, req);
448                 SysTryCatch(NID_APP, r == E_SUCCESS, reqObj.Invalidate(), r, "[%s] Propagating." , GetErrorMessage(r));
449         }
450         else
451         {
452                 r = pImpl->LaunchAppImplicit(pArg, -1);
453                 delete pArg;
454         }
455         SysLog(NID_APP, "Exit");
456
457         // [FIXME] launch registration is not working correctly
458
459 CATCH:
460
461         return r;
462 }
463
464 result
465 _AppControlImpl::AppControlCbLegacy(void* data, _AppArg* pArg, _AppArg* pResArg, service_result_e res, int prop, int reqId)
466 {
467         SysLog(NID_APP, "Result value %d", res);
468
469         SysTryReturnResult(NID_APP, data && pResArg && pArg, E_SYSTEM, "Invalid result (callback, result, arg) = (0x%x, 0x%x, 0x%x).",
470                                           data, pResArg,
471                                           pArg);
472
473         bundle* b = pResArg->GetBundle();
474         SysTryReturnResult(NID_APP, b != NULL, E_SYSTEM, "Invalid result bundle.");
475
476         IAppControlEventListener* pListener = static_cast<IAppControlEventListener*>(data);
477         SysTryReturnResult(NID_APP, pListener == null || typeid(pListener) == typeid(IAppControlEventListener*), E_SYSTEM, "Invalid result callback");
478
479         bundle* inb = pArg->GetBundle();
480         SysTryReturnResult(NID_APP, inb != NULL, E_SYSTEM, "Empty caller bundle.");
481
482         String oId;
483
484         AppId provider = pResArg->GetCalleeAppId();
485
486         const char* p = appsvc_get_operation(inb);
487         if (p)
488         {
489                 oId = p;
490         }
491
492         SysLog(NID_APP, "Invoking callback with (%ls, %ls)", provider.GetPointer(), oId.GetPointer());
493
494         if (prop & _APPCONTROL_PROPERTY_ALIAS)
495         {
496                 const _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
497                 pEntry = _AppControlRegistry::GetInstance()->GetReverseAppControlAliasEntry(provider, oId);
498                 if (pEntry)
499                 {
500                         provider = pEntry->provider;
501                         oId = pEntry->operation;
502
503                         SysLog(NID_APP, "Legacy AppControl(%ls, %ls).", provider.GetPointer(), oId.GetPointer());
504                 }
505         }
506
507         if (prop & _APPCONTROL_PROPERTY_APPID_CHANGE)
508         {
509                 String tmp = _AppControlRegistry::GetInstance()->GetReverseAliasAppId(provider);
510                 if (!tmp.IsEmpty())
511                 {
512                         SysLog(NID_APP, "App change (%ls -> %ls).", provider.GetPointer(), tmp.GetPointer());
513
514                         provider = tmp;
515                 }
516         }
517
518         const bool isSubMode = _AppArg::IsSubMode(b);
519
520         std::unique_ptr<HashMap> pMap(pResArg->GetArgMapN());
521
522         ArrayList list(SingleObjectDeleter);
523         _AppArg::FillLegacyAppControlResult(list, res, pMap.get(), provider);
524
525         _AppControlManager::InvokeLegacyAppControlCompleteListener(*pListener, provider, oId, &list, isSubMode);
526
527         return E_SUCCESS;
528 }
529
530 result
531 _AppControlImpl::AppControlCb(void* data, _AppArg* pArg, _AppArg* pResArg, service_result_e res, int prop, int reqId)
532 {
533         SysLog(NID_APP, "Result value : %d, property : 0x%x", res, prop);
534
535         SysTryReturnResult(NID_APP, data && pResArg && pArg, E_SYSTEM, "Invalid result (callback, result, arg) = (0x%x, 0x%x, 0x%x).",
536                                           data, pResArg,
537                                           pArg);
538
539         bundle* b = pResArg->GetBundle();
540         SysTryReturnResult(NID_APP, b != NULL, E_SYSTEM, "Invalid result bundle.");
541
542         IAppControlResponseListener* pListener = static_cast<IAppControlResponseListener*>(data);
543         SysTryReturnResult(NID_APP, pListener == null || typeid(pListener) == typeid(IAppControlResponseListener*), E_SYSTEM, "Invalid result callback");
544
545         bundle* inb = pArg->GetBundle();
546         SysTryReturnResult(NID_APP, inb != NULL, E_SYSTEM, "Empty caller bundle.");
547
548         String oId;
549
550         AppId provider = pResArg->GetCalleeAppId();
551
552         const char* p = appsvc_get_operation(inb);
553         if (p)
554         {
555                 oId = p;
556         }
557
558         SysLog(NID_APP, "Invoking callback with (%ls, %ls)", provider.GetPointer(), oId.GetPointer());
559
560         if (prop & _APPCONTROL_PROPERTY_ALIAS)
561         {
562                 const _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
563                 pEntry = _AppControlRegistry::GetInstance()->GetReverseRuntimeAliasEntry(provider, oId);
564                 if (pEntry)
565                 {
566                         provider = pEntry->provider;
567                         oId = pEntry->operation;
568
569                         SysLog(NID_APP, "Original AppControl(%ls, %ls).", provider.GetPointer(), oId.GetPointer());
570                 }
571         }
572
573         if (prop & _APPCONTROL_PROPERTY_APPID_CHANGE)
574         {
575                 String tmp = _AppControlRegistry::GetInstance()->GetReverseAliasAppId(provider);
576                 if (!tmp.IsEmpty())
577                 {
578                         SysLog(NID_APP, "App change (%ls -> %ls).", provider.GetPointer(), tmp.GetPointer());
579
580                         provider = tmp;
581                 }
582         }
583
584         const bool isSubMode = _AppArg::IsSubMode(b);
585
586         std::unique_ptr<HashMap> pMap(pResArg->GetArgMapN());
587
588         AppCtrlResult ret = _AppControlManager::ConvertAppControlResultCode(res);
589
590         SysLog(NID_APP, "Result code : 0x%x.", ret);
591
592         // proper callback invokation
593         _AppControlResponseEvent* pResponseEvent = null;
594         _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(reqId, pResponseEvent);
595
596         if (pResponseEvent != null)
597         {
598                 _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_COMPLETE, provider, oId, E_SUCCESS, ret, pMap.release(), reqId, isSubMode);
599                 pResponseEvent->Fire(*pResponseEventArg);
600                 SysLog(NID_APP, "OnAppControlCompleteResponseReceived, pResponseEvent is Fired");
601         }
602         else
603         {
604                 _AppControlManager::InvokeAppControlCompleteListener(*pListener, provider, oId, ret, pMap.get(), isSubMode);
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                                 _AppControlManager::InvokeAppControlCompleteListener(*pResponseListener, pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData(), pEventArg->IsSubMode());
981
982                                 _AppControlResponseEvent* pResponseEvent = null;
983                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
984                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
985                                 delete pResponseEvent;
986                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
987                         }
988                         else
989                         {
990                                 SysLog(NID_APP, "Unexpected AppControlResponseType(%d)", pEventArg->GetType());
991                         }
992                 }
993                 else
994                 {
995                         SysLog(NID_APP, "Invalid ResponseListener");
996                 }
997         }
998         else
999         {
1000                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
1001         }
1002
1003 }
1004 }}    //Tizen::App