N_SE-36002 : fix submode for implicit resolution
[platform/framework/native/appfw.git] / src / app / FApp_AppControlManager.cpp
index de50e3f..79ea317 100755 (executable)
@@ -67,6 +67,7 @@
 #include "FAppPkg_PackageInfoImpl.h"
 #include "FApp_AppMessageImpl.h"
 #include "FApp_AppManagerImpl.h"
+#include "FApp_AppControlResponseEvent.h"
 
 using namespace Tizen::App::Package;
 using namespace Tizen::Base;
@@ -75,8 +76,6 @@ using namespace Tizen::Base::Runtime;
 using namespace Tizen::Base::Utility;
 using namespace Tizen::Io;
 
-//extern const char* _DATACONTROL_RESULTSET_DIR;
-
 namespace Tizen { namespace App
 {
 
@@ -103,12 +102,36 @@ _AppControlManager::_AppControlManager(void)
        __appControlEvent.Construct();
        __appControlEvent.AddListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
        __listenerList.Construct();
+       __pAppControlResponseEventContainer = new (std::nothrow)HashMapT<int, _AppControlResponseEvent*>;
+       __pAppControlResponseEventContainer->Construct();
+       __appControlResponseEventList.Construct();
 }
 
 _AppControlManager::~_AppControlManager(void)
 {
        SysLog(NID_APP, "");
        __appControlEvent.RemoveListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
+       IEnumeratorT<int>* pEnum = __appControlResponseEventList.GetEnumeratorN();
+
+       if (pEnum != null)
+       {
+               while(pEnum->MoveNext() == E_SUCCESS)
+               {
+                       int reqId;
+                       pEnum->GetCurrent(reqId);
+                       if (__pAppControlResponseEventContainer != null)
+                       {
+                               _AppControlResponseEvent* pResponseEvent = null;
+                               __pAppControlResponseEventContainer->GetValue(reqId, pResponseEvent);
+                               delete pResponseEvent;
+
+                               __pAppControlResponseEventContainer->Remove(reqId);
+                               SysLog(NID_APP, "pResponseEvent gets deleted. reqId(%d)", reqId);
+                       }
+               }
+       }
+       delete __pAppControlResponseEventContainer;
+       delete pEnum;
 }
 
 _AppControlManager*
@@ -157,7 +180,7 @@ _AppControlManager::OnAppControlEventReceivedN(int reqId, _AppArg* pAppArg, int
 
                        if (pInfo->pUserData && (!__listenerList.Contains(pInfo->pUserData)))
                        {
-                               (*pInfo->launchCb)(pInfo->pUserData, pInfo->pArg, pAppArg, static_cast<service_result_e>(res), pInfo->property);
+                               (*pInfo->launchCb)(pInfo->pUserData, pInfo->pArg, pAppArg, static_cast<service_result_e>(res), pInfo->property, reqId);
                        }
                }
                else
@@ -175,7 +198,7 @@ _AppControlManager::OnAppControlEventReceivedN(int reqId, _AppArg* pAppArg, int
 void
 _AppControlManager::OnAppControlEventReceivedN(int reqId, const AppId& appId, const String& operationId)
 {
-       SysLog(NID_APP, "Received request Id %d, appId %ls, operationId %ls", reqId, appId.GetPointer(), operationId.GetPointer());
+       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);
@@ -195,7 +218,26 @@ _AppControlManager::OnAppControlEventReceivedN(int reqId, const AppId& appId, co
                        r = E_OPERATION_CANCELED;
                }
                SysLog(NID_APP, "Invoking callback 0x%x.", pListener);
-               pListener->OnAppControlStartResponseReceived(actualAppId, operationId, r);
+
+               _AppControlResponseEvent* pResponseEvent = null;
+               __pAppControlResponseEventContainer->GetValue(reqId, pResponseEvent);
+               SysLog(NID_APP, "StartResponseReceived Request Id(%d), ResponseEvent 0x%x.", reqId, pResponseEvent);
+               if (pResponseEvent != null)
+               {
+                       String oId(operationId);
+                       _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_START, actualAppId, oId, r, APP_CTRL_RESULT_SUCCEEDED, null, reqId);
+
+                       if (pResponseEventArg != null)
+                       {
+                               pResponseEvent->Fire(*pResponseEventArg);
+                               SysLog(NID_APP, "pResponseEvent is Fired");
+                       }
+               }
+               else
+               {
+                       pListener->OnAppControlStartResponseReceived(actualAppId, operationId, r);
+                       SysLog(NID_APP, "OnAppControlStartResponseReceived called directly");
+               }
        }
        else
        {
@@ -208,7 +250,7 @@ _AppControlManager::OnAppControlEventReceivedN(int reqId, const AppId& appId, co
 void
 _AppControlManager::OnAppControlEventReceivedN(int reqId, int res, const IMap* pArgs)
 {
-       SysLog(NID_APP, "Received request Id %d, args 0x%x", reqId, pArgs);
+       SysLog(NID_APP, "Received request Id %d, res %d, args 0x%x", reqId, res, pArgs);
 
        // process proper callback
        _InProcessInfo* pInfo = __inAppManager.FindItem(reqId);
@@ -224,7 +266,7 @@ _AppControlManager::OnAppControlEventReceivedN(int reqId, int res, const IMap* p
 
                if (pInfo->property & _APPCONTROL_PROPERTY_ALIAS)
                {
-                       _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
+                       const _AppControlRegistry::_AppControlAliasEntry* pEntry = null;
                        pEntry = _AppControlRegistry::GetInstance()->GetReverseAppControlAliasEntry(aId, oId);
                        if (pEntry)
                        {
@@ -255,8 +297,26 @@ _AppControlManager::OnAppControlEventReceivedN(int reqId, int res, const IMap* p
                        IAppControlResponseListener* pListener = dynamic_cast<IAppControlResponseListener*>(pInfo->pListener);
                        if (pListener && (!__listenerList.Contains(pInfo->pListener)))
                        {
-                               SysLog(NID_APP, "OSP_AC OnAppControlCompleteResponseReceived");
-                               pListener->OnAppControlCompleteResponseReceived(aId, oId, static_cast<AppCtrlResult>(res), pArgs);
+                               _AppControlResponseEvent* pResponseEvent = null;
+                               int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + reqId;
+                               __pAppControlResponseEventContainer->GetValue(responseEventRequestId, pResponseEvent);
+
+                               if (pResponseEvent != null)
+                               {
+                                       _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_COMPLETE, aId, oId, E_SUCCESS, static_cast<AppCtrlResult>(res), const_cast<IMap*> (pArgs), responseEventRequestId);
+                                       if (pResponseEventArg != null)
+                                       {
+                                               pResponseEvent->Fire(*pResponseEventArg);
+                                               SysLog(NID_APP, "pResponseEvent is Fired");
+                                       }
+                               }
+                               else
+                               {
+                                       pListener->OnAppControlCompleteResponseReceived(aId, oId, ConvertAppControlResultCode(res), pArgs);
+                                       SysLog(NID_APP, "OnAppControlCompleteResponseReceived called directly");
+                                       IMap* pMap = const_cast<IMap*> (pArgs);
+                                       delete pMap;
+                               }
                        }
                        else
                        {
@@ -292,6 +352,13 @@ _AppControlManager::SendAppControlEvent(IEventArg& arg)
        return __appControlEvent.FireAsync(arg);
 }
 
+Tizen::Base::Collection::IMapT<int,_AppControlResponseEvent*>*
+_AppControlManager::GetAppControlResponseEventContainer(void)
+{
+       return __pAppControlResponseEventContainer;
+}
+
+
 // generic launch callback
 static void
 LaunchResultCb(bundle* b, int request_code, appsvc_result_val res, void* data)
@@ -311,9 +378,6 @@ LaunchResultCb(bundle* b, int request_code, appsvc_result_val res, void* data)
        result r = pAppArg->Construct(b);
        SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] AppControl event argument creation failure.", GetErrorMessage(r));
 
-       // save callee appId ASAP
-       pAppArg->SaveCalleeAppId();
-
        pArg = new (std::nothrow) _AppControlEventArg(request_code, pAppArg, res);
        SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, r, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
 
@@ -388,6 +452,8 @@ _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const char* pkg_name, const
 
        return r;
 }
+
+
 int
 _AppControlManager::Launch(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
 {
@@ -440,6 +506,33 @@ _AppControlManager::Launch(_AppMessageImpl& msg, const char* pkg_name, const cha
 }
 
 
+int
+_AppControlManager::LaunchPkg(_AppMessageImpl& msg, const AppId& appId, const String& opId, const String* pUri, const String* pMime, AppSvcResFn pCb, void* data)
+{
+       std::unique_ptr<char[]> pPackage(_StringConverter::CopyToCharArrayN(appId));
+       std::unique_ptr<char[]> pOperation(_StringConverter::CopyToCharArrayN(opId));
+
+       const char* pUriData = null;
+       if (pUri)
+       {
+               pUriData =  _StringConverter::CopyToCharArrayN(*pUri);
+       }
+
+       const char* pMimeData = null;
+       if (pMime)
+       {
+               pMimeData = _StringConverter::CopyToCharArrayN(*pMime);
+       }
+
+       int pid = Launch(msg, pPackage.get(), pOperation.get(), pMimeData, pUriData, pCb, data);
+
+       delete [] pUriData;
+       delete [] pMimeData;
+
+       return pid;
+}
+
+
 result
 _AppControlManager::LaunchPkg(const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
 {
@@ -468,7 +561,7 @@ result
 _AppControlManager::LaunchApp(const AppId& appId, _AppArg* pArg, int req)
 {
        SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
-       SysLog(NID_APP, "AppId: %ls.", appId.GetPointer());
+       SysLog(NID_APP, "App: %ls.", appId.GetPointer());
 
        String actualAppId = appId;
        if (appId.GetLength() == 10)
@@ -545,21 +638,69 @@ _AppControlManager::LaunchApp(const AppId& appId, _AppArg* pArg, int req)
        return r;
 }
 
+static bool
+_IsDefaultApplication(const AppId& packageId, const String& appId)
+{
+       const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
+
+       int index = -1;
+       result r = appId.IndexOf(L'.', 0, index);
+       if (r != E_SUCCESS)
+       {
+               return false;
+       }
+
+       String tmp;
+       appId.SubString(index + 1, tmp);
+       if (tmp == execName)
+       {
+               SysLog(NID_APP, "Default application %ls", tmp.GetPointer());
+               return true;
+       }
+
+       return false;
+}
+
+
+int
+_AppControlManager::Launch(const _AppMessageImpl& msg, const AppId& aId, const String& oId, const String* pUriData, const String* pMimeType, AppSvcResFn pCb, void* pData)
+{
+       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;
+}
+
+
 int
 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
 {
+       return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
+}
+
+
+int
+_AppControlManager::Launch(const AppId& appId, _AppArg* pArg, AppSvcResFn pCb, void* pData, int req)
+{
        SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Invalid launch argument");
-       SysLog(NID_APP, "AppId: %ls.", appId.GetPointer());
+       SysLog(NID_APP, "App: %ls.", appId.GetPointer());
 
        String actualAppId = appId;
        if (appId.GetLength() == 10)
        {
-               const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
+               const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
 
-               if (!name.IsEmpty())
+               if (!execName.IsEmpty())
                {
                        actualAppId.Append(L'.');
-                       actualAppId.Append(name);
+                       actualAppId.Append(execName);
                }
        }
 
@@ -574,19 +715,24 @@ _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int 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)
+       if (_IsDefaultApplication(tempId, appId))
        {
-               SysLog(NID_APP, "Submode launch successful");
-               return pid;
+               tempId += L'.';
+               tempId += L"_AppControl";
+
+               // [INFO] Ugly solution for submode support
+               pArg->UpdateAppId(tempId);
+               kb = pArg->GetBundle();
+
+               pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
+               if (pid > 0)
+               {
+                       SysLog(NID_APP, "Submode launch successful");
+                       return pid;
+               }
        }
 
        pArg->UpdateAppId(actualAppId);
@@ -598,7 +744,7 @@ _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
        do
        {
                kb = pArg->GetBundle();
-               pid = appsvc_run_service(kb, req, LaunchResultCb, this);
+               pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
                if (pid > 0)
                {
                        SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
@@ -642,6 +788,12 @@ _AppControlManager::LaunchAppImplicit(_AppArg* pArg, int req)
                _AppMessageImpl::AddData(kb, SELECTOR_NOTI_KEY, _AppInfo::GetApplicationId());
        }
 
+       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)
        {
@@ -686,12 +838,14 @@ _AppControlManager::LaunchAppImplicit(_AppArg* pArg, int req)
 }
 
 void
-_AppControlManager::FinishAppControl(int reqId, int res, const IMap* pMap)
+_AppControlManager::FinishAppControl(int reqId, int res, IMap* pMap)
 {
+       SysLog(NID_APP, "req %d, res %d.", reqId, res);
        _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap);
        SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
 
        SendAppControlEvent(*pArg);
+       SysLog(NID_APP, "Exit.");
 }
 
 const _AppArg*
@@ -731,7 +885,7 @@ _AppControlManager::RegisterRequest(service_s* service, int& req, _AppHandler& h
        bundle* b = _AppArg::GetBundleFromSvc(service);
 
        _AppArg* pArg = new (std::nothrow) _AppArg();
-       SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "rrayList creation failure.");
+       SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "ArrayList creation failure.");
        pArg->Construct(b);
 
        result r = E_SUCCESS;
@@ -755,13 +909,13 @@ CATCH:
 
 
 bool
-_AppControlManager::IsAllowedAppControl(const wchar_t aTable[][2][64], int count, const String& aId, const String& oId)
+_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 (%ls, %ls)", aTable[i][0], aTable[i][1]);
+                       SysLog(NID_APP, "Found entry (%s, %s)", aTable[i][0], aTable[i][1]);
                        return true;
                }
        }
@@ -769,4 +923,82 @@ _AppControlManager::IsAllowedAppControl(const wchar_t aTable[][2][64], int count
        return false;
 }
 
+
+AppCtrlResult
+_AppControlManager::ConvertAppControlResultCode(int resCode)
+{
+       AppCtrlResult ret = APP_CTRL_RESULT_FAILED;
+
+       switch(resCode)
+       {
+               case SERVICE_RESULT_SUCCEEDED:
+                       ret = APP_CTRL_RESULT_SUCCEEDED;
+                       break;
+               case SERVICE_RESULT_FAILED:
+                       ret = APP_CTRL_RESULT_CANCELED;
+                       break;
+               case SERVICE_RESULT_CANCELED:
+                       ret = APP_CTRL_RESULT_ABORTED;
+                       break;
+               case APPSVC_OSP_RES_FAIL:
+                       ret = APP_CTRL_RESULT_FAILED;
+                       break;
+               case APPSVC_OSP_RES_TERMINATE:
+                       ret = APP_CTRL_RESULT_TERMINATED;
+                       break;
+               default:
+                       ret = APP_CTRL_RESULT_FAILED;
+                       break;
+       }
+
+       return ret;
+}
+
+
+void
+_AppControlManager::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
+{
+       const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
+
+       if (pEventArg != null)
+       {
+               IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
+
+               if(pResponseListener != null)
+               {
+                       if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_START)
+                       {
+                               pResponseListener->OnAppControlStartResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetResult());
+                               SysLog(NID_APP, "OnAppControlStartResponseReceived called");
+                       }
+                       else
+                       {
+                               pResponseListener->OnAppControlCompleteResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData());
+                               SysLog(NID_APP, "OnAppControlCompleteResponseReceived called");
+
+                               _AppControlResponseEvent* pResponseEvent = null;
+                               _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
+                               _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
+
+                               delete pResponseEvent;
+                               SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
+                       }
+               }
+               else
+               {
+                       SysLog(NID_APP, "Invalid ResponseListener");
+               }
+       }
+       else
+       {
+               SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
+       }
+}
+
+AppId
+_AppControlManager::GetAliasAppId(const AppId& appId)
+{
+       return _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
+}
+
 }} // Tizen::App