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