Merge "Optimising GetHashCode()" into devel_3.0_main
[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 <app.h>
25 #include <bundle.h>
26
27 #include <FBaseErrors.h>
28 #include <FBaseSysLog.h>
29 #include <FBaseColAllElementsDeleter.h>
30 #include <FBaseColHashMap.h>
31 #include <FAppAppControl.h>
32 #include <FIoRegistry.h>
33 #include <FIoFile.h>
34
35 #include <FBase_StringConverter.h>
36 #include <FIo_RegistryImpl.h>
37
38 #include "FAppPkg_PackageManagerImpl.h"
39 #include "FApp_AppControlImpl.h"
40 #include "FApp_Aul.h"
41 #include "FApp_AppControlRegistry.h"
42 #include "FApp_AppMessageImpl.h"
43 #include "FApp_TemplateUtil.h"
44
45 using namespace Tizen::App::Package;
46 using namespace Tizen::Base;
47 using namespace Tizen::Base::Collection;
48 using namespace Tizen::Io;
49
50 namespace
51 {
52
53 const wchar_t ACTL_DEFAULT_FILE[] = L"/usr/etc/app-control-info.ini";
54 const wchar_t ACTL_LEGACY_FILE[] = L"/usr/etc/app-control-alias.ini";
55 const wchar_t ACTL_ALIAS_FILE[] = L"/usr/etc/app-control-appid.ini";
56
57 const wchar_t TIZEN_ALIAS_APPID_PREFIX[] = L"tizen.";
58
59 const String ACTL_REGISTRY_PATH = L"Path";
60 const String ACTL_REGISTRY_ALIAS_PROVIDER = L"PROVIDER_ALIAS";
61
62 const int PKG_APPID_LEN = 256;
63 const int REG_VALUE_BUFFER_LEN = 256;
64
65 }
66
67
68 namespace Tizen { namespace App
69 {
70
71 _AppControlRegistry* _AppControlRegistry::__pSelf = null;
72
73 _AppControlRegistry::_AppControlRegistry(void)
74 {
75         __tizenList.Construct();
76
77         __aliasList.Construct();
78
79         __aliasAppId.Construct();
80
81         __runtimeAlias.Construct();
82 }
83
84 _AppControlRegistry::~_AppControlRegistry(void)
85 {
86         _DeleteCollectionMapValue<String, _AppControlAliasEntry>(__aliasList);
87
88         _DeleteCollection<_AppControlAliasEntry>(__runtimeAlias);
89 }
90
91 _AppControlRegistry*
92 _AppControlRegistry::GetInstance(void)
93 {
94         if (__pSelf == null)
95         {
96                 SysLog(NID_APP, "Create new instance");
97                 __pSelf = new (std::nothrow) _AppControlRegistry();
98                 SysTryReturn(NID_APP, __pSelf != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
99                 SysAssertf(__pSelf != null, "AppControl registry instance creation failure");
100
101                 __pSelf->LoadTizenAppControlRegistry();
102
103                 __pSelf->LoadLegacyList();
104
105                 __pSelf->LoadAliasList();
106         }
107
108         return __pSelf;
109 }
110
111
112 result
113 _AppControlRegistry::LoadTizenAppControlRegistry(void)
114 {
115         _RegistryImpl reg;
116
117         const String regPath = ACTL_DEFAULT_FILE;
118
119         result r = reg.Construct(regPath, REG_OPEN_READ_ONLY, null);
120         SysTryReturn(NID_APP, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
121
122         const int secCount = reg.GetAllSectionCount();
123         SysTryReturnResult(NID_APP, !(secCount <= 0), E_OBJ_NOT_FOUND, "Registry contains no data.");
124
125         SysLog(NID_APP, "Loading %d sections from %ls", secCount, regPath.GetPointer());
126
127         int index = 0;
128         int size = 0;
129         //int num = 0;
130         String path;
131
132         for (int i = 0; i < secCount; i++)
133         {
134                 ///////////////////////////////////////////////////////////////////////
135                 // appcontrol Id
136                 String sec_name(reg.GetSectionName(i));
137                 sec_name.Trim();
138
139                 if (sec_name.IsEmpty())
140                 {
141                         continue;
142                 }
143
144                 ///////////////////////////////////////////////////////////////////////
145                 // Path
146                 index = reg.GetEntryIndex(i, ACTL_REGISTRY_PATH);
147                 if (index >= 0)
148                 {
149                         size = REG_VALUE_BUFFER_LEN;
150                         reg.GetEntryValue(i, index, REG_VALUE_TYPE_STRING, &path, &size);
151                 }
152
153                 __tizenList.Add(sec_name, path);
154         }
155
156         SysLog(NID_APP, "Finished loading %d tizen AppControl entries", __tizenList.GetCount());
157
158         return E_SUCCESS;
159 }
160
161 result
162 _AppControlRegistry::LoadLegacyList(void)
163 {
164         _RegistryImpl reg;
165
166         const String& regPath(ACTL_LEGACY_FILE);
167
168         result r = reg.Construct(regPath, REG_OPEN_READ_ONLY, null);
169         SysTryReturn(NID_APP, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
170
171         const int sec_count = reg.GetAllSectionCount();
172         SysTryReturnResult(NID_APP, !(sec_count <= 0), E_OBJ_NOT_FOUND, "Registry contains no data.");
173
174         SysLog(NID_APP, "Loading %d sections from %ls", sec_count, regPath.GetPointer());
175
176         String aliasProvider;
177         String value;
178
179
180         // actual parameter manipulation
181         for (int i = 0; i < sec_count; i++)
182         {
183                 ///////////////////////////////////////////////////////////////////////
184                 // appcontrol Id
185                 const String& secName(reg.GetSectionName(i));
186
187                 ///////////////////////////////////////////////////////////////////////
188                 // aliased appcontrol name
189                 const int index = reg.GetEntryIndex(i, ACTL_REGISTRY_ALIAS_PROVIDER);
190                 if (index >= 0)
191                 {
192                         int size = REG_VALUE_BUFFER_LEN;
193                         reg.GetEntryValue(i, index, REG_VALUE_TYPE_STRING, &aliasProvider, &size);
194                 }
195
196                 ///////////////////////////////////////////////////////////////////////
197                 // Operations
198                 IList* pList = reg.GetAllEntryNamesN(secName);
199                 if (pList == null)
200                 {
201                         continue;
202                 }
203
204                 std::unique_ptr<IEnumerator> pEnum(pList->GetEnumeratorN());
205
206                 while (pEnum->MoveNext() == E_SUCCESS)
207                 {
208                         String* pStr = dynamic_cast<String*>(pEnum->GetCurrent());
209
210                         if (pStr == null || pStr->IsEmpty() || pStr->Equals(ACTL_REGISTRY_ALIAS_PROVIDER, false))
211                         {
212                                 continue;
213                         }
214
215                         r = reg.GetValue(secName, *pStr, value);
216                         if (IsFailed(r))
217                         {
218                                 SysLog(NID_APP, "[%s] Propagating.", GetErrorMessage(r));
219                                 continue;
220                         }
221
222                         // add entry to aliasList
223                         _AppControlAliasEntry* pEntry = new (std::nothrow) _AppControlAliasEntry(secName, *pStr, aliasProvider, value);
224                         SysTryReturnResult(NID_APP, pEntry != null, E_OUT_OF_MEMORY, "Insufficient memory.");
225
226                         if (pEntry)
227                         {
228                                 SysLog(NID_APP, "(%ls, %ls)", secName.GetPointer(), aliasProvider.GetPointer());
229                                 __aliasList.Add(secName, pEntry);
230                         }
231                 }
232
233                 pList->RemoveAll(true);
234                 delete pList;
235         }
236
237         SysLog(NID_APP, "Finished loading %d entries.", __aliasList.GetCount());
238
239         return E_SUCCESS;
240 }
241
242 result
243 _AppControlRegistry::LoadAliasList(void)
244 {
245         _RegistryImpl reg;
246
247         const String regPath = ACTL_ALIAS_FILE;
248
249         result r = reg.Construct(regPath, REG_OPEN_READ_ONLY, null);
250         SysTryReturn(NID_APP, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
251
252         HashMap* pMap = null;
253         r = reg.GetEntryListN(L"Alias", &pMap);
254         if (r != E_SUCCESS)
255         {
256                 SysLog(NID_APP, "[%s] Propagating.", GetErrorMessage(r));
257                 pMap->RemoveAll(true);
258                 delete pMap;
259                 return r;
260         }
261
262         String* pKey = null;
263         String* pVal = null;
264         std::unique_ptr<IMapEnumerator> pEnum(pMap->GetMapEnumeratorN());
265         SysTryCatch(NID_APP, pEnum.get(), r = E_OUT_OF_MEMORY , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory error.");
266
267         while(pEnum->MoveNext() == E_SUCCESS)
268         {
269                 pKey = static_cast<String*>(pEnum->GetKey());
270                 pVal = static_cast<String*>(pEnum->GetValue());
271
272                 __aliasAppId.Add(*pKey, *pVal);
273                 //SysLog(NID_APP, "(%ls, %ls)", pKey->GetPointer(), pVal->GetPointer());
274         }
275
276         SysLog(NID_APP, "Loading %d alias sections", __aliasAppId.GetCount());
277
278 CATCH:
279         pMap->RemoveAll(true);
280         delete pMap;
281
282         return r;
283 }
284
285
286 AppControl*
287 _AppControlRegistry::GetTizenAppControlN(const String& aId, const String& oId) const
288 {
289         int count = 0;
290         const String* pAppId = &aId;
291         const String* pOperation = &oId;
292         do
293         {
294                 const _AppControlAliasEntry* const pEntry = GetAppControlAliasEntry(*pAppId, *pOperation);
295                 // number does not matter
296                 if (count >= 5 || pEntry == null)
297                 {
298                         break;
299                 }
300
301                 pAppId = &pEntry->provider2;
302                 pOperation = &pEntry->operation2;
303                 count++;
304         }
305         while (true);
306
307
308         SysAssert(pAppId != null);
309         SysAssert(pOperation != null);
310
311         SysLog(NID_APP, "Found matching AppControl (%ls, %ls)", pAppId->GetPointer(), pOperation->GetPointer());
312
313         const String& soName = GetTizenAppControlProvider(*pAppId, *pOperation);
314
315         if (soName.IsEmpty())
316         {
317                 AppControl* pAc = GetAppControlN(*pAppId, *pOperation);
318                 if (pAc)
319                 {
320                         _AppControlImpl* pImpl = _AppControlImpl::GetInstance(*pAc);
321                         pImpl->SetProperty(_APPCONTROL_PROPERTY_ALIAS);
322
323                         const _AppControlAliasEntry* pLookupEntry = GetReverseRuntimeAliasEntry(*pAppId, *pOperation);
324                         if (pLookupEntry == null)
325                         {
326                                 // no entry found : add new one
327                                 _AppControlAliasEntry* pEntry = new (std::nothrow) _AppControlAliasEntry(aId, oId, *pAppId, *pOperation);
328                                 if (pEntry)
329                                 {
330                                         // may fail
331                                         __runtimeAlias.Add(pEntry);
332                                         SysLog(NID_APP, "Setting alias app (%ls -> %ls).", aId.GetPointer(), pAppId->GetPointer());
333                                 }
334                         }
335                 }
336                 else
337                 {
338                         SysLog(NID_APP, "No AppControl instance for (%ls, %ls)", pAppId->GetPointer(), pOperation->GetPointer());
339                 }
340                 return pAc;
341         }
342
343         return _AppControlImpl::CreateN(soName, *pAppId, *pOperation, L"", _APPCONTROL_PROPERTY_PUBLIC | _APPCONTROL_PROPERTY_SLP);
344 }
345
346
347 String
348 _AppControlRegistry::GetTizenAppControlProvider(const String& appId, const String& oId) const
349 {
350         String val;
351         result r = __tizenList.GetValue(appId, val);
352         if (r == E_SUCCESS)
353         {
354                 SysLog(NID_APP, "Found TIZEN AppControl stub %ls for %ls.", val.GetPointer(), appId.GetPointer());
355                 return val;
356         }
357
358         SysLog(NID_APP, "No platform AppControl and use custom AppControl instead.");
359         return L"";
360 }
361
362
363 //
364 // data structure for _AppControlRegistry::FindAppControlListN() only
365 //
366 struct AppSvcIterData
367 {
368 public:
369         AppSvcIterData(ArrayList* pArr, const String& op) : pArray(pArr), operation(op) {}
370
371         ArrayList* pArray;
372         const String& operation;
373 };
374
375 //
376 // callback function for _AppControlRegistry::FindAppControlListN()
377 //
378 static int
379 AppSvcIterFnCb(const char* pAppId, void* pData)
380 {
381         SysAssert(pData != null);
382
383         AppSvcIterData* pAppSvcIterData = static_cast<AppSvcIterData*>(pData);
384         ArrayList* pList = pAppSvcIterData->pArray;
385         SysAssert(pList != null);
386         const String& operation = pAppSvcIterData->operation;
387
388         if (pAppId == NULL)
389         {
390                 SysLog(NID_APP, "Empty appId received.");
391                 return -1;
392         }
393
394         String appId = pAppId;
395         AppControl* pAc = _AppControlImpl::CreateN(appId, operation, false);
396         if (pAc == null)
397         {
398                 SysLog(NID_APP, "AppControl allocation failure for %ls.", appId.GetPointer());
399                 return -1;
400         }
401
402         pList->Add(pAc);
403
404         return 0;
405 }
406
407 Tizen::Base::Collection::ArrayList*
408 _AppControlRegistry::FindAppControlListN(const String* pOid, const String* pUri, const String* pMimeType, const String* pCategory) const
409 {
410         String operation = (pOid) ? *pOid : TIZEN_OPERATION_MAIN;
411
412         std::unique_ptr<bundle, BundleDeleter> pBundle(bundle_create());
413         SysTryReturn(NID_APP, pBundle.get(), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Bundle creation failure.");
414
415         _AppMessageImpl::SetOperation(pBundle.get(), operation);
416
417         if (pUri)
418         {
419                 _AppMessageImpl::SetUri(pBundle.get(), *pUri);
420         }
421
422         if (pMimeType)
423         {
424                 _AppMessageImpl::SetMime(pBundle.get(), *pMimeType);
425         }
426
427         if (pCategory)
428         {
429                 _AppMessageImpl::SetCategory(pBundle.get(), *pCategory);
430         }
431
432         ArrayList* pList = new (std::nothrow) ArrayList;
433         SysTryReturn(NID_APP, pList != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] ArrayList creation failure.");
434         pList->Construct();
435
436         AppSvcIterData data(pList, operation);
437
438         appsvc_get_list(pBundle.get(), AppSvcIterFnCb, reinterpret_cast<void*>(&data));
439
440         if (pList->GetCount() == 0)
441         {
442                 SysLog(NID_APP, "Found no AppControl entry for operation %ls.", operation.GetPointer());
443
444                 delete pList;
445                 pList = null;
446         }
447
448         return pList;
449 }
450
451 const _AppControlRegistry::_AppControlAliasEntry*
452 _AppControlRegistry::GetAppControlAliasEntry(const String& aId, const String& oId) const
453 {
454         std::unique_ptr< IEnumeratorT<_AppControlAliasEntry*> > pEnum(__aliasList.GetValuesN(aId));
455         if (pEnum.get() == null)
456         {
457                 SysLog(NID_APP, "[E_OBJ_NOT_FOUND] No alias entry for %ls.", aId.GetPointer());
458                 return null;
459         }
460
461         while (pEnum->MoveNext() == E_SUCCESS)
462         {
463                 _AppControlAliasEntry* pEntry = null;
464                 pEnum->GetCurrent(pEntry);
465                 if (pEntry->provider == aId && pEntry->operation == oId)
466                 {
467                         SysLog(NID_APP, "Found matching AppControl (%ls, %ls)->(%ls, %ls)", aId.GetPointer(), oId.GetPointer(), pEntry->provider2.GetPointer(), pEntry->operation2.GetPointer());
468
469                         return pEntry;
470                 }
471         }
472
473         return null;
474 }
475
476
477 const _AppControlRegistry::_AppControlAliasEntry*
478 _AppControlRegistry::GetReverseAppControlAliasEntry(const String& aId, const String& oId) const
479 {
480         std::unique_ptr< IMapEnumeratorT<String, _AppControlAliasEntry*> > pEnum(__aliasList.GetMapEnumeratorN());
481
482         while (pEnum->MoveNext() == E_SUCCESS)
483         {
484                 _AppControlAliasEntry* pEntry = null;
485                 pEnum->GetValue(pEntry);
486                 if (pEntry->provider2 == aId && pEntry->operation2 == oId)
487                 {
488                         SysLog(NID_APP, "Found matching AppControl (%ls, %ls)<-(%ls, %ls)", aId.GetPointer(), oId.GetPointer(), pEntry->provider.GetPointer(), pEntry->operation.GetPointer());
489
490                         return pEntry;
491                 }
492         }
493
494         return null;
495 }
496
497
498 const _AppControlRegistry::_AppControlAliasEntry*
499 _AppControlRegistry::GetReverseRuntimeAliasEntry(const String& aId, const String& oId) const
500 {
501         std::unique_ptr< IEnumeratorT<_AppControlAliasEntry*> > pEnum(__runtimeAlias.GetEnumeratorN());
502
503         while (pEnum->MoveNext() == E_SUCCESS)
504         {
505                 _AppControlAliasEntry* pEntry = null;
506                 pEnum->GetCurrent(pEntry);
507                 if (pEntry->provider2 == aId && pEntry->operation2 == oId)
508                 {
509                         SysLog(NID_APP, "Found matching AppControl (%ls, %ls)->(%ls, %ls)", aId.GetPointer(), oId.GetPointer(), pEntry->provider2.GetPointer(), pEntry->operation2.GetPointer());
510
511                         return pEntry;
512                 }
513         }
514
515         return null;
516 }
517
518
519 AppControl*
520 _AppControlRegistry::GetAppControlN(const String& appId, const String& operationId) const
521 {
522         bool changeAppId = false;
523
524         String actualAppId = appId;
525         if (appId.StartsWith(TIZEN_ALIAS_APPID_PREFIX, 0))
526         {
527                 const String& tmp = GetAliasAppId(appId);
528
529                 if (!tmp.IsEmpty())
530                 {
531                         actualAppId = tmp;
532                         SysLog(NID_APP, "Found alias app (%ls -> %ls).", appId.GetPointer(), tmp.GetPointer());
533
534                         changeAppId = true;
535                 }
536         }
537
538         bool b = _Aul::IsInstalled(actualAppId);
539         SysTryReturn(NID_APP, b == true, null, E_APP_NOT_INSTALLED, "[E_APP_NOT_INSTALLED] %ls not installed.", actualAppId.GetPointer());
540
541         return _AppControlImpl::CreateN(actualAppId, operationId, changeAppId);
542 }
543
544
545 AppId
546 _AppControlRegistry::GetAliasAppId(const AppId& appId) const
547 {
548         String tmp;
549         result r = __aliasAppId.GetValue(appId, tmp);
550         if (r != E_SUCCESS)
551         {
552                 tmp.Clear();
553         }
554
555         return tmp;
556 }
557
558
559 AppId
560 _AppControlRegistry::GetReverseAliasAppId(const AppId& appId) const
561 {
562         std::unique_ptr< IMapEnumeratorT<String, String> > pEnum(__aliasAppId.GetMapEnumeratorN());
563
564         String key;
565         String value;
566         while (pEnum->MoveNext() == E_SUCCESS)
567         {
568                 pEnum->GetKey(key);
569                 pEnum->GetValue(value);
570                 if (value == appId)
571                 {
572                         return key;
573                 }
574         }
575
576         SysLog(NID_APP, "No entry found for %ls", appId.GetPointer());
577         return L"";
578 }
579
580
581 } } // Tizen::App