Merge "Update deprecated libprivilege-control API functions." into tizen
[platform/framework/native/appfw.git] / src / app / FApp_AppControlRegistry.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_AppControlRegistry.cpp
19  * @brief       This is the implementation for the _AppControlRegistry.cpp class.
20  */
21
22 #include <new>
23 #include <unique_ptr.h>
24 #include <bundle.h>
25 #include <appsvc.h>
26 #include <new>
27
28 #include <FBaseErrors.h>
29 #include <FBaseSysLog.h>
30 #include <FBaseColAllElementsDeleter.h>
31 #include <FBaseColHashMap.h>
32 #include <FAppAppControl.h>
33 #include <FIoRegistry.h>
34 #include <FIoFile.h>
35
36 #include <FBase_StringConverter.h>
37 #include <FIo_RegistryImpl.h>
38
39 #include "FApp_AppControlImpl.h"
40 #include "FApp_AppControlRegistry.h"
41 #include "FApp_AppMessageImpl.h"
42 #include "FApp_TemplateUtil.h"
43
44 using namespace Tizen::Base;
45 using namespace Tizen::Base::Collection;
46 using namespace Tizen::Io;
47
48 namespace
49 {
50
51 const wchar_t ACTL_DEFAULT_FILE[] = L"/usr/etc/app-control-info.ini";
52 const wchar_t ACTL_LEGACY_FILE[] = L"/usr/etc/app-control-alias.ini";
53 const wchar_t ACTL_DEFAULT_PLUGIN[] = L"libosp-ac-platform.so";
54
55 const String ACTL_REGISTRY_PATH = L"Path";
56 const String ACTL_REGISTRY_ALIAS_PROVIDER = L"PROVIDER_ALIAS";
57
58 const int REG_VALUE_BUFFER_LEN = 256;
59
60 }
61
62
63 namespace Tizen { namespace App
64 {
65
66 _AppControlRegistry* _AppControlRegistry::__pSelf = null;
67
68 _AppControlRegistry::_AppControlRegistry(void)
69 {
70         __tizenList.Construct();
71
72         __aliasList.Construct();
73 }
74
75 _AppControlRegistry::~_AppControlRegistry(void)
76 {
77         _DeleteCollectionMapValue<String, _AppControlAliasEntry>(__aliasList);
78 }
79
80 _AppControlRegistry*
81 _AppControlRegistry::GetInstance(void)
82 {
83         if (__pSelf == null)
84         {
85                 SysLog(NID_APP, "Create new instance");
86                 __pSelf = new (std::nothrow) _AppControlRegistry();
87                 SysTryReturn(NID_APP, __pSelf != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
88                 SysAssertf(__pSelf != null, "AppControl registry instance creation failure");
89
90                 __pSelf->LoadTizenAppControlRegistry();
91
92                 __pSelf->LoadLegacyList();
93         }
94
95         return __pSelf;
96 }
97
98
99 result
100 _AppControlRegistry::LoadTizenAppControlRegistry(void)
101 {
102         _RegistryImpl reg;
103
104         const String regPath = ACTL_DEFAULT_FILE;
105
106         result r = reg.Construct(regPath, REG_OPEN_READ_ONLY, null);
107         if (IsFailed(r))
108         {
109                 SysPropagate(NID_APP, r);
110                 return r;
111         }
112
113         const int secCount = reg.GetAllSectionCount();
114         SysTryReturnResult(NID_APP, !(secCount <= 0), E_OBJ_NOT_FOUND, "Registry contains no data.");
115
116         SysLog(NID_APP, "Loading %d sections from %ls", secCount, regPath.GetPointer());
117
118         int index = 0;
119         int size = 0;
120         //int num = 0;
121         String path;
122
123         for (int i = 0; i < secCount; i++)
124         {
125                 ///////////////////////////////////////////////////////////////////////
126                 // appcontrol Id
127                 String sec_name(reg.GetSectionName(i));
128                 sec_name.Trim();
129
130                 if (sec_name.IsEmpty())
131                 {
132                         continue;
133                 }
134
135                 ///////////////////////////////////////////////////////////////////////
136                 // Path
137                 index = reg.GetEntryIndex(i, ACTL_REGISTRY_PATH);
138                 if (index >= 0)
139                 {
140                         size = REG_VALUE_BUFFER_LEN;
141                         reg.GetEntryValue(i, index, REG_VALUE_TYPE_STRING, &path, &size);
142                 }
143
144                 __tizenList.Add(sec_name, path);
145         }
146
147         SysLog(NID_APP, "Finished loading %d tizen AppControl entries", __tizenList.GetCount());
148
149         return E_SUCCESS;
150 }
151
152 result
153 _AppControlRegistry::LoadLegacyList(void)
154 {
155         _RegistryImpl reg;
156
157         const String& regPath(ACTL_LEGACY_FILE);
158
159         result r = reg.Construct(regPath, REG_OPEN_READ_ONLY, null);
160         if (IsFailed(r))
161         {
162                 SysPropagate(NID_APP, r);
163                 return r;
164         }
165
166         const int sec_count = reg.GetAllSectionCount();
167         SysTryReturnResult(NID_APP, !(sec_count <= 0), E_OBJ_NOT_FOUND, "Registry contains no data.");
168
169         SysLog(NID_APP, "Loading %d sections from %ls", sec_count, regPath.GetPointer());
170
171         String aliasProvider;
172         String value;
173
174
175         // actual parameter manipulation
176         for (int i = 0; i < sec_count; i++)
177         {
178                 ///////////////////////////////////////////////////////////////////////
179                 // appcontrol Id
180                 const String& secName(reg.GetSectionName(i));
181
182                 ///////////////////////////////////////////////////////////////////////
183                 // aliased appcontrol name
184                 const int index = reg.GetEntryIndex(i, ACTL_REGISTRY_ALIAS_PROVIDER);
185                 if (index >= 0)
186                 {
187                         int size = REG_VALUE_BUFFER_LEN;
188                         reg.GetEntryValue(i, index, REG_VALUE_TYPE_STRING, &aliasProvider, &size);
189                 }
190
191                 ///////////////////////////////////////////////////////////////////////
192                 // Operations
193                 IList* pList = reg.GetAllEntryNamesN(secName);
194                 if (pList == null)
195                 {
196                         continue;
197                 }
198
199                 std::unique_ptr<IEnumerator> pEnum(pList->GetEnumeratorN());
200
201                 while (pEnum->MoveNext() == E_SUCCESS)
202                 {
203                         String* pStr = dynamic_cast<String*>(pEnum->GetCurrent());
204
205                         if (pStr == null || pStr->IsEmpty() || pStr->Equals(ACTL_REGISTRY_ALIAS_PROVIDER, false))
206                         {
207                                 continue;
208                         }
209
210                         r = reg.GetValue(secName, *pStr, value);
211                         if (IsFailed(r))
212                         {
213                                 SysPropagate(NID_APP, r);
214                                 continue;
215                         }
216
217                         // add entry to aliasList
218                         _AppControlAliasEntry* pEntry = new (std::nothrow) _AppControlAliasEntry(secName, *pStr, aliasProvider, value);
219                         SysTryReturnResult(NID_APP, pEntry != null, E_OUT_OF_MEMORY, "Insufficient memory.");
220
221                         if (pEntry)
222                         {
223                                 SysLog(NID_APP, "(%ls, %ls)", secName.GetPointer(), aliasProvider.GetPointer());
224                                 __aliasList.Add(secName, pEntry);
225                         }
226                 }
227
228                 pList->RemoveAll(true);
229                 delete pList;
230         }
231
232         SysLog(NID_APP, "Finished loading %d entries.", __aliasList.GetCount());
233
234         return E_SUCCESS;
235 }
236
237
238 AppControl*
239 _AppControlRegistry::GetTizenAppControlN(const String& aId, const String& oId) const
240 {
241         int count = 0;
242         const String* pAppId = &aId;
243         const String* pOperation = &oId;
244
245         // legacy check first
246         do
247         {
248                 const _AppControlAliasEntry* const pEntry = GetAppControlAliasEntry(*pAppId, *pOperation);
249                 // number does not matter
250                 if (count >= 5 || pEntry == null)
251                 {
252                         break;
253                 }
254
255                 pAppId = &pEntry->provider2;
256                 pOperation = &pEntry->operation2;
257                 count++;
258         }
259         while (true);
260
261
262         SysAssert(pAppId != null);
263         SysAssert(pOperation != null);
264
265         SysLog(NID_APP, "Found matching AppControl (%ls, %ls)", pAppId->GetPointer(), pOperation->GetPointer());
266
267         const String& soName = GetTizenAppControlProvider(*pAppId, *pOperation);
268
269         return _AppControlImpl::CreateN(soName, *pAppId, *pOperation, _APPCONTROL_PROPERTY_PUBLIC);
270 }
271
272
273 String
274 _AppControlRegistry::GetTizenAppControlProvider(const String& appId, const String& oId) const
275 {
276         String val;
277         result r = __tizenList.GetValue(appId, val);
278         if (r == E_SUCCESS)
279         {
280                 SysLog(NID_APP, "Found TIZEN AppControl stub %ls for %ls.", val.GetPointer(), appId.GetPointer());
281                 return val;
282         }
283
284         SysLog(NID_APP, "Default platform AppControl %ls is used.", ACTL_DEFAULT_PLUGIN);
285         return String(ACTL_DEFAULT_PLUGIN);
286 }
287
288
289 //
290 // data structure for _AppControlRegistry::FindAppControlListN() only
291 //
292 struct AppSvcIterData
293 {
294 public:
295         AppSvcIterData(const _AppControlRegistry* pRegs, ArrayList* pArr, const String& op) : pThis(pRegs), pArray(pArr), operation(op) {}
296
297         const _AppControlRegistry* pThis;
298         ArrayList* pArray;
299         const String& operation;
300 };
301
302 //
303 // callback function for _AppControlRegistry::FindAppControlListN()
304 //
305 static int
306 AppSvcIterFnCb(const char* pAppId, void* pData)
307 {
308         SysAssert(pData != null);
309
310         AppSvcIterData* pAppSvcIterData = static_cast<AppSvcIterData*>(pData);
311         ArrayList* pList = pAppSvcIterData->pArray;
312         SysAssert(pList != null);
313         const _AppControlRegistry* pThis = pAppSvcIterData->pThis;
314         SysAssert(pThis != null);
315         const String& operation = pAppSvcIterData->operation;
316
317         if (pAppId == NULL)
318         {
319                 SysLog(NID_APP, "Empty appId received.");
320                 return -1;
321         }
322
323         String appId = pAppId;
324         AppControl* pAc = pThis->GetTizenAppControlN(appId, operation);
325         if (pAc == null)
326         {
327                 SysLog(NID_APP, "AppControl allocation failure for %ls.", appId.GetPointer());
328                 return -1;
329         }
330
331         pList->Add(pAc);
332
333         return 0;
334 }
335
336 Tizen::Base::Collection::ArrayList*
337 _AppControlRegistry::FindAppControlListN(const String* pOid, const String* pUri, const String* pMimeType, const String* pCategory) const
338 {
339         String operation = (pOid) ? *pOid : TIZEN_OPERATION_MAIN;
340
341         std::unique_ptr<bundle, BundleDeleter> pBundle(bundle_create());
342         SysTryReturn(NID_APP, pBundle.get(), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Bundle creation failure.");
343
344         _AppMessageImpl::SetOperation(pBundle.get(), operation);
345
346         if (pUri)
347         {
348                 _AppMessageImpl::SetUri(pBundle.get(), *pUri);
349         }
350
351         if (pMimeType)
352         {
353                 _AppMessageImpl::SetMime(pBundle.get(), *pMimeType);
354         }
355
356         if (pCategory)
357         {
358                 _AppMessageImpl::SetCategory(pBundle.get(), *pCategory);
359         }
360
361         ArrayList* pList = new (std::nothrow) ArrayList;
362         SysTryReturn(NID_APP, pList != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] ArrayList creation failure.");
363         pList->Construct();
364
365         AppSvcIterData data(this, pList, operation);
366
367         appsvc_get_list(pBundle.get(), AppSvcIterFnCb, reinterpret_cast<void*>(&data));
368
369         if (pList->GetCount() == 0)
370         {
371                 SysLog(NID_APP, "Found no AppControl entry for operation %ls.", operation.GetPointer());
372
373                 delete pList;
374                 pList = null;
375         }
376
377         return pList;
378 }
379
380 const _AppControlRegistry::_AppControlAliasEntry*
381 _AppControlRegistry::GetAppControlAliasEntry(const String& aId, const String& oId) const
382 {
383         std::unique_ptr< IEnumeratorT<_AppControlAliasEntry*> > pEnum(__aliasList.GetValuesN(aId));
384         if (pEnum.get() == null)
385         {
386                 SysLog(NID_APP, "[E_OBJ_NOT_FOUND] No alias entry for %ls.", aId.GetPointer());
387                 return null;
388         }
389
390         while (pEnum->MoveNext() == E_SUCCESS)
391         {
392                 _AppControlAliasEntry* pEntry = null;
393                 pEnum->GetCurrent(pEntry);
394                 if (pEntry->provider == aId && pEntry->operation == oId)
395                 {
396                         SysLog(NID_APP, "Found matching AppControl (%ls, %ls)->(%ls, %ls)", aId.GetPointer(), oId.GetPointer(), pEntry->provider2.GetPointer(), pEntry->operation2.GetPointer());
397
398                         return pEntry;
399                 }
400         }
401
402         return null;
403 }
404
405
406 AppId
407 _AppControlRegistry::GetAliasAppId(const AppId& appId) const
408 {
409         std::unique_ptr<bundle, BundleDeleter> pBundle(bundle_create());
410
411         if (pBundle.get())
412         {
413                 std::unique_ptr<char[]> pAppId(_StringConverter::CopyToCharArrayN(appId));
414
415                 // appsvc_set_appid() lookup for actual app ID internally
416                 appsvc_set_appid(pBundle.get(), pAppId.get());
417                 const char* pTmp = appsvc_get_appid(pBundle.get());
418
419                 if (pTmp)
420                 {
421                         return String(pTmp);
422                 }
423         }
424
425         return String();
426 }
427
428 } } // Tizen::App