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