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