2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
19 * @file FApp_AppControlManager.cpp
20 * @brief This is the implementation for the _AppControlManager class.
25 #include <unique_ptr.h>
27 #include <appsvc/appsvc.h>
30 #include <content/mime_type.h>
32 #include <FBaseInteger.h>
33 #include <FBaseObject.h>
34 #include <FBaseString.h>
35 #include <FBaseColIListT.h>
36 #include <FBaseColArrayList.h>
37 #include <FBaseErrors.h>
38 #include <FAppAppControl.h>
39 #include <FAppAppManager.h>
40 #include <FAppIAppControlListener.h>
41 #include <FAppIAppControlResponseListener.h>
42 #include <FAppIAppFrame.h>
43 #include <FAppSqlDataControl.h>
44 #include <FAppMapDataControl.h>
45 #include <FAppPkgPackageInfo.h>
47 #include <FBaseSysLog.h>
48 #include <FBase_StringConverter.h>
49 #include <FBaseRt_LibraryImpl.h>
50 #include <FIo_DataControlResultSetImpl.h>
52 #include "FApp_AppArg.h"
53 #include "FApp_AppControlEventArg.h"
54 #include "FApp_AppControlRegistry.h"
55 #include "FApp_AppControlImpl.h"
56 #include "FApp_AppImpl.h"
57 #include "FApp_AppInfo.h"
58 #include "FApp_AppManagerEventArg.h"
60 #include "FApp_AppControlManager.h"
61 #include "FApp_AppManagerProxy.h"
62 #include "FApp_ConditionManagerProxy.h"
63 #include "FApp_IAppManagerEventListener.h"
64 #include "FApp_MapDataControlImpl.h"
65 #include "FApp_SqlDataControlImpl.h"
66 #include "FAppPkg_PackageManagerImpl.h"
67 #include "FAppPkg_PackageInfoImpl.h"
68 #include "FApp_AppMessageImpl.h"
69 #include "FApp_AppManagerImpl.h"
71 using namespace Tizen::App::Package;
72 using namespace Tizen::Base;
73 using namespace Tizen::Base::Collection;
74 using namespace Tizen::Base::Runtime;
75 using namespace Tizen::Base::Utility;
76 using namespace Tizen::Io;
78 //extern const char* _DATACONTROL_RESULTSET_DIR;
80 namespace Tizen { namespace App
83 const wchar_t TIZEN_OPERATION_PICK[] = L"http://tizen.org/appcontrol/operation/pick";
84 const wchar_t SELECTOR_NOTI_KEY[] = L"__APP_SVC_CALLER_NOTI__";
85 const int _MAX_PACKAGE_ID_LENGTH = 10;
86 const int _MAX_DATA_ARGUMENT_LENGTH = 32768; // 32KB
88 _InProcessInfo::~_InProcessInfo(void)
93 _LaunchInfo::~_LaunchInfo(void)
99 _AppControlManager::_AppControlManager(void)
103 // AppControl event handling is expected to be performed in the main thread.
104 __appControlEvent.Construct();
105 __appControlEvent.AddListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
106 __listenerList.Construct();
109 _AppControlManager::~_AppControlManager(void)
112 __appControlEvent.RemoveListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
116 _AppControlManager::GetInstance(void)
118 static _AppControlManager inst;
124 _AppControlManager::GetMimeFromExt(const String& ext, String& out)
126 std::unique_ptr<char[]> pExtension(_StringConverter::CopyToCharArrayN(ext));
127 SysTryReturnResult(NID_APP, pExtension != null, E_OUT_OF_MEMORY, "String allocation failure.");
130 mime_type_get_mime_type(pExtension.get(), &mime);
132 SysTryReturnResult(NID_APP, mime != NULL, E_UNSUPPORTED_FORMAT, "MIME type conversion failure for %ls.", ext.GetPointer());
141 _AppControlManager::OnAppControlEventReceivedN(int reqId, _AppArg* pAppArg, int res)
143 SysLog(NID_APP, "Received request Id %d, arg 0x%x", reqId, pAppArg);
146 // get launch info from request Id
147 _LaunchInfo* pInfo = __launchManager.FindItem(reqId);
148 SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with response %d", reqId,
154 if (pInfo->magic == LAUNCH_INFO_MAGIC)
156 SysLog(NID_APP, "Invoking callback 0x%x", pInfo->launchCb);
159 if (pInfo->pUserData && (!__listenerList.Contains(pInfo->pUserData)))
161 (*pInfo->launchCb)(pInfo->pUserData, pInfo->pArg, pAppArg, static_cast<service_result_e>(res), pInfo->property);
166 SysLogException(NID_APP, E_SYSTEM, "Corrupted data structure.");
171 __launchManager.RemoveItem(reqId);
175 // callback for out-of-process AppControl start event
177 _AppControlManager::OnAppControlEventReceivedN(int reqId, const AppId& appId, const String& operationId)
179 SysLog(NID_APP, "Received request Id %d, appId %ls, operationId %ls", reqId, appId.GetPointer(), operationId.GetPointer());
181 // get launch info from request Id
182 _LaunchInfo* pInfo = __launchManager.FindItem(reqId);
183 SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found.", reqId);
186 IAppControlResponseListener* pListener = static_cast<IAppControlResponseListener*>(pInfo->pUserData);
187 SysTryReturnVoidResult(NID_APP, typeid(pListener) == typeid(IAppControlResponseListener*), E_SYSTEM, "[E_SYSTEM] Invalid result callback.");
191 result r = E_SUCCESS;
192 AppId actualAppId = appId;
196 r = E_OPERATION_CANCELED;
198 SysLog(NID_APP, "Invoking callback 0x%x.", pListener);
199 pListener->OnAppControlStartResponseReceived(actualAppId, operationId, r);
203 SysLog(NID_APP, "No listener registered.");
208 // callback for in-process event handling
210 _AppControlManager::OnAppControlEventReceivedN(int reqId, int res, const IMap* pArgs)
212 SysLog(NID_APP, "Received request Id %d, args 0x%x", reqId, pArgs);
214 // process proper callback
215 _InProcessInfo* pInfo = __inAppManager.FindItem(reqId);
216 SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with args 0x%x", reqId,
219 if (pInfo->pListener)
221 String aId = pInfo->providerId;
222 String oId = pInfo->operationId;
224 SysLog(NID_APP, "Invoking callback 0x%x for (%ls, %ls).", pInfo->pListener, aId.GetPointer(), oId.GetPointer());
226 if (pInfo->property & _APPCONTROL_PROPERTY_ALIAS)
228 _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
229 pEntry = _AppControlRegistry::GetInstance()->GetReverseAppControlAliasEntry(aId, oId);
232 aId = pEntry->provider;
233 oId = pEntry->operation;
235 SysLog(NID_APP, "Legacy AppControl name (%ls, %ls).", aId.GetPointer(), oId.GetPointer());
241 IAppControlEventListener* pListener = dynamic_cast<IAppControlEventListener*>(pInfo->pListener);
244 ArrayList list(SingleObjectDeleter);
245 _AppArg::FillLegacyAppControlResult(list, res, pArgs, aId);
247 pListener->OnAppControlCompleted(aId, oId, &list);
251 SysLog(NID_APP, "Wrong AppControl listener type.");
256 IAppControlResponseListener* pListener = dynamic_cast<IAppControlResponseListener*>(pInfo->pListener);
257 if (pListener && (!__listenerList.Contains(pInfo->pListener)))
259 SysLog(NID_APP, "OSP_AC OnAppControlCompleteResponseReceived");
260 pListener->OnAppControlCompleteResponseReceived(aId, oId, static_cast<AppCtrlResult>(res), pArgs);
264 SysLog(NID_APP, "Wrong AppControl listener type.");
270 SysLogException(NID_APP, E_SYSTEM, "Invalid AppControl listener.");
273 // call TerminateAppControl
274 result (* pFunc)(int req) = null;
275 pFunc = reinterpret_cast<result (*)(int)>(pInfo->pLib->GetProcAddress(L"TerminateAppControl"));
278 (*pFunc)(pInfo->reqId);
282 SysLogException(NID_APP, E_SYSTEM, "No TerminateAppControl() function.");
285 // remove from list and unload dll
286 __inAppManager.RemoveItem(reqId);
291 _AppControlManager::SendAppControlEvent(IEventArg& arg)
293 return __appControlEvent.FireAsync(arg);
296 // generic launch callback
298 LaunchResultCb(bundle* b, int request_code, appsvc_result_val res, void* data)
300 SysLog(NID_APP, "SLP callee result: %d", res);
302 _AppControlManager* pImpl = static_cast<_AppControlManager*>(data);
308 _AppArg* pAppArg = new (std::nothrow) _AppArg;
309 SysTryReturnVoidResult(NID_APP, pAppArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
311 _AppControlEventArg* pArg = null;
312 result r = pAppArg->Construct(b);
313 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] AppControl event argument creation failure.", GetErrorMessage(r));
315 // save callee appId ASAP
316 pAppArg->SaveCalleeAppId();
318 pArg = new (std::nothrow) _AppControlEventArg(request_code, pAppArg, res);
319 SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, r, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
322 pImpl->SendAppControlEvent(*pArg);
332 _AppControlManager::SendAppControlStartResponse(int req, const char* pValue, const char* pOp)
334 _AppControlStartEventArg* pArg = new (std::nothrow) _AppControlStartEventArg(req, AppId(pValue), String(pOp));
335 SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "AppControl start event creation failure.");
337 SendAppControlEvent(*pArg);
344 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
346 bundle* kb = msg.GetBundle();
347 SysTryReturnResult(NID_APP, kb != NULL, E_OUT_OF_MEMORY, "Bundle allocation failure.");
351 appsvc_set_pkgname(kb, pkg_name);
354 appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
358 appsvc_set_mime(kb, mime);
363 appsvc_set_uri(kb, uri);
366 if (_AppImpl::GetInstance() != null)
368 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
369 _AppArg::UpdateWindowHandle(kb, handle);
372 SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
373 int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
375 result r = E_SUCCESS;
380 case APPSVC_RET_EILLACC:
381 r = E_ILLEGAL_ACCESS;
387 SysLog(NID_APP, "[%s]Launching service %s failure", GetErrorMessage(r), pkg_name);
393 _AppControlManager::Launch(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
395 bundle* kb = msg.GetBundle();
396 SysTryReturn(NID_APP, kb != NULL, -1, E_OUT_OF_MEMORY, "Bundle allocation failure.");
400 appsvc_set_pkgname(kb, pkg_name);
403 appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
407 appsvc_set_mime(kb, mime);
412 appsvc_set_uri(kb, uri);
415 if (_AppImpl::GetInstance() != null)
417 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
418 _AppArg::UpdateWindowHandle(kb, handle);
421 SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
422 int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
424 result r = E_SUCCESS;
429 case APPSVC_RET_EILLACC:
430 r = E_ILLEGAL_ACCESS;
436 SysLog(NID_APP, "[%s]Launching service %s failure", GetErrorMessage(r), pkg_name);
445 _AppControlManager::LaunchPkg(const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
449 return LaunchPkg(msg, pkg_name, op, mime, uri, pCb, data);
453 _AppControlManager::LaunchAppWithCondition(const AppId& appId, const String& condition, IList* pArrayArgs)
455 result r = E_SUCCESS;
456 _AppArg * pArg = new (std::nothrow) _AppArg();
457 SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]");
459 r = pArg->ConstructForAppLaunchCondition(condition, pArrayArgs);
460 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] ConstructForAppLaunchCondition(%ls, .. ) fails", GetErrorMessage(r), condition.GetPointer());
462 r = _AppControlManager::LaunchApp(appId, pArg);
469 _AppControlManager::LaunchApp(const AppId& appId, _AppArg* pArg, int req)
471 SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
472 SysLog(NID_APP, "AppId: %ls.", appId.GetPointer());
474 String actualAppId = appId;
475 if (appId.GetLength() == 10)
477 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
481 actualAppId.Append(L'.');
482 actualAppId.Append(name);
486 pArg->UpdateRequestId(req);
488 if (_AppImpl::GetInstance() != null)
490 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
491 pArg->UpdateWindowHandle(handle);
497 actualAppId.SubString(0, 10, tempId);
499 tempId += L"_AppControl";
501 // [INFO] Ugly solution for submode support
502 pArg->UpdateAppId(tempId);
503 kb = pArg->GetBundle();
505 bundle_raw* dataBuf = null;
507 int res = bundle_encode(kb, &dataBuf, &dataLen);
508 bundle_free_encoded_rawdata(&dataBuf);
509 SysTryReturnResult(NID_APP, res == 0, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
510 SysTryReturnResult(NID_APP, dataLen <= _MAX_DATA_ARGUMENT_LENGTH, E_MAX_EXCEEDED,
511 "The data length (%d) exceeds the maximum limit.", dataLen);
513 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
516 SysLog(NID_APP, "Submode launch successful");
520 pArg->UpdateAppId(actualAppId);
522 // retry for possible failure
524 const int TRY_COUNT = 3;
525 const int TRY_SLEEP_TIME = 65;
528 kb = pArg->GetBundle();
529 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
532 SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
536 SysLog(NID_APP, "Waiting %dth time.", count);
537 Thread::Sleep(TRY_SLEEP_TIME);
539 while (count < TRY_COUNT);
541 result r = E_SUCCESS;
544 case APPSVC_RET_EILLACC:
545 r = E_ILLEGAL_ACCESS;
552 SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
558 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
560 SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Invalid launch argument");
561 SysLog(NID_APP, "AppId: %ls.", appId.GetPointer());
563 String actualAppId = appId;
564 if (appId.GetLength() == 10)
566 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
570 actualAppId.Append(L'.');
571 actualAppId.Append(name);
575 pArg->UpdateRequestId(req);
577 if (_AppImpl::GetInstance() != null)
579 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
580 pArg->UpdateWindowHandle(handle);
586 actualAppId.SubString(0, 10, tempId);
588 tempId += L"_AppControl";
590 // [INFO] Ugly solution for submode support
591 pArg->UpdateAppId(tempId);
592 kb = pArg->GetBundle();
594 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
597 SysLog(NID_APP, "Submode launch successful");
601 pArg->UpdateAppId(actualAppId);
603 // retry for possible failure
605 const int TRY_COUNT = 3;
606 const int TRY_SLEEP_TIME = 65;
609 kb = pArg->GetBundle();
610 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
613 SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
617 SysLog(NID_APP, "Waiting %dth time.", count);
618 Thread::Sleep(TRY_SLEEP_TIME);
620 while (count < TRY_COUNT);
622 result r = E_SUCCESS;
625 case APPSVC_RET_EILLACC:
626 r = E_ILLEGAL_ACCESS;
633 SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
641 _AppControlManager::LaunchAppImplicit(_AppArg* pArg, int req)
643 SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
645 result r = E_SUCCESS;
646 bundle* kb = pArg->GetBundle();
650 pArg->UpdateRequestId(req);
651 _AppMessageImpl::AddData(kb, SELECTOR_NOTI_KEY, _AppInfo::GetApplicationId());
654 int pid = appsvc_run_service(kb, req, LaunchResultCb, this);
657 char pkgname[255] = {0, };
658 aul_app_get_pkgname_bypid(pid, pkgname, 255);
660 if (strncmp(pkgname, APP_SELECTOR, strlen(APP_SELECTOR)) != 0)
662 const char* pOperation = appsvc_get_operation(kb);
664 SysLog(NID_APP, "Starting application without selector : (%s, %s).", pkgname, pOperation);
666 SendAppControlStartResponse(req, pkgname, pOperation);
673 case APPSVC_RET_EINVAL:
676 case APPSVC_RET_ENOMATCH:
679 case APPSVC_RET_EILLACC:
680 r = E_ILLEGAL_ACCESS;
682 case APPSVC_RET_ERROR:
684 case APPSVC_RET_ELAUNCH:
692 SysLog(NID_APP, "[%s] Application(%d) launched with reqId(%d) and arg(0x%x).", GetErrorMessage(r), pid, req, pArg);
698 _AppControlManager::FinishAppControl(int reqId, int res, const IMap* pMap)
700 _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap);
701 SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
703 SendAppControlEvent(*pArg);
707 _AppControlManager::FindResultRequest(int reqId) const
709 const _ResultInfo* pInfo = __resultManager.FindItem(reqId);
710 return (pInfo) ? &(pInfo->arg) : null;
714 _AppControlManager::AddLaunchRequest(_AppArg* pArg, LaunchCbType pCb, void* pData, int prop)
716 SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Empty argument.");
718 _LaunchInfo* pItem = new (std::nothrow) _LaunchInfo(pArg, pCb, pData, prop);
719 SysTryReturn(NID_APP, pItem != null, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
721 SysLog(NID_APP, "Registering callback 0x%x, 0x%x", pCb, pData);
723 return __launchManager.InsertItem(pItem);
727 _AppControlManager::RemoveLaunchRequest(int req)
729 __launchManager.RemoveItem(req);
732 _AppControlManager::GetLaunchRequestCount(void)
734 return __launchManager.GetCount();
738 _AppControlManager::RegisterRequest(service_s* service, int& req, _AppHandler& handler)
740 bundle* b = _AppArg::GetBundleFromSvc(service);
742 _AppArg* pArg = new (std::nothrow) _AppArg();
743 SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "rrayList creation failure.");
746 result r = E_SUCCESS;
748 // ownership is transfered to RequestManager
749 _ResultInfo* pItem = new (std::nothrow) _ResultInfo(*pArg);
750 SysTryCatch(NID_APP, pItem != null, , r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
752 req = __resultManager.InsertItem(pItem);
753 SysTryCatch(NID_APP, req != -1, , r = E_INVALID_STATE, "[E_INVALID_STATE] Invalid argument handling state.");
755 handler = _AppArg::GetHandler(b);
767 _AppControlManager::IsAllowedAppControl(const wchar_t aTable[][2][64], int count, const String& aId, const String& oId)
769 for (int i = 0; i < count; i++)
771 if (aId == aTable[i][0] && oId == aTable[i][1])
773 SysLog(NID_APP, "Found entry (%ls, %ls)", aTable[i][0], aTable[i][1]);