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