#include <FAppSqlDataControl.h>
#include <FAppMapDataControl.h>
#include <FAppPkgPackageInfo.h>
-
+#include <FAppPkgPackageAppInfo.h>
#include <FBaseSysLog.h>
+
#include <FBase_StringConverter.h>
-#include <FBaseRt_LibraryImpl.h>
#include <FIo_DataControlResultSetImpl.h>
#include "FApp_AppArg.h"
#include "FApp_AppControlImpl.h"
#include "FApp_AppImpl.h"
#include "FApp_AppInfo.h"
-#include "FApp_AppManagerEventArg.h"
#include "FApp_Aul.h"
#include "FApp_AppControlManager.h"
#include "FApp_AppManagerProxy.h"
#include "FApp_ConditionManagerProxy.h"
-#include "FApp_IAppManagerEventListener.h"
#include "FApp_MapDataControlImpl.h"
#include "FApp_SqlDataControlImpl.h"
#include "FAppPkg_PackageManagerImpl.h"
#include "FApp_AppMessageImpl.h"
#include "FApp_AppManagerImpl.h"
#include "FApp_AppControlResponseEvent.h"
+#include "FApp_IAppControlPluginProvider.h"
+
using namespace Tizen::App::Package;
using namespace Tizen::Base;
using namespace Tizen::Base::Utility;
using namespace Tizen::Io;
-namespace
-{
-const char SELECTOR_NOTI_KEY[] = "__APP_SVC_CALLER_NOTI__";
-}
namespace Tizen { namespace App
{
-const wchar_t TIZEN_OPERATION_PICK[] = L"http://tizen.org/appcontrol/operation/pick";
+const wchar_t TIZEN_OPERATION_PICK[] = L"http://tizen.org/appcontrol/operation/pick";
+const wchar_t TIZEN_OPERATION_MAIN[] = L"http://tizen.org/appcontrol/operation/main";
+const wchar_t LEGACY_OPERATION_MAIN[] = L"osp.operation.MAIN";
+const char TIZEN_NOTIFICATION_DATA[] = "http://tizen.org/appcontrol/data/notification";
_AppControlManager::_AppControlManager(void)
{
// AppControl event handling is expected to be performed in the main thread.
__appControlEvent.Construct();
__appControlEvent.AddListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
- __listenerList.Construct();
__appControlResponseEventContainer.Construct();
__appControlResponseEventList.Construct();
}
return E_SUCCESS;
}
+
+String
+_AppControlManager::GetMimeTypeFromDataType(const String& data)
+{
+ // Data type is either MIME type or .[extension]
+
+ if (data.IsEmpty() || data[0] != L'.')
+ {
+ return data;
+ }
+
+ // .[extension]
+ String ext;
+ data.SubString(1, ext);
+
+ String res;
+ result r = _AppControlManager::GetMimeFromExt(ext, res);
+ SysTryReturn(NID_APP, !IsFailed(r), L"", r, "[%s] MIME type conversion failed for %ls.", GetErrorMessage(r), ext.GetPointer());
+
+ SysLog(NID_APP, "Conversion from %ls into %ls.", data.GetPointer(), res.GetPointer());
+ return res;
+}
+
+
void
_AppControlManager::OnAppControlEventReceivedN(int reqId, _AppArg* pAppArg, int res)
{
//_AppArg::Print(b);
// get launch info from request Id
- _LaunchInfo* pInfo = __launchManager.FindItem(reqId);
+ _DataControlInfo* pInfo = __launchManager.FindItem(reqId);
SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with response %d", reqId,
res);
SysLog(NID_APP, "Invoking callback 0x%x", pInfo->launchCb);
//pAppArg->Print();
- if (pInfo->pUserData && (!__listenerList.Contains(pInfo->pUserData)))
+ if (pInfo->pUserData)
{
(*pInfo->launchCb)(pInfo->pUserData, pInfo->pArg, pAppArg, static_cast<service_result_e>(res), pInfo->property, reqId);
}
}
-// callback for out-of-process AppControl start event
+// callback for AppControl start event
void
_AppControlManager::OnAppControlEventReceivedN(int reqId, const AppId& appId, const String& operationId)
{
SysLog(NID_APP, "Received request Id %d, app %ls, operationId %ls", reqId, appId.GetPointer(), operationId.GetPointer());
// get launch info from request Id
- _LaunchInfo* pInfo = __launchManager.FindItem(reqId);
+ _InProcessInfo* pInfo = __inAppManager.FindItem(reqId);
SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found.", reqId);
// at least listener
- IAppControlResponseListener* pListener = static_cast<IAppControlResponseListener*>(pInfo->pUserData);
- SysTryReturnVoidResult(NID_APP, typeid(pListener) == typeid(IAppControlResponseListener*), E_SYSTEM, "[E_SYSTEM] Invalid result callback.");
+ IAppControlResponseListener* pListener = dynamic_cast<IAppControlResponseListener*>(pInfo->pListener);
+ SysTryReturnVoidResult(NID_APP, pListener != null, E_SYSTEM, "[E_SYSTEM] Invalid result callback for req %d, app %ls.", reqId, appId.GetPointer());
+
+ result r = E_SUCCESS;
if (pListener)
{
- result r = E_SUCCESS;
AppId actualAppId = appId;
if (appId == L'c')
{
{
SysLog(NID_APP, "No listener registered.");
}
+
+ if (r == E_OPERATION_CANCELED)
+ {
+ SysLog(NID_APP, "Removed start listener as operation is canceled.");
+ __inAppManager.RemoveItem(reqId);
+ }
}
// callback for in-process event handling
void
-_AppControlManager::OnAppControlEventReceivedN(int reqId, int res, const IMap* pArgs, int property)
+_AppControlManager::OnAppControlPluginEventReceivedN(int reqId, int res, const AppId& optAppId, const String& optOperation, const IMap* pArgs, int property)
{
SysLog(NID_APP, "Received request Id %d, res %d, args 0x%x", reqId, res, pArgs);
SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with args 0x%x", reqId,
pArgs);
- if (pInfo->pListener && (!__listenerList.Contains(pInfo->pListener)))
+ if (pInfo->pListener)
{
- String aId = pInfo->providerId;
- String oId = pInfo->operationId;
+ String aId;
+ String oId;
- SysLog(NID_APP, "Invoking callback 0x%x for (%ls, %ls).", pInfo->pListener, aId.GetPointer(), oId.GetPointer());
-
- if (pInfo->property & _APPCONTROL_PROPERTY_ALIAS)
+ if (optAppId.IsEmpty())
{
- const _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
- pEntry = _AppControlRegistry::GetInstance()->GetReverseAppControlAliasEntry(aId, oId);
- if (pEntry)
- {
- aId = pEntry->provider;
- oId = pEntry->operation;
+ aId = pInfo->providerId;
+ oId = pInfo->operationId;
+ }
+ else
+ {
+ // implicit launch only
+ aId = optAppId;
+ oId = optOperation;
- SysLog(NID_APP, "Legacy AppControl (%ls, %ls).", aId.GetPointer(), oId.GetPointer());
- }
+ SysLog(NID_APP, "Changing appId/operation for implicit launch.");
}
+ SysLog(NID_APP, "Invoking callback 0x%x for (%ls, %ls).", pInfo->pListener, aId.GetPointer(), oId.GetPointer());
+
const bool isSubMode = (property & _APPCONTROL_PROPERTY_SUBMODE);
const bool isServiceCallee = (property & _APPCONTROL_PROPERTY_SERVICE_CALLEE);
SysLogException(NID_APP, E_SYSTEM, "Invalid AppControl listener.");
}
- // call TerminateAppControl
- result (* pFunc)(int req) = null;
- pFunc = reinterpret_cast<result (*)(int)>(pInfo->pLib->GetProcAddress(L"TerminateAppControl"));
- if (pFunc)
- {
- (*pFunc)(pInfo->reqId);
- }
- else
- {
- SysLogException(NID_APP, E_SYSTEM, "No TerminateAppControl() function.");
- }
// remove from list and unload dll
__inAppManager.RemoveItem(reqId);
}
+static bool
+IsMatchingProcListener(const _InProcessInfo& info, IEventListener* pListener)
+{
+ return (info.pListener == pListener);
+}
+
+
+void
+_AppControlManager::StopAppControlResponseListener(IAppControlResponseListener* pListener)
+{
+ // __inAppManager, __launchManager
+ _InProcessInfo* pProcInfo = __inAppManager.FindItemWithListener(IsMatchingProcListener, pListener);
+ if (pProcInfo)
+ {
+ __inAppManager.RemoveItem(pProcInfo);
+ SysLog(NID_APP, "Listener 0x%x is removed from in-process stub list.", pListener);
+ }
+}
+
+
// generic launch callback
static void
LaunchResultCb(bundle* b, int request_code, appsvc_result_val res, void* data)
_AppControlManager::LaunchPkg(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
{
bundle* kb = msg.GetBundle();
- SysTryReturnResult(NID_APP, kb != NULL, E_OUT_OF_MEMORY, "Bundle allocation failure.");
if (pkg_name)
{
appsvc_set_uri(kb, uri);
}
- if (_AppImpl::GetInstance() != null)
- {
- const long handle = _AppImpl::GetInstance()->GetWindowHandle();
- _AppArg::UpdateWindowHandle(kb, handle);
- }
-
- SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
- int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
+ int pid = LaunchPkg(msg, pCb, data);
result r = E_SUCCESS;
if (pid < 0)
{
- switch (pid)
- {
- case APPSVC_RET_EILLACC:
- r = E_ILLEGAL_ACCESS;
- break;
- case APPSVC_RET_EINVAL:
- r = E_MAX_EXCEEDED;
- break;
- default:
- r = E_SYSTEM;
- break;
- }
- SysLog(NID_APP, "[%s] Launching service %s failure", GetErrorMessage(r), pkg_name);
+ r = GetLastResult();
}
return r;
int
-_AppControlManager::LaunchPkg(_AppMessageImpl& msg, const AppId& appId, const String& opId, const String* pUri, const String* pMime, AppSvcResFn pCb, void* data)
+_AppControlManager::LaunchPkg(_AppMessageImpl& msg, AppSvcResFn pCb, void* data)
{
- std::unique_ptr<char[]> pPackage(_StringConverter::CopyToCharArrayN(appId));
- std::unique_ptr<char[]> pOperation(_StringConverter::CopyToCharArrayN(opId));
+ bundle* kb = msg.GetBundle();
+ SysTryReturn(NID_APP, kb != NULL, -1, E_OUT_OF_MEMORY, "Bundle allocation failure.");
- const char* pUriData = null;
- if (pUri)
+ if (_AppImpl::GetInstance() != null)
{
- pUriData = _StringConverter::CopyToCharArrayN(*pUri);
+ const long handle = _AppImpl::GetInstance()->GetWindowHandle();
+ _AppArg::UpdateWindowHandle(kb, handle);
}
- const char* pMimeData = null;
- if (pMime)
+ int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
+
+ result r = E_SUCCESS;
+ if (pid < 0)
{
- pMimeData = _StringConverter::CopyToCharArrayN(*pMime);
+ switch (pid)
+ {
+ case APPSVC_RET_EILLACC:
+ r = E_ILLEGAL_ACCESS;
+ break;
+ case APPSVC_RET_EINVAL:
+ r = E_MAX_EXCEEDED;
+ break;
+ default:
+ r = E_SYSTEM;
+ break;
+ }
+ SysLog(NID_APP, "[%s] Launching service %s failure", GetErrorMessage(r), appsvc_get_appid(kb));
}
-
- int pid = Launch(msg, pPackage.get(), pOperation.get(), pMimeData, pUriData, pCb, data);
-
- delete [] pUriData;
- delete [] pMimeData;
+ SetLastResult(r);
return pid;
}
result
-_AppControlManager::LaunchPkg(const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
-{
- _AppMessageImpl msg;
-
- return LaunchPkg(msg, pkg_name, op, mime, uri, pCb, data);
-}
-
-result
-_AppControlManager::LaunchAppWithCondition(const AppId& appId, const String& condition, IList* pArrayArgs)
-{
- result r = E_SUCCESS;
- _AppArg * pArg = new (std::nothrow) _AppArg();
- SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]");
-
- r = pArg->ConstructForAppLaunchCondition(condition, pArrayArgs);
- SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] ConstructForAppLaunchCondition(%ls, .. ) fails", GetErrorMessage(r), condition.GetPointer());
-
- r = _AppControlManager::LaunchApp(appId, pArg);
-CATCH:
- delete pArg;
- return r;
-}
-
-result
_AppControlManager::LaunchApp(const AppId& appId, _AppArg* pArg, int req)
{
SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
SysLog(NID_APP, "App: %ls.", appId.GetPointer());
String actualAppId = appId;
+#if 0
+ // This logic is only for very old legacy code to support "pkgid" launch and should be removed
if (appId.GetLength() == 10)
{
const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
actualAppId.Append(name);
}
}
+#endif
pArg->UpdateRequestId(req);
int pid = -1;
bundle* kb = NULL;
- String tempId;
- actualAppId.SubString(0, 10, tempId);
- tempId += L'.';
- tempId += L"_AppControl";
-
- // [INFO] Ugly solution for submode support
- pArg->UpdateAppId(tempId);
- kb = pArg->GetBundle();
-
- pid = appsvc_run_service(kb, req, LaunchResultCb, this);
- if (pid >= 0)
- {
- SysLog(NID_APP, "Submode launch successful");
- return E_SUCCESS;
- }
- else if (pid == APPSVC_RET_EINVAL)
+
+ std::unique_ptr< PackageAppInfo > pAppInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
+ SysTryReturn(NID_APP, pAppInfo != null, E_SYSTEM, GetLastResult(), "[%s] Getting AppInfo failed.", GetErrorMessage(GetLastResult()));
+ _PackageAppInfoImpl* pAppInfoImpl = _PackageAppInfoImpl::GetInstance(pAppInfo.get());
+ SysTryReturnResult(NID_APP, pAppInfoImpl != null , E_SYSTEM, "Severe system error");
+
+ if (pAppInfoImpl->IsServiceApp() == false)
{
- SysLog(NID_APP, "Argument overflow");
- return E_MAX_EXCEEDED;
+ String tempId;
+ actualAppId.SubString(0, 10, tempId);
+ tempId += L'.';
+ tempId += String(SUBMODE_NAME);
+
+ // [INFO] Ugly solution for submode support
+ pArg->UpdateAppId(tempId);
+ kb = pArg->GetBundle();
+
+ pid = appsvc_run_service(kb, req, LaunchResultCb, this);
+ if (pid >= 0)
+ {
+ SysLog(NID_APP, "Submode launch successful");
+ return E_SUCCESS;
+ }
+ else if (pid == APPSVC_RET_EINVAL)
+ {
+ SysLog(NID_APP, "Argument overflow");
+ return E_MAX_EXCEEDED;
+ }
}
pArg->UpdateAppId(actualAppId);
int
-_AppControlManager::Launch(const _AppMessageImpl& msg, const AppId& aId, const String& oId, const String* pUriData, const String* pMimeType, AppSvcResFn pCb, void* pData)
+_AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
{
- SysLog(NID_APP, "Enter");
-
- _AppArg arg;
- arg.Construct(msg, oId, pUriData, pMimeType);
-
- int pid = Launch(aId, &arg, pCb, pData, -1);
- SysTryReturn(NID_APP, pid >= 0, -1, GetLastResult(), "Launching(%ls) is failed", aId.GetPointer());
-
- SysLog(NID_APP, "Exit");
-
- return pid;
+ return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
}
int
-_AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
+_AppControlManager::Launch(const _AppMessageImpl& msg, AppSvcResFn pCb, void* pData, int req)
{
- return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
+ const bundle* pBundle = msg.GetBundle();
+
+ _AppArg arg;
+ arg.Construct(pBundle);
+
+ return Launch(_AppMessageImpl::GetApplicationId(pBundle), &arg, pCb, pData, req);
}
SysLog(NID_APP, "App: %ls.", appId.GetPointer());
String actualAppId = appId;
-#if 0
- if (appId.GetLength() == 10)
- {
- const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
-
- if (!execName.IsEmpty())
- {
- actualAppId.Append(L'.');
- actualAppId.Append(execName);
- }
- }
-#endif
pArg->UpdateRequestId(req);
if ((!(type & _APP_TYPE_SERVICE_APP)) && _IsDefaultApplication(tempId, appId))
{
tempId += L'.';
- tempId += L"_AppControl";
+ tempId += String(SUBMODE_NAME);
// [INFO] Ugly solution for submode support
pArg->UpdateAppId(tempId);
return pid;
}
-result
-_AppControlManager::LaunchAppImplicit(_AppArg* pArg, int req)
-{
- SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
-
- result r = E_SUCCESS;
- bundle* kb = pArg->GetBundle();
-
- if (req >= 0)
- {
- pArg->UpdateRequestId(req);
- appsvc_add_data(kb, SELECTOR_NOTI_KEY, appinfo_get_appid());
- }
-
- if (_AppImpl::GetInstance() != null)
- {
- const long handle = _AppImpl::GetInstance()->GetWindowHandle();
- _AppArg::UpdateWindowHandle(kb, handle);
- }
-
- int pid = appsvc_run_service(kb, req, LaunchResultCb, this);
- if (pid >= 0)
- {
- if (pid == 0)
- {
- SysLog(NID_APP, "Sending local process again.");
- pid = getpid();
- }
-
- char pkgname[255] = {0, };
- if (aul_app_get_pkgname_bypid(pid, pkgname, 255) != AUL_R_OK)
- {
- SysLog(NID_APP, "Fail to get package name by pid : (%d).", pid);
- return E_SYSTEM;
- }
-
- if (strncmp(pkgname, APP_SELECTOR, strlen(APP_SELECTOR)) != 0)
- {
- const char* pOperation = appsvc_get_operation(kb);
-
- SysLog(NID_APP, "Starting application without selector : (%s, %s).", pkgname, pOperation);
-
- SendAppControlStartResponse(req, pkgname, pOperation);
- }
- }
- else
- {
- switch (pid)
- {
- case APPSVC_RET_EINVAL:
- r = E_OBJ_NOT_FOUND;
- break;
- case APPSVC_RET_ENOMATCH:
- r = E_OBJ_NOT_FOUND;
- break;
- case APPSVC_RET_EILLACC:
- r = E_ILLEGAL_ACCESS;
- break;
- case APPSVC_RET_ERROR:
- // fall through
- case APPSVC_RET_ELAUNCH:
- // fall through
- default:
- r = E_SYSTEM;
- break;
- }
- }
-
- SysLog(NID_APP, "[%s] Application(%d) launched with reqId(%d) and arg(0x%x).", GetErrorMessage(r), pid, req, pArg);
-
- return r;
-}
void
_AppControlManager::FinishAppControl(int reqId, int res, IMap* pMap)
SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
SendAppControlEvent(*pArg);
- SysLog(NID_APP, "Exit.");
}
+
+ void
+_AppControlManager::FinishAppControl(int reqId, int res, const AppId& appId, const String& oId, IMap* pMap, int prop)
+{
+ SysLog(NID_APP, "req %d, res %d, appId(%ls), oId(%ls).", reqId, res, appId.GetPointer(), oId.GetPointer());
+ _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, appId, oId, pMap, prop);
+ SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
+
+ SendAppControlEvent(*pArg);
+}
+
+
void
_AppControlManager::RemoveResultRequest(int reqId)
{
{
SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Empty argument.");
- _LaunchInfo* pItem = new (std::nothrow) _LaunchInfo(pArg, pCb, pData, prop);
+ _DataControlInfo* pItem = new (std::nothrow) _DataControlInfo(pArg, pCb, pData, prop);
SysTryReturn(NID_APP, pItem != null, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
SysLog(NID_APP, "Registering callback 0x%x, 0x%x", pCb, pData);
}
-bool
-_AppControlManager::IsAllowedAppControl(const char aTable[][2][96], int count, const String& aId, const String& oId)
-{
- for (int i = 0; i < count; i++)
- {
- if (aId == aTable[i][0] && oId == aTable[i][1])
- {
- SysLog(NID_APP, "Found entry (%s, %s)", aTable[i][0], aTable[i][1]);
- return true;
- }
- }
-
- return false;
-}
-
-
AppCtrlResult
_AppControlManager::ConvertAppControlResultCode(int resCode)
{
}
}
-AppId
-_AppControlManager::GetAliasAppId(const AppId& appId)
-{
- return _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
-}
-
}} // Tizen::App