Merge "[2.2.1]String::Contains() seems to block for long time for very long String...
[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         const bool isServiceCallee = _AppArg::IsServiceApp(b);
520
521         std::unique_ptr<HashMap> pMap(pResArg->GetArgMapN());
522
523         ArrayList list(SingleObjectDeleter);
524         _AppArg::FillLegacyAppControlResult(list, res, pMap.get(), provider);
525
526         _AppControlManager::InvokeLegacyAppControlCompleteListener(*pListener, provider, oId, &list, isSubMode | isServiceCallee);
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, pListener == null || 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(%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         const bool isSubMode = _AppArg::IsSubMode(b);
586         const bool isServiceCallee = _AppArg::IsServiceApp(b);
587
588         std::unique_ptr<HashMap> pMap(pResArg->GetArgMapN());
589
590         AppCtrlResult ret = _AppControlManager::ConvertAppControlResultCode(res);
591
592         SysLog(NID_APP, "Result code : 0x%x.", ret);
593
594         // proper callback invokation
595         _AppControlResponseEvent* pResponseEvent = null;
596         _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(reqId, pResponseEvent);
597
598         if (pResponseEvent != null)
599         {
600                 _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_COMPLETE, provider, oId, E_SUCCESS, ret, pMap.release(), reqId, isSubMode | isServiceCallee);
601                 pResponseEvent->Fire(*pResponseEventArg);
602                 SysLog(NID_APP, "OnAppControlCompleteResponseReceived, pResponseEvent is Fired");
603         }
604         else
605         {
606                 _AppControlManager::InvokeAppControlCompleteListener(*pListener, provider, oId, ret, pMap.get(), isSubMode | isServiceCallee);
607         }
608
609         return E_SUCCESS;
610 }
611
612 result
613 _AppControlImpl::StartNative(const IList* pDataList, IAppControlEventListener* pListener)
614 {
615         SysLog(NID_APP, "Enter");
616         _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
617         SysTryReturnResult(NID_APP, pInfo == null, E_IN_PROGRESS, "Request ID %d is already in progress.", _reqId);
618
619         int req = _REQ_ID_INVALID;
620         _LibraryImpl* pLib = null;
621
622         pLib = new (std::nothrow) _LibraryImpl;
623         SysTryReturnResult(NID_APP, pLib != null, E_OUT_OF_MEMORY, "Failed to allocate libraryimpl.");
624
625         unsigned long option = _LIBRARY_LOAD_OPTION_LAZY;
626         option |= _LIBRARY_LOAD_OPTION_NODELETE;
627
628         result r = pLib->Construct(_path, option);
629         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
630
631         if (pListener)
632         {
633                 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(_provider, _opId, _property, true, *pLib, pListener);
634                 if (pItem)
635                 {
636                         req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
637                 }
638         }
639         r = InvokeStartAppControl(*pLib, req, _provider, _opId, pDataList);
640
641         if (pListener == null)
642         {
643                 delete pLib;
644         }
645
646         // after acquring request number, pLib should be managed from the list, not CATCH
647         if (IsFailed(r))
648         {
649                 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
650                 SysLog(NID_APP, "[%s] A system error has occurred.", GetErrorMessage(r));
651
652                 return r;
653         }
654
655         _reqId = req;
656
657         SysLog(NID_APP, "Exit");
658         return E_SUCCESS;
659
660 CATCH:
661         delete pLib;
662
663         switch (r)
664         {
665         case E_LIBRARY_NOT_FOUND:
666                 r = E_OBJ_NOT_FOUND;
667                 break;
668         default:
669                 r = E_SYSTEM;
670                 break;
671         }
672
673         return r;
674 }
675
676 result
677 _AppControlImpl::StartNative(const String* pUriData, const String* pMimeType, const IMap* pDataList, IAppControlResponseListener* pListener)
678 {
679         SysLog(NID_APP, "Enter");
680         _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
681         SysTryReturnResult(NID_APP, pInfo == null, E_IN_PROGRESS, "Request ID %d is already in progress.", _reqId);
682
683         int req = _REQ_ID_INVALID;
684         _LibraryImpl* pLib = null;
685
686         pLib = new (std::nothrow) _LibraryImpl;
687         SysTryReturnResult(NID_APP, pLib != null, E_OUT_OF_MEMORY, "Failed to allocate libraryimpl.");
688
689         unsigned long option = _LIBRARY_LOAD_OPTION_LAZY;
690         option |= _LIBRARY_LOAD_OPTION_NODELETE;
691
692         result r = pLib->Construct(_path, option);
693
694         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
695
696         if (pListener)
697         {
698                 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(_provider, _opId, _property, false, *pLib, pListener);
699                 if (pItem)
700                 {
701                         req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
702                 }
703
704                 if (_ThreadImpl::GetCurrentThreadImpl()->GetThreadType() == THREAD_TYPE_EVENT_DRIVEN)
705                 {
706                         _AppControlResponseEvent* pAppControlResponseEvent = new (std::nothrow) _AppControlResponseEvent();
707
708                         if (pAppControlResponseEvent != null)
709                         {
710                                 r = pAppControlResponseEvent->Construct();
711                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::Construct() is failed", GetErrorMessage(r));
712
713                                 r = pAppControlResponseEvent->AddListener(*this, true);
714                                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::AddListener() is failed", GetErrorMessage(r));
715
716                                 IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = _AppControlManager::GetInstance()->GetAppControlResponseEventContainer();
717                                 if (pResponseEventContainer != null)
718                                 {
719                                         int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + req;
720                                         pResponseEventContainer->Add(responseEventRequestId, pAppControlResponseEvent);
721                                         __appControlResponseEventList.Add(responseEventRequestId);
722                                         SysLog(NID_APP, "pResponseEvent gets added. reqId(%d)", responseEventRequestId);
723                                 }
724                         }
725                 }
726         }
727         r = InvokeStartAppControl(*pLib, req, _provider, _opId, pUriData, pMimeType, pDataList);
728
729         if (pListener == null)
730         {
731                 delete pLib;
732         }
733
734         // after acquring request number, pLib should be managed from the list, not CATCH
735         if (IsFailed(r))
736         {
737                 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
738                 SysLog(NID_APP, "[%s] A system error has occurred.", GetErrorMessage(r));
739
740                 return r;
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                                 _AppControlManager::InvokeAppControlCompleteListener(*pResponseListener, pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData(), pEventArg->IsSubMode());
983
984                                 _AppControlResponseEvent* pResponseEvent = null;
985                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
986                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
987                                 delete pResponseEvent;
988                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
989                         }
990                         else
991                         {
992                                 SysLog(NID_APP, "Unexpected AppControlResponseType(%d)", pEventArg->GetType());
993                         }
994                 }
995                 else
996                 {
997                         SysLog(NID_APP, "Invalid ResponseListener");
998                 }
999         }
1000         else
1001         {
1002                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
1003         }
1004
1005 }
1006 }}    //Tizen::App