export _AppControlImpl::FindAndStart()
[platform/framework/native/appfw.git] / src / app / FApp_DataControlProviderManagerImpl.cpp
index e3eecb6..a78c9f5 100644 (file)
@@ -1,5 +1,4 @@
 //
-// Open Service Platform
 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
 //
 // Licensed under the Apache License, Version 2.0 (the License);
@@ -20,7 +19,9 @@
  * @brief      This is the implementation for the %_DataControlProviderManagerImpl class.
  */
 
+#include <new>
 #include <unique_ptr.h>
+#include <security-server.h>
 
 #include <FBaseDataType.h>
 #include <FBaseInteger.h>
 #include <FBaseLongLong.h>
 #include <FBaseColArrayList.h>
 #include <FBaseColIList.h>
+#include <FBaseSysLog.h>
 #include <FBaseErrors.h>
+#include <FAppTypes.h>
 #include <FAppAppManager.h>
 #include <FAppSqlDataControl.h>
 #include <FAppMapDataControl.h>
 #include <FAppDataControlProviderManager.h>
+#include <FIoFile.h>
 
-#include <FBaseSysLog.h>
+#include <FBase_StringConverter.h>
 #include <FIo_DataControlResultSetImpl.h>
+#include <FAppPkg_PackageManagerImpl.h>
 
 #include "FApp_Aul.h"
 #include "FApp_AppArg.h"
 #include "FApp_SqlDataControlImpl.h"
 #include "FApp_MapDataControlImpl.h"
 #include "FApp_DataControlProviderManagerImpl.h"
+#include "FApp_DataControlManager.h"
 
+using namespace std;
 using namespace Tizen::Base;
 using namespace Tizen::Base::Collection;
 using namespace Tizen::Io;
+using namespace Tizen::App::Package;
 
-extern const char* _DATACONTROL_RESULTSET_DIR;
+extern const char* _DATACONTROL_RESULT_DIR;
+extern const char* _DATACONTROL_RESULT_COMPAT_DIR;
 
 namespace Tizen { namespace App
 {
 
+static const int _MAX_ARGUMENT_SIZE = 16384; // 16KB
+
 result
 _DataControlProviderManagerImpl::SetSqlDataControlProviderEventListener(ISqlDataControlProviderEventListener* pListener)
 {
@@ -78,12 +89,14 @@ _DataControlProviderManagerImpl::SendDataControlResult(RequestId reqId, _DataCon
                IDbEnumerator* pDbEnum, IList* pResultValueList, long long insertRowId, bool providerResult, const String* pErrorMsg)
 {
        ArrayList* pList = null;
-       String* pAppId = null;
-       String* pRequestType = null;
+       String callerAppId;
+       int callerPid = -1;
+       String version;
+       String reqType;
        int type = 0;
        _DataControlRequestType requestType = _DATACONTROL_REQUEST_TYPE_UNDEFINED;
-       String* pProviderId = null;
-       String* pReqId = null;
+       String providerId;
+       String callerReqId;
        ArrayList* pResultArgList = null;
        String* pResult = null;
        String* pErrorMessage = null;
@@ -95,29 +108,23 @@ _DataControlProviderManagerImpl::SendDataControlResult(RequestId reqId, _DataCon
        String* pResultCount = null;
        String* pResultValue = null;
        _AppArg resultArg;
+       String* pDataId = null;
        result r = E_SUCCESS;
+       //int ret = -1;
 
        _AppControlManager* pAppMgr = _AppControlManager::GetInstance();
        SysTryReturnResult(NID_APP, pAppMgr, E_SYSTEM, "Failed to get instance.");
 
-       _ResultInfo* pResultInfo = pAppMgr->__resultManager.FindItem(static_cast< int >(reqId));
+       _ResultInfo* pResultInfo = pAppMgr->__resultManager.FindItem(static_cast< int >(reqId)); // provider reqId
        SysTryReturnResult(NID_APP, pResultInfo, E_OBJ_NOT_FOUND,
-                       "The data control request specified with the reqId (%ld) did not exist.", reqId);
-
-       const _AppArg& arg = pResultInfo->arg;
+                       "The data control request specified with the req (%ld) did not exist.", reqId);
 
-       pList = arg.GetArgListN(0);
-       SysTryCatch(NID_APP, pList, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
+       const _AppArg& arg = pResultInfo->arg; // request info
 
        // key-based request
-       pAppId = dynamic_cast< String* >(pList->GetAt(0)); // request key[0]
-       SysTryCatch(NID_APP, pAppId, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
-
-       pRequestType = dynamic_cast< String* >(pList->GetAt(1)); // request key[1]
-       SysTryCatch(NID_APP, pRequestType, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
-       Integer::Parse(*pRequestType, type);
+       reqType = arg.GetValue(OSP_K_DATACONTROL_REQUEST_TYPE);
+       Integer::Parse(reqType, type);
        requestType = static_cast< _DataControlRequestType >(type);
-
        if (providerResult == true && apiType != requestType)
        {
                if ((apiType == _DATACONTROL_REQUEST_TYPE_SQL_UPDATE /*UpdateDelete*/ && requestType == _DATACONTROL_REQUEST_TYPE_SQL_DELETE) ||
@@ -133,13 +140,23 @@ _DataControlProviderManagerImpl::SendDataControlResult(RequestId reqId, _DataCon
                }
        }
 
-       pReqId = dynamic_cast< String* >(pList->GetAt(2)); // request key[2]
-       SysTryCatch(NID_APP, pReqId, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
+       callerAppId = arg.GetCallerAppId();
+       callerPid = arg.GetCallerPid();
+       version = arg.GetValue(OSP_K_DATACONTROL_PROTOCOL_VERSION);
+       callerReqId = arg.GetValue(OSP_K_REQUEST_ID);
+       providerId = arg.GetValue(OSP_K_DATACONTROL_PROVIDER);
+
+       // list-based request
+       pList = _AppArg::GetListN(arg.GetBundle(), OSP_K_ARG);
+       SysTryCatch(NID_APP, pList, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
+
+       pDataId = dynamic_cast< String* >(pList->GetAt(0)); // request list[0]
+       SysTryCatch(NID_APP, pDataId, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
 
-       pProviderId = dynamic_cast< String* >(pList->GetAt(3)); // request key[3]
-       SysTryCatch(NID_APP, pProviderId, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
+       SysSecureLog(NID_APP, "[DC_PROV_SEND] > caller app: %ls, caller proc: %d, version: %ls requestType: %d, callerReq: %ls, provider: %ls, data: %ls",
+                       callerAppId.GetPointer(), callerPid, version.GetPointer(), requestType, callerReqId.GetPointer(), providerId.GetPointer(), pDataId->GetPointer());
 
-       // Serializes the result
+       // Serializes result
        pResultArgList = new (std::nothrow) ArrayList();
        SysTryCatch(NID_APP, pResultArgList, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
                        "[E_OUT_OF_MEMORY] The memory was insufficient.");
@@ -161,6 +178,8 @@ _DataControlProviderManagerImpl::SendDataControlResult(RequestId reqId, _DataCon
        }
        SysTryCatch(NID_APP, pErrorMessage, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
                        "[E_OUT_OF_MEMORY] The memory was insufficient.");
+       SysTryCatch(NID_APP, pErrorMessage->GetLength() <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
+                       "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", pErrorMessage->GetLength());
        pResultArgList->Add(*pErrorMessage); // result list[1]
 
        switch (requestType)
@@ -169,17 +188,30 @@ _DataControlProviderManagerImpl::SendDataControlResult(RequestId reqId, _DataCon
        {
                if (pDbEnum)
                {
-                       std::unique_ptr<_DataControlResultSetImpl> pResultSet(new (std::nothrow) _DataControlResultSetImpl(reqId));
+                       unique_ptr<_DataControlResultSetImpl> pResultSet(new (std::nothrow) _DataControlResultSetImpl(reqId));
                        SysTryCatch(NID_APP, pResultSet, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
                                        "[E_OUT_OF_MEMORY] The memory is insufficient.");
 
-                       r = pResultSet->FillWith(pDbEnum);
+                       r = pResultSet->FillWith(pDbEnum, version);
                        SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM,
                                        "[E_SYSTEM] The method cannot proceed due to a severe system error.");
 
-                       String tempFilePath(_DATACONTROL_RESULTSET_DIR);
-                       tempFilePath.Append(*pAppId);
-                       tempFilePath.Append(*pReqId);
+                       String tempFilePath;
+                       if (version == L"ver_2.1.0.3")
+                       {
+                               tempFilePath.Append(_DATACONTROL_RESULT_DIR);
+
+                               DataControlProviderManager* pDcMgr = DataControlProviderManager::GetInstance();
+                               SysTryCatch(NID_APP, pDcMgr != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to get DataControlProviderManager instance.");
+                               r = pDcMgr->__pDataControlProviderManagerImpl->AllowAccess(callerAppId);
+                               SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
+                       }
+                       else
+                       {
+                               tempFilePath.Append(_DATACONTROL_RESULT_COMPAT_DIR);
+                       }
+                       tempFilePath.Append(callerAppId);
+                       tempFilePath.Append(callerReqId);
                        pTempFilePath = new (std::nothrow) String(tempFilePath);
                }
                else
@@ -209,13 +241,14 @@ _DataControlProviderManagerImpl::SendDataControlResult(RequestId reqId, _DataCon
                if (pResultValueList)
                {
                        // list-based request
-                       pNo = dynamic_cast< String* >(pList->GetAt(6)); // request list[2]
+                       pNo = dynamic_cast< String* >(pList->GetAt(2)); // request list[2]
                        SysTryCatch(NID_APP, pNo, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
                        Integer::Parse(*pNo, pageNo);
 
-                       pCount = dynamic_cast< String* >(pList->GetAt(7)); // request list[3]
+                       pCount = dynamic_cast< String* >(pList->GetAt(3)); // request list[3]
                        SysTryCatch(NID_APP, pCount, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
                        Integer::Parse(*pCount, countPerPage);
+                       SysLog(NID_APP, "[DC_PROV_SEND] pageNo: %d, countPerPage: %d", pageNo, countPerPage);
 
                        String resultCount;
                        int num = pResultValueList->GetCount();
@@ -229,17 +262,80 @@ _DataControlProviderManagerImpl::SendDataControlResult(RequestId reqId, _DataCon
                        SysTryCatch(NID_APP, pResultCount, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
                                        "[E_OUT_OF_MEMORY] The memory was insufficient.");
                        pResultArgList->Add(*pResultCount); // result list[2]
+                       SysLog(NID_APP, "[DC_PROV_SEND] result count: %ls", resultCount.GetPointer());
 
-                       for (int i = currentoffset; i < num; i++)
+                       long long argSize = 0;
+                       if (addItemCount > 0)
                        {
-                               String* pTempValue = dynamic_cast< String* >(pResultValueList->GetAt(i));
-                               SysTryCatch(NID_APP, pTempValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
-                                               "[E_INVALID_ARG] The specified pResultValueList parameter should be String class.");
-
-                               pResultValue = new (std::nothrow) String(*pTempValue);
-                               SysTryCatch(NID_APP, pResultValue, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
-                                               "[E_OUT_OF_MEMORY] The memory was insufficient.");
-                               pResultArgList->Add(*pResultValue); // list[3] ~
+                               if (version == L"ver_2.1.0.1" || version == L"ver_2.1.0.2" || version == L"ver_2.1.0.3")
+                               {
+                                       String tempFilePath;
+                                       if (version == L"ver_2.1.0.3")
+                                       {
+                                               tempFilePath.Append(_DATACONTROL_RESULT_DIR);
+                                       }
+                                       else
+                                       {
+                                               tempFilePath.Append(_DATACONTROL_RESULT_COMPAT_DIR);
+                                       }
+                                       tempFilePath.Append(callerAppId);
+                                       tempFilePath.Append(callerReqId);
+                                       pTempFilePath = new (std::nothrow) String(tempFilePath);
+                                       pResultArgList->Add(*pTempFilePath); // result list[3]
+                                       SysLog(NID_APP, "[DC_PROV_SEND] protocol version: %ls, path: %ls", version.GetPointer(), pTempFilePath->GetPointer());
+
+                                       unique_ptr< File > pFile(new (std::nothrow) File());
+                                       SysTryCatch(NID_APP, pFile != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
+
+                                       r = pFile->Construct(*pTempFilePath, L"w+", true);
+                                       SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Failed to create temp file (%ls) for result set.",
+                                                       GetErrorMessage(r), pTempFilePath->GetPointer());
+
+                                       for (int i = currentoffset; i < num; ++i)
+                                       {
+                                               String* pValue = dynamic_cast< String* >(pResultValueList->GetAt(i));
+                                               SysTryCatch(NID_APP, pValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
+                                                               "[E_INVALID_ARG] The specified pResultValueList parameter should be String class.");
+
+                                               unique_ptr< char[] > pData(_StringConverter::CopyToCharArrayN(*pValue));
+                                               SysTryCatch(NID_APP, pData != null, , GetLastResult(), "[%s] Invalid result value",
+                                                               GetErrorMessage(GetLastResult()));
+
+                                               int length = strlen(pData.get());
+                                               r = pFile->Write(&length, sizeof(int)); // data length
+                                               SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] Failed to send result.", GetErrorMessage(r));
+
+                                               r = pFile->Write(pData.get(), length); // data
+                                               SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] Failed to send result.", GetErrorMessage(r));
+                                       }
+                                       pFile->Flush();
+
+                                       if (version == L"ver_2.1.0.3")
+                                       {
+                                               DataControlProviderManager* pDcMgr = DataControlProviderManager::GetInstance();
+                                               SysTryCatch(NID_APP, pDcMgr != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to get DataControlProviderManager instance.");
+                                               r = pDcMgr->__pDataControlProviderManagerImpl->AllowAccess(callerAppId);
+                                               SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
+                                       }
+                               }
+                               else
+                               {
+                                       SysLog(NID_APP, "[DC_PROV_SEND] protocol version: none");
+                                       for (int i = currentoffset; i < num; ++i)
+                                       {
+                                               String* pValue = dynamic_cast< String* >(pResultValueList->GetAt(i));
+                                               SysTryCatch(NID_APP, pValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
+                                                               "[E_INVALID_ARG] The specified pResultValueList parameter should be String class.");
+
+                                               pResultValue = new (std::nothrow) String(*pValue);
+                                               SysTryCatch(NID_APP, pResultValue, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
+                                                               "[E_OUT_OF_MEMORY] The memory was insufficient.");
+                                               pResultArgList->Add(*pResultValue); // list[3] ~
+                                               argSize += pValue->GetLength() * sizeof(wchar_t);
+                                       }
+                                       SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
+                                                       "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
+                               }
                        }
                }
                break;
@@ -261,9 +357,14 @@ _DataControlProviderManagerImpl::SendDataControlResult(RequestId reqId, _DataCon
 
        r = resultArg.ConstructResult(arg, pResultArgList);
        SysTryCatch(NID_APP, !IsFailed(r), r = E_SYSTEM, r, "[%s] Propagating.", GetErrorMessage(r));
+       resultArg.UpdateKeyValue(OSP_K_REQUEST_ID, callerReqId);
+       resultArg.UpdateKeyValue(OSP_K_DATACONTROL_REQUEST_TYPE, reqType);
+       resultArg.UpdateKeyValue(OSP_K_DATACONTROL_PROVIDER, providerId);
+       resultArg.UpdateKeyValue(OSP_K_DATACONTROL_DATA, *pDataId);
+       resultArg.UpdateKeyValue(OSP_K_DATACONTROL_PROTOCOL_VERSION, version);
 
        //resultArg.Print();
-       r = _Aul::SendResult(resultArg.GetBundle(), static_cast< appsvc_result_val >(0));
+       r = _Aul::SendResult(resultArg.GetBundle(), static_cast< appsvc_result_val >(0), false, false);
        SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Failed to send result.", GetErrorMessage(r));
 
        // Erases _AppArg after sending the result back to the caller
@@ -334,14 +435,58 @@ _DataControlProviderManagerImpl::GetInstance(void)
        return pDcMgr;
 }
 
-// private
+void
+_DataControlProviderManagerImpl::Cache(const AppId& appId)
+{
+       __pProviderList->Add(new (std::nothrow) String(appId));
+}
+
+bool
+_DataControlProviderManagerImpl::IsCached(const AppId& appId)
+{
+       unique_ptr< IEnumerator > pEnum(__pProviderList->GetEnumeratorN());
+       while (pEnum->MoveNext() == E_SUCCESS)
+       {
+               String* pCachedAppId = dynamic_cast< String* >(pEnum->GetCurrent());
+               if (pCachedAppId != null && pCachedAppId->Equals(appId) == true)
+               {
+                       return true;
+               }
+       }
+       return false;
+}
+
+result
+_DataControlProviderManagerImpl::AllowAccess(const AppId& appId)
+{
+       //if (IsCached(appId) == false)
+       //{
+               const PackageId& pkgId = _PackageManagerImpl::GetPackageIdByAppId(appId);
+               unique_ptr< char[] > pPkgId(_StringConverter::CopyToCharArrayN(pkgId));
+               SysTryReturnResult(NID_APP, pPkgId != null, E_SYSTEM, "The method cannot proceed due to a severe system error.");
+
+               int ret = security_server_app_give_access(pPkgId.get(), -1);
+               SysTryReturnResult(NID_APP, ret == 0, E_SYSTEM,
+                               "Failed to call security_server_app_give_access(), provider: %s, ret: %d", pPkgId.get(), ret);
+
+       //      Cache(appId);
+       //}
+
+       SysLog(NID_APP, "[DC_PROV_SEND] Allow %ls to access", appId.GetPointer());
+       return E_SUCCESS;
+}
+
 _DataControlProviderManagerImpl::_DataControlProviderManagerImpl(void)
+       : __pProviderList(null)
 {
+       __pProviderList = new (std::nothrow) LinkedList(SingleObjectDeleter);
+       SysTryReturnVoidResult(NID_APP, __pProviderList != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
 }
 
 _DataControlProviderManagerImpl::~_DataControlProviderManagerImpl(void)
 {
+       delete __pProviderList;
 }
 
-} } // Tizen::App
+}} // Tizen::App