2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file FApp_AppControlImpl.cpp
19 * @brief This is the implementation for the Application Control class.
24 #include <unique_ptr.h>
26 #include <appsvc/appsvc.h>
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>
36 #include "FApp_AppControlImpl.h"
37 #include "FApp_AppControlManager.h"
38 #include "FApp_IAppControlPluginProvider.h"
39 #include "FApp_AppArg.h"
40 #include "FApp_AppControlRegistry.h"
41 #include "FApp_AppMessageImpl.h"
42 #include "FApp_AppInfo.h"
43 #include "FAppPkg_PackageManagerImpl.h"
45 #include "FApp_AppControlEventArg.h"
46 #include "FApp_AppControlResponseEvent.h"
47 #include "FBaseRt_ThreadImpl.h"
49 using namespace Tizen::Base;
50 using namespace Tizen::Base::Collection;
51 using namespace Tizen::Base::Runtime;
52 using namespace Tizen::App;
53 using namespace Tizen::App::Package;
54 using namespace Tizen::Io;
59 static const int _REQ_ID_INVALID = -1;
60 const wchar_t ACTL_IMPLICIT_PLUGIN[] = L"libosp-ac-implicit.so";
64 namespace Tizen { namespace App
67 _AppControlImpl::_AppControlImpl(const AppControl& value)
69 , _reqId(_REQ_ID_INVALID)
70 , _property(_APPCONTROL_PROPERTY_NONE)
71 , _processId(_REQ_ID_INVALID)
73 __appControlResponseEventList.Construct();
76 _AppControlImpl::~_AppControlImpl(void)
78 IEnumeratorT<int>* pEnum = __appControlResponseEventList.GetEnumeratorN();
79 IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = null;
82 pResponseEventContainer = _AppControlManager::GetInstance()->GetAppControlResponseEventContainer();
85 while(pEnum->MoveNext() == E_SUCCESS)
88 pEnum->GetCurrent(reqId);
89 if (pResponseEventContainer != null)
91 _AppControlResponseEvent* pResponseEvent = null;
92 pResponseEventContainer->GetValue(reqId, pResponseEvent);
93 delete pResponseEvent;
95 pResponseEventContainer->Remove(reqId);
96 SysLog(NID_APP, "pResponseEvent gets deleted. reqId(%d)", reqId);
103 _AppControlImpl::CreateN(const String& path, const String& aId, const String& oId, int prop)
105 SysTryReturn(NID_APP, !path.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Path is empty.");
106 SysTryReturn(NID_APP, !aId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Provider Id is empty.");
107 SysTryReturn(NID_APP, !oId.IsEmpty(), null, E_INVALID_ARG, "[E_INVALID_ARG] Operation Id is empty.");
109 AppControl* pAc = new (std::nothrow) AppControl;
110 SysTryReturn(NID_APP, pAc != null, null, E_OUT_OF_MEMORY, "AppControl allocation failure.");
112 _AppControlImpl* pImpl = pAc->__pAppControlImpl;
113 SysTryReturn(NID_APP, pImpl != null, null, E_OUT_OF_MEMORY, "AppControlImpl instance must not be null.");
118 pImpl->_property = prop;
124 const _AppControlImpl*
125 _AppControlImpl::GetInstance(const AppControl& ac)
127 return ac.__pAppControlImpl;
131 _AppControlImpl::GetInstance(AppControl& ac)
133 return ac.__pAppControlImpl;
136 _IAppControlPluginProvider*
137 _AppControlImpl::GetAppControlPluginProvider(const String& path)
140 lib.Construct(path, _LIBRARY_OPTION);
142 APP_CONTROL_PROVIDER_GET_FN pProvider = reinterpret_cast<APP_CONTROL_PROVIDER_GET_FN>(lib.GetProcAddress(L"GetAppControlProviderPlugin"));
146 SysLogException(NID_APP, E_SYSTEM, "Cannot load plugin properly for %ls.", path.GetPointer());
150 return (*pProvider)();
155 _AppControlImpl::FindAndStart(const String& operationId, const String* pUriPattern, const String* pDataType, const String* pCategory, const IMap* pExtraData, IAppControlResponseListener* pListener)
157 // [FIXME] valid argument size checking required
158 SysLog(NID_APP, "Enter");
160 std::unique_ptr<bundle, BundleDeleter> pBundle(bundle_create());
161 SysTryReturnResult(NID_APP, pBundle.get(), E_OUT_OF_MEMORY, "Bundle creation failure.");
163 _AppMessageImpl::SetOperation(pBundle.get(), operationId);
167 _AppMessageImpl::SetUri(pBundle.get(), *pUriPattern);
172 String mimeType = *pDataType;
174 if ((*pDataType)[0] == L'.')
176 SysLog(NID_APP, "Extension to MIME conversion for %ls", pDataType->GetPointer());
180 pDataType->SubString(1, ext);
182 result r = _AppControlManager::GetMimeFromExt(ext, mimeType);
184 SysTryReturn(NID_APP, !IsFailed(r), null, r, "[%s] MIME type conversion failure for %ls.", GetErrorMessage(r), ext.GetPointer());
186 pMimeType = &mimeType;
188 SysLog(NID_APP, "Conversion : %ls -> %ls.", pDataType->GetPointer(), pMimeType->GetPointer());
192 _AppMessageImpl::SetMime(pBundle.get(), mimeType);
197 _AppMessageImpl::SetCategory(pBundle.get(), *pCategory);
200 return StartImplicit(pBundle.get(), pExtraData, pListener);
205 _AppControlImpl::StartImplicit(const _AppMessageImpl& msg, IEventListener* pListener, bool isLegacy)
207 SysLog(NID_APP, "Enter");
208 int req = _REQ_ID_INVALID;
210 _IAppControlPluginProvider* pProvider = GetAppControlPluginProvider(ACTL_IMPLICIT_PLUGIN);
211 if (pProvider == null)
213 SysPropagate(NID_APP, E_OBJ_NOT_FOUND);
214 return E_OBJ_NOT_FOUND;
219 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(isLegacy, pProvider, pListener);
222 req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
226 result r = InvokeStartAppControl(pProvider, req, L"", msg);
228 if (pListener == null)
230 pProvider->Release();
233 // after acquring request number, pLib should be managed from the list, not CATCH
236 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
237 SysLog(NID_APP, "[%s] A system error has occurred.", GetErrorMessage(r));
242 SysLog(NID_APP, "Exit %d", req);
248 _AppControlImpl::StartImplicit(bundle* pBundle, const IList* pDataList, IAppControlEventListener* pListener)
250 _AppMessageImpl msg(pBundle);
251 msg.AddData(pDataList);
253 return StartImplicit(msg, pListener, true);
258 _AppControlImpl::StartImplicit(bundle* pBundle, const IMap* pData, IAppControlResponseListener* pListener)
260 _AppMessageImpl msg(pBundle);
261 _AppArg::AddStrMap(msg.GetBundle(), pData);
263 return StartImplicit(msg, pListener, false);
268 _AppControlImpl::Start(const IList* pDataList, IAppControlEventListener* pListener)
270 SysLog(NID_APP, "Enter");
271 _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
272 SysTryReturnResult(NID_APP, pInfo == null, E_IN_PROGRESS, "Request ID %d is already in progress.", _reqId);
274 int req = _REQ_ID_INVALID;
276 _IAppControlPluginProvider* pProvider = GetAppControlPluginProvider(_path);
277 if (pProvider == null)
279 SysPropagate(NID_APP, E_OBJ_NOT_FOUND);
280 return E_OBJ_NOT_FOUND;
285 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(_appId, _opId, _property, true, pProvider, pListener);
288 req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
292 result r = InvokeStartAppControl(pProvider, req, _appId, _opId, pDataList);
294 if (pListener == null)
296 pProvider->Release();
299 // after acquring request number, pLib should be managed from the list, not CATCH
302 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
303 SysLog(NID_APP, "[%s] A system error has occurred.", GetErrorMessage(r));
310 SysLog(NID_APP, "Exit %d", req);
315 _AppControlImpl::Start(const String* pUriData, const String* pMimeType, const IMap* pDataList, IAppControlResponseListener* pListener)
317 SysLog(NID_APP, "Enter");
318 _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
319 SysTryReturnResult(NID_APP, pInfo == null, E_IN_PROGRESS, "Request ID %d is already in progress.", _reqId);
321 int req = _REQ_ID_INVALID;
322 result r = E_SUCCESS;
324 _IAppControlPluginProvider* pProvider = GetAppControlPluginProvider(_path);
325 if (pProvider == null)
327 SysPropagate(NID_APP, E_OBJ_NOT_FOUND);
328 return E_OBJ_NOT_FOUND;
333 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(_appId, _opId, _property, false, pProvider, pListener);
336 req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
339 if (_ThreadImpl::GetCurrentThreadImpl()->GetThreadType() == THREAD_TYPE_EVENT_DRIVEN)
341 _AppControlResponseEvent* pAppControlResponseEvent = new (std::nothrow) _AppControlResponseEvent();
343 if (pAppControlResponseEvent != null)
345 r = pAppControlResponseEvent->Construct();
346 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::Construct() is failed", GetErrorMessage(r));
348 r = pAppControlResponseEvent->AddListener(*this, true);
349 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::AddListener() is failed", GetErrorMessage(r));
351 IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = _AppControlManager::GetInstance()->GetAppControlResponseEventContainer();
352 if (pResponseEventContainer != null)
354 int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + req;
355 pResponseEventContainer->Add(responseEventRequestId, pAppControlResponseEvent);
356 __appControlResponseEventList.Add(responseEventRequestId);
357 SysLog(NID_APP, "pResponseEvent gets added. reqId(%d)", responseEventRequestId);
362 r = InvokeStartAppControl(pProvider, req, _appId, _opId, pUriData, pMimeType, pDataList);
364 if (pListener == null)
366 pProvider->Release();
369 // after acquring request number, pLib should be managed from the list, not CATCH
372 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
373 SysLog(NID_APP, "[%s] A system error has occurred.", GetErrorMessage(r));
379 SysLog(NID_APP, "Exit %d", req);
385 _AppControlImpl::InvokeStartAppControl(_IAppControlPluginProvider* pProvider, int req, const String& appId, const String& oId, const IList* pList)
387 SysLog(NID_APP, "Legacy stuff for converting argument");
389 HashMap map(SingleObjectDeleter);
390 HashMap* pMap = null;
395 _AppArg::FillMapFromList(&map, pList);
400 return InvokeStartAppControl(pProvider, req, appId, oId, null, null, pMap);
405 _AppControlImpl::InvokeStartAppControl(_IAppControlPluginProvider* pProvider, int req, const String& appId, const String& oId, const String* pUri, const String* pMime, const IMap* pMap)
407 _AppMessageImpl msg(appId, oId, pUri, pMime, pMap);
409 return InvokeStartAppControl(pProvider, req, appId, msg);
414 _AppControlImpl::InvokeStartAppControl(_IAppControlPluginProvider* pProvider, int req, const String& appId, const _AppMessageImpl& message)
416 SysTryReturnResult(NID_APP, pProvider != null, E_SYSTEM, "Wrong AppControl provider plugin for %ls(%d).", appId.GetPointer(), req);
418 return pProvider->StartAppControlPlugin(req, appId, message, null);
423 IsValidAppControl(const String& appcontrolID)
425 return ((appcontrolID == L"osp.appcontrol.provider.audio")
426 || (appcontrolID == L"osp.appcontrol.provider.bluetooth")
427 || (appcontrolID == L"osp.appcontrol.provider.calendar")
428 || (appcontrolID == L"osp.appcontrol.provider.camera")
429 || (appcontrolID == L"osp.appcontrol.provider.contact")
430 || (appcontrolID == L"osp.appcontrol.provider.certificatemanager")
431 || (appcontrolID == L"osp.appcontrol.provider.email")
432 || (appcontrolID == L"osp.appcontrol.provider.image")
433 || (appcontrolID == L"osp.appcontrol.provider.media")
434 || (appcontrolID == L"osp.appcontrol.provider.message")
435 || (appcontrolID == L"osp.appcontrol.provider.video")
436 || (appcontrolID == L"osp.appcontrol.provider.imageeditor")
437 || (appcontrolID == L"osp.appcontrol.provider.allshare")
438 || (appcontrolID == L"tizen.filemanager")
439 || (appcontrolID == L"tizen.camera")
440 || (appcontrolID == L"tizen.gallery")
441 || (appcontrolID == L"tizen.imageviewer")
442 || (appcontrolID == L"tizen.videoplayer")
443 || (appcontrolID == L"tizen.memo")
444 || (appcontrolID == L"tizen.contacts")
445 || (appcontrolID == L"tizen.calendar")
446 || (appcontrolID == L"tizen.todo")
447 || (appcontrolID == L"tizen.email")
448 || (appcontrolID == L"tizen.settings")
449 || (appcontrolID == L"tizen.messages")
450 || (appcontrolID == L"tizen.musicplayer")
451 || (appcontrolID == L"tizen.bluetooth")
452 || (appcontrolID == L"samsung.snote")
453 || (appcontrolID == L"0pnxz8hbsr.MyFiles")
454 || (appcontrolID == L"hdufar9ycj.Camera")
455 || (appcontrolID == L"ijudt7w61q.Gallery")
456 || (appcontrolID == L"jysyv9o1dc.ImageViewer")
457 || (appcontrolID == L"npwf0scb88.VideoPlayer")
458 || (appcontrolID == L"zunqjlsnce.Memo")
459 || (appcontrolID == L"f9uev8hsyo.Contacts")
460 || (appcontrolID == L"ph1vq2phrp.Calendar")
461 || (appcontrolID == L"vxqbrefica.Email")
462 || (appcontrolID == L"kto5jikgul.Settings")
463 || (appcontrolID == L"8r4r5ddzzn.Messages")
464 || (appcontrolID == L"dhrul6qzj3.MusicPlayer")
465 || (appcontrolID == L"smemo-efl"));
469 _AppControlImpl::Stop(void)
471 const String appcontrolID(GetAppControlProviderId());
472 SysTryReturnResult(NID_APP, IsValidAppControl(appcontrolID), E_INVALID_OPERATION, "Invalid appcontrolID(%ls)", appcontrolID.GetPointer());
474 result (*pStop)(int req) = null;
476 if (_reqId != _REQ_ID_INVALID)
478 _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
479 SysTryReturnResult(NID_APP, pInfo != null, E_INVALID_OPERATION, "Request ID %d is not found.", _reqId);
481 if (pInfo->pProvider)
483 pInfo->pProvider->StopAppControlPlugin(_reqId);
486 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(_reqId);
488 _reqId = _REQ_ID_INVALID;
492 _IAppControlPluginProvider* pProvider = GetAppControlPluginProvider(_path);
495 pProvider->StopAppControlPlugin(-1);
496 SysLog(NID_APP, "Request is stopped.");
498 pProvider->Release();
506 _AppControlImpl::GetAppName(void)
508 if (_appName.IsEmpty())
510 AppId appId = GetAppId();
511 AppId aliasAppId = _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
512 if (!aliasAppId.IsEmpty())
517 std::unique_ptr<PackageAppInfo> pInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
520 SysLog(NID_APP, "PackageInfo of appId(%ls) exists", appId.GetPointer());
521 const String& name = pInfo->GetAppName();
522 if (name == L"_AppControl")
524 // workaround for special case: requery with actual appId
525 const PackageId& packageId = _PackageManagerImpl::GetPackageIdByAppId(appId);
526 const String& defaultName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
528 const String& convertedAppId = packageId + L'.' + defaultName;
530 std::unique_ptr<PackageAppInfo> pNewInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(convertedAppId));
534 _appName = pNewInfo->GetAppDisplayName();
538 SysLog(NID_APP, "No default applicaiton information, possible database error.");
543 _appName = pInfo->GetAppDisplayName();
548 SysLog(NID_APP, "PackageInfo of appId(%ls) does not exist", appId.GetPointer());
556 _AppControlImpl::GetAppId(void) const
562 _AppControlImpl::GetAppControlProviderId(void) const
568 _AppControlImpl::GetOperationId(void) const
574 _AppControlImpl::GetCategoryListN(void) const
576 AppId appId = GetAppId();
577 SysTryReturn(NID_APP, !appId.IsEmpty(), null, E_SYSTEM, "[E_SYSTEM] Empty appId.");
579 AppId aliasAppId = _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
580 if (!aliasAppId.IsEmpty())
585 SysLog(NID_APP, "Acquiring category for app %ls.", appId.GetPointer());
587 std::unique_ptr<PackageAppInfo> pAppInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
588 SysTryReturn(NID_APP, pAppInfo.get() != null, null, E_SYSTEM, "[E_SYSTEM] Getting PackageAppInfo failed.");
590 return pAppInfo->GetAppCategoryListN();
594 _AppControlImpl::StopAppControlResponseListener(IAppControlResponseListener* pListener)
596 _AppControlManager::GetInstance()->StopAppControlResponseListener(pListener);
600 _AppControlImpl::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
602 const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
604 if (pEventArg != null)
606 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
608 if(pResponseListener != null)
610 if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_COMPLETE)
612 _AppControlManager::InvokeAppControlCompleteListener(*pResponseListener, pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData(), pEventArg->IsSubMode());
614 _AppControlResponseEvent* pResponseEvent = null;
615 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
616 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
617 delete pResponseEvent;
618 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
622 SysLog(NID_APP, "Unexpected AppControlResponseType(%d)", pEventArg->GetType());
627 SysLog(NID_APP, "Invalid ResponseListener");
632 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);