Use security_server_app_give_access() API for updating smack rule
[platform/framework/native/appfw.git] / src / app / FApp_DataControlProviderManagerImpl.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15 //
16
17 /**
18  * @file        FApp_DataControlProviderManagerImpl.cpp
19  * @brief       This is the implementation for the %_DataControlProviderManagerImpl class.
20  */
21
22 #include <new>
23 #include <unique_ptr.h>
24 #include <security-server.h>
25
26 #include <FBaseDataType.h>
27 #include <FBaseInteger.h>
28 #include <FBaseString.h>
29 #include <FBaseLongLong.h>
30 #include <FBaseColArrayList.h>
31 #include <FBaseColIList.h>
32 #include <FBaseSysLog.h>
33 #include <FBaseErrors.h>
34 #include <FAppAppManager.h>
35 #include <FAppSqlDataControl.h>
36 #include <FAppMapDataControl.h>
37 #include <FAppDataControlProviderManager.h>
38 #include <FIoFile.h>
39
40 #include <FBase_StringConverter.h>
41 #include <FIo_DataControlResultSetImpl.h>
42
43 #include "FApp_Aul.h"
44 #include "FApp_AppArg.h"
45 #include "FApp_AppInfo.h"
46 #include "FApp_AppImpl.h"
47 #include "FApp_AppControlManager.h"
48 #include "FApp_SqlDataControlImpl.h"
49 #include "FApp_MapDataControlImpl.h"
50 #include "FApp_DataControlProviderManagerImpl.h"
51 #include "FApp_DataControlManager.h"
52
53 using namespace std;
54 using namespace Tizen::Base;
55 using namespace Tizen::Base::Collection;
56 using namespace Tizen::Io;
57
58 extern const char* _DATACONTROL_RESULT_DIR;
59 extern const char* _DATACONTROL_RESULT_COMPAT_DIR;
60
61 namespace Tizen { namespace App
62 {
63
64 static const int _MAX_ARGUMENT_SIZE = 16384; // 16KB
65
66 result
67 _DataControlProviderManagerImpl::SetSqlDataControlProviderEventListener(ISqlDataControlProviderEventListener* pListener)
68 {
69         _AppImpl* pAppImpl = _AppImpl::GetInstance();
70         SysTryReturn(NID_APP, pAppImpl, false, E_INVALID_STATE, "[E_INVALID_STATE] Getting _AppImpl instance failed.");
71
72         return pAppImpl->SetSqlDataControlProviderEventListener(pListener);
73 }
74
75 result
76 _DataControlProviderManagerImpl::SetMapDataControlProviderEventListener(IMapDataControlProviderEventListener* pListener)
77 {
78         _AppImpl* pAppImpl = _AppImpl::GetInstance();
79         SysTryReturn(NID_APP, pAppImpl, false, E_INVALID_STATE, "[E_INVALID_STATE] Getting _AppImpl instance failed.");
80
81         return pAppImpl->SetMapDataControlProviderEventListener(pListener);
82 }
83
84 result
85 _DataControlProviderManagerImpl::SendDataControlResult(RequestId reqId, _DataControlRequestType apiType,
86                 IDbEnumerator* pDbEnum, IList* pResultValueList, long long insertRowId, bool providerResult, const String* pErrorMsg)
87 {
88         ArrayList* pList = null;
89         String callerAppId;
90         int callerPid = -1;
91         String version;
92         String reqType;
93         int type = 0;
94         _DataControlRequestType requestType = _DATACONTROL_REQUEST_TYPE_UNDEFINED;
95         String providerId;
96         String callerReqId;
97         ArrayList* pResultArgList = null;
98         String* pResult = null;
99         String* pErrorMessage = null;
100         String* pTempFilePath = null;
101         String* pNo = null;
102         int pageNo = 0;
103         String* pCount = null;
104         int countPerPage = 0;
105         String* pResultCount = null;
106         String* pResultValue = null;
107         _AppArg resultArg;
108         String* pDataId = null;
109         result r = E_SUCCESS;
110         int ret = -1;
111
112         _AppControlManager* pAppMgr = _AppControlManager::GetInstance();
113         SysTryReturnResult(NID_APP, pAppMgr, E_SYSTEM, "Failed to get instance.");
114
115         _ResultInfo* pResultInfo = pAppMgr->__resultManager.FindItem(static_cast< int >(reqId)); // provider reqId
116         SysTryReturnResult(NID_APP, pResultInfo, E_OBJ_NOT_FOUND,
117                         "The data control request specified with the req (%ld) did not exist.", reqId);
118
119         const _AppArg& arg = pResultInfo->arg; // request info
120
121         // key-based request
122         reqType = arg.GetValue(OSP_K_DATACONTROL_REQUEST_TYPE);
123         Integer::Parse(reqType, type);
124         requestType = static_cast< _DataControlRequestType >(type);
125         if (providerResult == true && apiType != requestType)
126         {
127                 if ((apiType == _DATACONTROL_REQUEST_TYPE_SQL_UPDATE /*UpdateDelete*/ && requestType == _DATACONTROL_REQUEST_TYPE_SQL_DELETE) ||
128                                 apiType == _DATACONTROL_REQUEST_TYPE_UNDEFINED /*MAP*/)
129                 {
130                         r = E_SUCCESS;
131                 }
132                 else
133                 {
134                         r = E_INVALID_ARG;
135                         SysLog(NID_APP, "[E_INVALID_ARG] This method cannot send the result set for the specified reqId.");
136                         goto CATCH;
137                 }
138         }
139
140         callerAppId = arg.GetCallerAppId();
141         callerPid = arg.GetCallerPid();
142         version = arg.GetValue(OSP_K_DATACONTROL_PROTOCOL_VERSION);
143         callerReqId = arg.GetValue(OSP_K_REQUEST_ID);
144         providerId = arg.GetValue(OSP_K_DATACONTROL_PROVIDER);
145
146         // list-based request
147         pList = _AppArg::GetListN(arg.GetBundle(), OSP_K_ARG);
148         SysTryCatch(NID_APP, pList, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
149
150         pDataId = dynamic_cast< String* >(pList->GetAt(0)); // request list[0]
151         SysTryCatch(NID_APP, pDataId, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
152
153         SysSecureLog(NID_APP, "[DC_PROV_SEND] > caller app: %ls, caller proc: %d, version: %ls requestType: %d, callerReq: %ls, provider: %ls, data: %ls",
154                         callerAppId.GetPointer(), callerPid, version.GetPointer(), requestType, callerReqId.GetPointer(), providerId.GetPointer(), pDataId->GetPointer());
155
156         // Serializes result
157         pResultArgList = new (std::nothrow) ArrayList();
158         SysTryCatch(NID_APP, pResultArgList, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
159                         "[E_OUT_OF_MEMORY] The memory was insufficient.");
160         pResultArgList->Construct();
161
162         pResult = new (std::nothrow) String();
163         SysTryCatch(NID_APP, pResult, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
164                         "[E_OUT_OF_MEMORY] The memory was insufficient.");
165         pResult->Append(static_cast< int >(providerResult));
166         pResultArgList->Add(*pResult); // result list[0]
167
168         if (pErrorMsg == null)
169         {
170                 pErrorMessage = new (std::nothrow) String();
171         }
172         else
173         {
174                 pErrorMessage = new (std::nothrow) String(*pErrorMsg);
175         }
176         SysTryCatch(NID_APP, pErrorMessage, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
177                         "[E_OUT_OF_MEMORY] The memory was insufficient.");
178         SysTryCatch(NID_APP, pErrorMessage->GetLength() <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
179                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", pErrorMessage->GetLength());
180         pResultArgList->Add(*pErrorMessage); // result list[1]
181
182         switch (requestType)
183         {
184         case _DATACONTROL_REQUEST_TYPE_SQL_QUERY:
185         {
186                 if (pDbEnum)
187                 {
188                         unique_ptr<_DataControlResultSetImpl> pResultSet(new (std::nothrow) _DataControlResultSetImpl(reqId));
189                         SysTryCatch(NID_APP, pResultSet, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
190                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
191
192                         r = pResultSet->FillWith(pDbEnum, version);
193                         SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM,
194                                         "[E_SYSTEM] The method cannot proceed due to a severe system error.");
195
196                         String tempFilePath;
197                         if (version == L"ver_2.1.0.3")
198                         {
199                                 tempFilePath.Append(_DATACONTROL_RESULT_DIR);
200
201                                 DataControlProviderManager* pDcMgr = DataControlProviderManager::GetInstance();
202                                 SysTryCatch(NID_APP, pDcMgr != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to get DataControlProviderManager instance.");
203                                 r = pDcMgr->__pDataControlProviderManagerImpl->AllowAccess(callerAppId);
204                                 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
205                         }
206                         else
207                         {
208                                 tempFilePath.Append(_DATACONTROL_RESULT_COMPAT_DIR);
209                         }
210                         tempFilePath.Append(callerAppId);
211                         tempFilePath.Append(callerReqId);
212                         pTempFilePath = new (std::nothrow) String(tempFilePath);
213                 }
214                 else
215                 {
216                         pTempFilePath = new (std::nothrow) String(L"NoResultSet");
217                 }
218                 SysTryCatch(NID_APP, pTempFilePath, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
219                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
220
221                 pResultArgList->Add(*pTempFilePath); // result list[2]
222                 break;
223         }
224         case _DATACONTROL_REQUEST_TYPE_SQL_INSERT:
225                 pResultArgList->Add(*(new String(LongLong::ToString(insertRowId)))); // result list[2]
226                 break;
227
228         case _DATACONTROL_REQUEST_TYPE_SQL_UPDATE:
229                 // fall through
230         case _DATACONTROL_REQUEST_TYPE_SQL_DELETE:
231                 break;
232
233         case _DATACONTROL_REQUEST_TYPE_MAP_QUERY:
234         {
235                 SysTryCatch(NID_APP, !(providerResult == true && pResultValueList == null), r = E_INVALID_ARG, E_INVALID_ARG,
236                                 "[E_INVALID_ARG] The specified pResultValueList should not be null if the request is GetValue query.");
237
238                 if (pResultValueList)
239                 {
240                         // list-based request
241                         pNo = dynamic_cast< String* >(pList->GetAt(2)); // request list[2]
242                         SysTryCatch(NID_APP, pNo, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
243                         Integer::Parse(*pNo, pageNo);
244
245                         pCount = dynamic_cast< String* >(pList->GetAt(3)); // request list[3]
246                         SysTryCatch(NID_APP, pCount, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
247                         Integer::Parse(*pCount, countPerPage);
248                         SysLog(NID_APP, "[DC_PROV_SEND] pageNo: %d, countPerPage: %d", pageNo, countPerPage);
249
250                         String resultCount;
251                         int num = pResultValueList->GetCount();
252                         int currentoffset = (pageNo - 1) * countPerPage;
253                         int remainingNum = num - currentoffset;
254                         remainingNum = (remainingNum > 0) ? remainingNum : 0; // round off to zero if negative num is found
255                         int addItemCount = (countPerPage > remainingNum) ? remainingNum : countPerPage;
256                         resultCount.Append(addItemCount);
257
258                         pResultCount = new (std::nothrow) String(resultCount);
259                         SysTryCatch(NID_APP, pResultCount, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
260                                         "[E_OUT_OF_MEMORY] The memory was insufficient.");
261                         pResultArgList->Add(*pResultCount); // result list[2]
262                         SysLog(NID_APP, "[DC_PROV_SEND] result count: %ls", resultCount.GetPointer());
263
264                         long long argSize = 0;
265                         if (addItemCount > 0)
266                         {
267                                 if (version == L"ver_2.1.0.1" || version == L"ver_2.1.0.2" || version == L"ver_2.1.0.3")
268                                 {
269                                         String tempFilePath;
270                                         if (version == L"ver_2.1.0.3")
271                                         {
272                                                 tempFilePath.Append(_DATACONTROL_RESULT_DIR);
273                                         }
274                                         else
275                                         {
276                                                 tempFilePath.Append(_DATACONTROL_RESULT_COMPAT_DIR);
277                                         }
278                                         tempFilePath.Append(callerAppId);
279                                         tempFilePath.Append(callerReqId);
280                                         pTempFilePath = new (std::nothrow) String(tempFilePath);
281                                         pResultArgList->Add(*pTempFilePath); // result list[3]
282                                         SysLog(NID_APP, "[DC_PROV_SEND] protocol version: %ls, path: %ls", version.GetPointer(), pTempFilePath->GetPointer());
283
284                                         unique_ptr< File > pFile(new (std::nothrow) File());
285                                         SysTryCatch(NID_APP, pFile != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
286
287                                         r = pFile->Construct(*pTempFilePath, L"w+", true);
288                                         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Failed to create temp file (%ls) for result set.",
289                                                         GetErrorMessage(r), pTempFilePath->GetPointer());
290
291                                         for (int i = currentoffset; i < num; ++i)
292                                         {
293                                                 String* pValue = dynamic_cast< String* >(pResultValueList->GetAt(i));
294                                                 SysTryCatch(NID_APP, pValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
295                                                                 "[E_INVALID_ARG] The specified pResultValueList parameter should be String class.");
296
297                                                 unique_ptr< char[] > pData(_StringConverter::CopyToCharArrayN(*pValue));
298                                                 SysTryCatch(NID_APP, pData != null, , GetLastResult(), "[%s] Invalid result value",
299                                                                 GetErrorMessage(GetLastResult()));
300
301                                                 int length = strlen(pData.get());
302                                                 r = pFile->Write(&length, sizeof(int)); // data length
303                                                 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] Failed to send result.", GetErrorMessage(r));
304
305                                                 r = pFile->Write(pData.get(), length); // data
306                                                 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] Failed to send result.", GetErrorMessage(r));
307                                         }
308                                         pFile->Flush();
309
310                                         if (version == L"ver_2.1.0.3")
311                                         {
312                                                 DataControlProviderManager* pDcMgr = DataControlProviderManager::GetInstance();
313                                                 SysTryCatch(NID_APP, pDcMgr != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to get DataControlProviderManager instance.");
314                                                 r = pDcMgr->__pDataControlProviderManagerImpl->AllowAccess(callerAppId);
315                                                 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
316                                         }
317                                 }
318                                 else
319                                 {
320                                         SysLog(NID_APP, "[DC_PROV_SEND] protocol version: none");
321                                         for (int i = currentoffset; i < num; ++i)
322                                         {
323                                                 String* pValue = dynamic_cast< String* >(pResultValueList->GetAt(i));
324                                                 SysTryCatch(NID_APP, pValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
325                                                                 "[E_INVALID_ARG] The specified pResultValueList parameter should be String class.");
326
327                                                 pResultValue = new (std::nothrow) String(*pValue);
328                                                 SysTryCatch(NID_APP, pResultValue, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
329                                                                 "[E_OUT_OF_MEMORY] The memory was insufficient.");
330                                                 pResultArgList->Add(*pResultValue); // list[3] ~
331                                                 argSize += pValue->GetLength() * sizeof(wchar_t);
332                                         }
333                                         SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
334                                                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
335                                 }
336                         }
337                 }
338                 break;
339         }
340         case _DATACONTROL_REQUEST_TYPE_MAP_INSERT:
341                 // fall through
342         case _DATACONTROL_REQUEST_TYPE_MAP_UPDATE:
343                 // fall through
344         case _DATACONTROL_REQUEST_TYPE_MAP_DELETE:
345                 SysTryCatch(NID_APP, !(providerResult == true && pResultValueList != null), r = E_INVALID_ARG, E_INVALID_ARG,
346                                 "[E_INVALID_ARG] The specified pResultValueList should be null if the request is \
347                                 one of AddValue, SetValue, RemoveValue queries.");
348                 break;
349
350         default:
351                 SysTryCatch(NID_APP, false, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
352                 break;
353         }
354
355         r = resultArg.ConstructResult(arg, pResultArgList);
356         SysTryCatch(NID_APP, !IsFailed(r), r = E_SYSTEM, r, "[%s] Propagating.", GetErrorMessage(r));
357         resultArg.UpdateKeyValue(OSP_K_REQUEST_ID, callerReqId);
358         resultArg.UpdateKeyValue(OSP_K_DATACONTROL_REQUEST_TYPE, reqType);
359         resultArg.UpdateKeyValue(OSP_K_DATACONTROL_PROVIDER, providerId);
360         resultArg.UpdateKeyValue(OSP_K_DATACONTROL_DATA, *pDataId);
361         resultArg.UpdateKeyValue(OSP_K_DATACONTROL_PROTOCOL_VERSION, version);
362
363         //resultArg.Print();
364         r = _Aul::SendResult(resultArg.GetBundle(), static_cast< appsvc_result_val >(0));
365         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Failed to send result.", GetErrorMessage(r));
366
367         // Erases _AppArg after sending the result back to the caller
368         pAppMgr->__resultManager.RemoveItem(static_cast< int >(reqId));
369
370 CATCH:
371         if (pList)
372         {
373                 pList->RemoveAll(true);
374         }
375         delete pList;
376
377         if (pResultArgList)
378         {
379                 pResultArgList->RemoveAll(true);
380         }
381         delete pResultArgList;
382
383         return r;
384 }
385
386 result
387 _DataControlProviderManagerImpl::SendSqlDataControlSelectResult(RequestId reqId, IDbEnumerator* pDbEnum)
388 {
389         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_SQL_QUERY,
390                         pDbEnum, null, -1, true, null);
391 }
392
393 result
394 _DataControlProviderManagerImpl::SendSqlDataControlInsertResult(RequestId reqId, long long insertRowId)
395 {
396         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_SQL_INSERT,
397                         null, null, insertRowId, true, null);
398 }
399
400 result
401 _DataControlProviderManagerImpl::SendSqlDataControlUpdateDeleteResult(RequestId reqId)
402 {
403         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_SQL_UPDATE,
404                         null, null, -1, true, null);
405 }
406
407 result
408 _DataControlProviderManagerImpl::SendMapDataControlResult(RequestId reqId, IList* pResultValueList)
409 {
410         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_UNDEFINED,
411                         null, pResultValueList, -1, true, null);
412 }
413
414 result
415 _DataControlProviderManagerImpl::SendDataControlError(RequestId reqId, const String& errorMsg)
416 {
417         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_UNDEFINED,
418                         null, null, -1, false, &errorMsg);
419 }
420
421 DataControlProviderManager*
422 _DataControlProviderManagerImpl::GetInstance(void)
423 {
424         static DataControlProviderManager* pDcMgr = null;
425
426         if (pDcMgr == null)
427         {
428                 pDcMgr = new (std::nothrow) DataControlProviderManager();
429                 SysTryReturn(NID_APP, pDcMgr, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory was insufficient.");
430         }
431
432         return pDcMgr;
433 }
434
435 void
436 _DataControlProviderManagerImpl::Cache(String& appId)
437 {
438         __pProviderList->Add(new (std::nothrow) String(appId));
439 }
440
441 bool
442 _DataControlProviderManagerImpl::IsCached(String& appId)
443 {
444         unique_ptr< IEnumerator > pEnum(__pProviderList->GetEnumeratorN());
445         while (pEnum->MoveNext() == E_SUCCESS)
446         {
447                 String* pCachedAppId = dynamic_cast< String* >(pEnum->GetCurrent());
448                 if (pCachedAppId != null && pCachedAppId->Equals(appId) == true)
449                 {
450                         return true;
451                 }
452         }
453         return false;
454 }
455
456 result
457 _DataControlProviderManagerImpl::AllowAccess(String& appId)
458 {
459         if (IsCached(appId) == false)
460         {
461                 unique_ptr< char[] > pPkgId(_StringConverter::CopyToCharArrayN(appId));
462                 SysTryReturnResult(NID_APP, pPkgId != null, E_SYSTEM, "The method cannot proceed due to a severe system error.");
463                 pPkgId.get()[10] = '\0';
464
465                 int ret = security_server_app_give_access(pPkgId.get(), -1);
466                 SysTryReturnResult(NID_APP, ret == 0, E_SYSTEM,
467                                 "Failed to call security_server_app_give_access(), provider: %s, ret: %d", pPkgId.get(), ret);
468
469                 Cache(appId);
470         }
471
472         SysLog(NID_APP, "[DC_PROV_SEND] Allow %ls to access", appId.GetPointer());
473         return E_SUCCESS;
474 }
475
476 _DataControlProviderManagerImpl::_DataControlProviderManagerImpl(void)
477         : __pProviderList(null)
478 {
479         __pProviderList = new (std::nothrow) LinkedList(SingleObjectDeleter);
480         SysTryReturnVoidResult(NID_APP, __pProviderList != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
481 }
482
483 _DataControlProviderManagerImpl::~_DataControlProviderManagerImpl(void)
484 {
485         delete __pProviderList;
486 }
487
488 }} // Tizen::App
489