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