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 const wchar_t ACTL_IMPLICIT_PLUGIN[] = L"libosp-ac-implicit.so";
60 const wchar_t TIZEN_ALIAS_APPID_PREFIX[] = L"tizen.";
64 namespace Tizen { namespace App
67 _AppControlImpl::_AppControlImpl(const AppControl& value)
69 , _reqId(APPCONTROL_REQUEST_ID_INVALID)
70 , _property(_APPCONTROL_PROPERTY_NONE)
71 , _processId(APPCONTROL_REQUEST_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.");
108 String actualAppId = aId;
109 if (aId.StartsWith(TIZEN_ALIAS_APPID_PREFIX, 0))
111 // little bit of performance tweak
112 actualAppId = _AppControlRegistry::GetInstance()->GetAliasAppId(aId);
115 const bool isInstalled = _Aul::IsInstalled(actualAppId);
116 SysTryReturn(NID_APP, isInstalled, null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] %ls not installed.", actualAppId.GetPointer());
119 AppControl* pAc = new (std::nothrow) AppControl;
120 SysTryReturn(NID_APP, pAc != null, null, E_OUT_OF_MEMORY, "AppControl allocation failure.");
122 _AppControlImpl* pImpl = pAc->__pAppControlImpl;
123 SysTryReturn(NID_APP, pImpl != null, null, E_OUT_OF_MEMORY, "AppControlImpl instance must not be null.");
127 pImpl->_opId = (oId.IsEmpty()) ? TIZEN_OPERATION_MAIN : oId;
128 pImpl->_property = prop;
134 _IAppControlPluginProvider*
135 _AppControlImpl::GetAppControlPluginProvider(const String& path)
138 lib.Construct(path, _LIBRARY_OPTION);
140 APP_CONTROL_PROVIDER_GET_FN pProvider = reinterpret_cast<APP_CONTROL_PROVIDER_GET_FN>(lib.GetProcAddress(L"GetAppControlProviderPlugin"));
144 SysLogException(NID_APP, E_SYSTEM, "Cannot load plugin properly for %ls.", path.GetPointer());
148 return (*pProvider)();
153 _AppControlImpl::FindAndStart(const String& operationId, const String* pUriPattern, const String* pDataType, const String* pCategory, const IMap* pExtraData, IAppControlResponseListener* pListener)
155 // [FIXME] valid argument size checking required
156 SysLog(NID_APP, "Enter");
158 std::unique_ptr<bundle, BundleDeleter> pBundle(bundle_create());
159 SysTryReturnResult(NID_APP, pBundle.get(), E_OUT_OF_MEMORY, "Bundle creation failure.");
161 _AppMessageImpl::SetOperation(pBundle.get(), operationId);
165 _AppMessageImpl::SetUri(pBundle.get(), *pUriPattern);
170 const String& mimeType = _AppControlManager::GetMimeTypeFromDataType(*pDataType);
172 _AppMessageImpl::SetMime(pBundle.get(), mimeType);
177 _AppMessageImpl::SetCategory(pBundle.get(), *pCategory);
180 return StartImplicit(pBundle.get(), pExtraData, pListener);
185 _AppControlImpl::StartImplicit(const _AppMessageImpl& msg, IEventListener* pListener, bool isLegacy)
187 SysLog(NID_APP, "Enter");
188 int req = APPCONTROL_REQUEST_ID_INVALID;
190 _IAppControlPluginProvider* pProvider = GetAppControlPluginProvider(ACTL_IMPLICIT_PLUGIN);
191 if (pProvider == null)
193 SysPropagate(NID_APP, E_OBJ_NOT_FOUND);
194 return E_OBJ_NOT_FOUND;
199 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(isLegacy, pProvider, pListener);
202 req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
206 result r = InvokeStartAppControl(pProvider, req, L"", msg);
208 if (pListener == null)
210 pProvider->Release();
213 // after acquring request number, pLib should be managed from the list, not CATCH
216 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
217 SysLog(NID_APP, "[%s] A system error has occurred.", GetErrorMessage(r));
222 SysLog(NID_APP, "Exit %d", req);
228 _AppControlImpl::StartImplicit(bundle* pBundle, const IList* pDataList, IAppControlEventListener* pListener)
230 _AppMessageImpl msg(pBundle);
231 msg.AddData(pDataList);
233 return StartImplicit(msg, pListener, true);
238 _AppControlImpl::StartImplicit(bundle* pBundle, const IMap* pData, IAppControlResponseListener* pListener)
240 _AppMessageImpl msg(pBundle);
241 _AppArg::AddStrMap(msg.GetBundle(), pData);
243 return StartImplicit(msg, pListener, false);
248 _AppControlImpl::Start(const IList* pDataList, IAppControlEventListener* pListener)
250 SysLog(NID_APP, "Enter");
251 _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
252 SysTryReturnResult(NID_APP, pInfo == null, E_IN_PROGRESS, "Request ID %d is already in progress.", _reqId);
254 int req = APPCONTROL_REQUEST_ID_INVALID;
256 _IAppControlPluginProvider* pProvider = GetAppControlPluginProvider(_path);
257 if (pProvider == null)
259 SysPropagate(NID_APP, E_OBJ_NOT_FOUND);
260 return E_OBJ_NOT_FOUND;
265 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(_appId, _opId, _property, true, pProvider, pListener);
268 req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
272 result r = InvokeStartAppControl(pProvider, req, _appId, _opId, pDataList);
274 if (pListener == null)
276 pProvider->Release();
281 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
282 SysLog(NID_APP, "[%s] A system error has occurred.", GetErrorMessage(r));
289 SysLog(NID_APP, "Exit %d", req);
294 _AppControlImpl::Start(const String* pUriData, const String* pMimeType, const IMap* pDataList, IAppControlResponseListener* pListener)
296 SysLog(NID_APP, "Enter");
297 _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
298 SysTryReturnResult(NID_APP, pInfo == null, E_IN_PROGRESS, "Request ID %d is already in progress.", _reqId);
300 int req = APPCONTROL_REQUEST_ID_INVALID;
301 result r = E_SUCCESS;
303 _IAppControlPluginProvider* pProvider = GetAppControlPluginProvider(_path);
304 if (pProvider == null)
306 SysPropagate(NID_APP, E_OBJ_NOT_FOUND);
307 return E_OBJ_NOT_FOUND;
312 _InProcessInfo* pItem = new (std::nothrow) _InProcessInfo(_appId, _opId, _property, false, pProvider, pListener);
315 req = _AppControlManager::GetInstance()->__inAppManager.InsertItem(pItem);
318 const _ThreadImpl* pThreadImpl = _ThreadImpl::GetCurrentThreadImpl();
319 if (pThreadImpl && pThreadImpl->GetThreadType() == THREAD_TYPE_EVENT_DRIVEN)
321 _AppControlResponseEvent* pAppControlResponseEvent = new (std::nothrow) _AppControlResponseEvent();
323 if (pAppControlResponseEvent != null)
325 r = pAppControlResponseEvent->Construct();
326 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::Construct() is failed", GetErrorMessage(r));
328 r = pAppControlResponseEvent->AddListener(*this, true);
329 SysTryLog(NID_APP, r == E_SUCCESS, "[%s]_AppControlResponseEvent::AddListener() is failed", GetErrorMessage(r));
331 IMapT<int, _AppControlResponseEvent*>* pResponseEventContainer = _AppControlManager::GetInstance()->GetAppControlResponseEventContainer();
332 if (pResponseEventContainer != null)
334 int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + req;
335 pResponseEventContainer->Add(responseEventRequestId, pAppControlResponseEvent);
336 __appControlResponseEventList.Add(responseEventRequestId);
337 SysLog(NID_APP, "pResponseEvent gets added. reqId(%d)", responseEventRequestId);
342 r = InvokeStartAppControl(pProvider, req, _appId, _opId, pUriData, pMimeType, pDataList);
344 if (pListener == null)
346 pProvider->Release();
351 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(req);
352 SysLog(NID_APP, "[%s] A system error has occurred.", GetErrorMessage(r));
358 SysLog(NID_APP, "Exit %d", req);
364 _AppControlImpl::InvokeStartAppControl(_IAppControlPluginProvider* pProvider, int req, const String& appId, const String& oId, const IList* pList)
366 SysLog(NID_APP, "Legacy stuff for converting argument");
368 HashMap map(SingleObjectDeleter);
369 HashMap* pMap = null;
374 _AppArg::FillMapFromList(&map, pList);
379 return InvokeStartAppControl(pProvider, req, appId, oId, null, null, pMap);
384 _AppControlImpl::InvokeStartAppControl(_IAppControlPluginProvider* pProvider, int req, const String& appId, const String& oId, const String* pUri, const String* pMime, const IMap* pMap)
390 data = _AppControlManager::GetMimeTypeFromDataType(*pMime);
393 _AppMessageImpl msg(appId, oId, pUri, &data, pMap);
395 return InvokeStartAppControl(pProvider, req, appId, msg);
400 _AppControlImpl::InvokeStartAppControl(_IAppControlPluginProvider* pProvider, int req, const String& appId, const _AppMessageImpl& message)
402 SysTryReturnResult(NID_APP, pProvider != null, E_SYSTEM, "Wrong AppControl provider plugin for %ls(%d).", appId.GetPointer(), req);
404 return pProvider->StartAppControlPlugin(req, appId, message, null);
409 _AppControlImpl::Stop(void)
411 result r = E_SUCCESS;
412 result (*pStop)(int req) = null;
414 if (_reqId != APPCONTROL_REQUEST_ID_INVALID)
416 _InProcessInfo* pInfo = _AppControlManager::GetInstance()->__inAppManager.FindItem(_reqId);
417 SysTryReturnResult(NID_APP, pInfo != null, E_INVALID_OPERATION, "Request ID %d is not found.", _reqId);
419 if (pInfo->pProvider)
421 r = pInfo->pProvider->StopAppControlPlugin(_reqId);
424 _AppControlManager::GetInstance()->__inAppManager.RemoveItem(_reqId);
426 _reqId = APPCONTROL_REQUEST_ID_INVALID;
430 _IAppControlPluginProvider* pProvider = GetAppControlPluginProvider(_path);
433 r = pProvider->StopAppControlPlugin(-1);
435 pProvider->Release();
439 SysLog(NID_APP, "[%s] Request is stopped.", GetErrorMessage(r));
445 _AppControlImpl::GetAppName(void) const
447 if (_appName.IsEmpty())
449 AppId appId = GetAppId();
450 const AppId& aliasAppId = _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
451 if (!aliasAppId.IsEmpty())
456 appId = _Aul::GetRealAppId(appId);
458 std::unique_ptr<PackageAppInfo> pInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
461 SysLog(NID_APP, "PackageInfo of [%ls] exists.", appId.GetPointer());
462 _appName = pInfo->GetAppDisplayName();
466 SysLog(NID_APP, "PackageInfo of [%ls] does not exist.", appId.GetPointer());
475 _AppControlImpl::GetCategoryListN(void) const
477 AppId appId = GetAppId();
478 SysTryReturn(NID_APP, !appId.IsEmpty(), null, E_SYSTEM, "[E_SYSTEM] Empty appId.");
480 const AppId& aliasAppId = _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
481 if (!aliasAppId.IsEmpty())
486 SysLog(NID_APP, "Acquiring category for app %ls.", appId.GetPointer());
488 std::unique_ptr<PackageAppInfo> pAppInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
489 SysTryReturn(NID_APP, pAppInfo.get() != null, null, E_SYSTEM, "[E_SYSTEM] Getting PackageAppInfo failed.");
491 return pAppInfo->GetAppCategoryListN();
495 _AppControlImpl::StopAppControlResponseListener(IAppControlResponseListener* pListener)
497 _AppControlManager::GetInstance()->StopAppControlResponseListener(pListener);
501 _AppControlImpl::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
503 const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
505 if (pEventArg != null)
507 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
509 if(pResponseListener != null)
511 if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_COMPLETE)
513 _AppControlManager::InvokeAppControlCompleteListener(*pResponseListener, pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData(), pEventArg->IsSubMode());
515 _AppControlResponseEvent* pResponseEvent = null;
516 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
517 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
518 delete pResponseEvent;
519 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
523 SysLog(NID_APP, "Unexpected AppControlResponseType(%d)", pEventArg->GetType());
528 SysLog(NID_APP, "Invalid ResponseListener");
533 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);