Merge "Add store client appId for installation" into tizen_2.1
[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                 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         delete pMap;
308
309         return r;
310 }
311
312
313 AppControl*
314 _AppControlRegistry::GetTizenAppControlN(const String& aId, const String& oId)
315 {
316         int count = 0;
317         const String* pAppId = &aId;
318         const String* pOperation = &oId;
319         do
320         {
321                 const _AppControlAliasEntry* const pEntry = GetAppControlAliasEntry(*pAppId, *pOperation);
322                 // number does not matter
323                 if (count >= 5 || pEntry == null)
324                 {
325                         break;
326                 }
327
328                 pAppId = &pEntry->provider2;
329                 pOperation = &pEntry->operation2;
330                 count++;
331         }
332         while (true);
333
334
335         SysAssert(pAppId != null);
336         SysAssert(pOperation != null);
337
338         SysLog(NID_APP, "Found matching AppControl (%ls, %ls)", pAppId->GetPointer(), pOperation->GetPointer());
339
340         const String& soName = GetTizenAppControlProvider(*pAppId, *pOperation);
341
342         if (soName.IsEmpty())
343         {
344                 AppControl* pAc = GetAppControlN(*pAppId, *pOperation);
345                 if (pAc)
346                 {
347                         _AppControlImpl* pImpl = _AppControlImpl::GetInstance(*pAc);
348                         pImpl->SetProperty(_APPCONTROL_PROPERTY_ALIAS);
349
350                         const _AppControlAliasEntry* pLookupEntry = GetReverseRuntimeAliasEntry(*pAppId, *pOperation);
351                         if (pLookupEntry == null)
352                         {
353                                 // no entry found : add new one
354                                 _AppControlAliasEntry* pEntry = new (std::nothrow) _AppControlAliasEntry(aId, oId, *pAppId, *pOperation);
355                                 if (pEntry)
356                                 {
357                                         // may fail
358                                         __runtimeAlias.Add(pEntry);
359                                         SysLog(NID_APP, "Setting alias appId (%ls -> %ls).", aId.GetPointer(), pAppId->GetPointer());
360                                 }
361                         }
362                 }
363                 else
364                 {
365                         SysLog(NID_APP, "No AppControl instance for (%ls, %ls)", pAppId->GetPointer(), pOperation->GetPointer());
366                 }
367                 return pAc;
368         }
369
370         return _AppControlImpl::CreateN(soName, *pAppId, *pOperation, L"", _APPCONTROL_PROPERTY_PUBLIC | _APPCONTROL_PROPERTY_SLP);
371 }
372
373
374 String
375 _AppControlRegistry::GetTizenAppControlProvider(const String& appId, const String& oId) const
376 {
377         String val;
378         result r = __tizenList.GetValue(appId, val);
379         if (r == E_SUCCESS)
380         {
381                 SysLog(NID_APP, "Found TIZEN AppControl stub %ls for %ls.", val.GetPointer(), appId.GetPointer());
382                 return val;
383         }
384
385         SysLog(NID_APP, "No platform AppControl and use custom AppControl instead.");
386         return L"";
387 }
388
389
390 //
391 // data structure for _AppControlRegistry::FindAppControlListN() only
392 //
393 struct AppSvcIterData
394 {
395 public:
396         AppSvcIterData(ArrayList* pArr, const String& op) : pArray(pArr), operation(op) {}
397
398         ArrayList* pArray;
399         const String& operation;
400 };
401
402 //
403 // callback function for _AppControlRegistry::FindAppControlListN()
404 //
405 static int
406 AppSvcIterFnCb(const char* pAppId, void* pData)
407 {
408         SysAssert(pData != null);
409
410         AppSvcIterData* pAppSvcIterData = static_cast<AppSvcIterData*>(pData);
411         ArrayList* pList = pAppSvcIterData->pArray;
412         SysAssert(pList != null);
413         const String& operation = pAppSvcIterData->operation;
414
415         if (pAppId == NULL)
416         {
417                 SysLog(NID_APP, "Empty appId received.");
418                 return -1;
419         }
420
421         String appId = pAppId;
422         AppControl* pAc = _AppControlImpl::CreateN(appId, operation, false);
423         if (pAc == null)
424         {
425                 SysLog(NID_APP, "AppControl allocation failure for %ls.", appId.GetPointer());
426                 return -1;
427         }
428
429         pList->Add(pAc);
430
431         return 0;
432 }
433
434 Tizen::Base::Collection::ArrayList*
435 _AppControlRegistry::FindAppControlListN(const String* pOid, const String* pUri, const String* pMimeType, const String* pCategory) const
436 {
437         String operation = (pOid) ? *pOid : TIZEN_OPERATION_MAIN;
438
439         std::unique_ptr<bundle, BundleDeleter> pBundle(bundle_create());
440         SysTryReturn(NID_APP, pBundle.get(), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Bundle creation failure.");
441
442         _AppMessageImpl::SetOperation(pBundle.get(), operation);
443
444         if (pUri)
445         {
446                 _AppMessageImpl::SetUri(pBundle.get(), *pUri);
447         }
448
449         if (pMimeType)
450         {
451                 _AppMessageImpl::SetMime(pBundle.get(), *pMimeType);
452         }
453
454         if (pCategory)
455         {
456                 _AppMessageImpl::SetCategory(pBundle.get(), *pCategory);
457         }
458
459         ArrayList* pList = new (std::nothrow) ArrayList;
460         SysTryReturn(NID_APP, pList != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] ArrayList creation failure.");
461         pList->Construct();
462
463         AppSvcIterData data(pList, operation);
464
465         appsvc_get_list(pBundle.get(), AppSvcIterFnCb, reinterpret_cast<void*>(&data));
466
467         if (pList->GetCount() == 0)
468         {
469                 SysLog(NID_APP, "Found no AppControl entry for operation %ls.", operation.GetPointer());
470
471                 delete pList;
472                 pList = null;
473         }
474
475         return pList;
476 }
477
478 const _AppControlRegistry::_AppControlAliasEntry*
479 _AppControlRegistry::GetAppControlAliasEntry(const String& aId, const String& oId) const
480 {
481         std::unique_ptr< IEnumeratorT<_AppControlAliasEntry*> > pEnum(__aliasList.GetValuesN(aId));
482         if (pEnum.get() == null)
483         {
484                 SysLog(NID_APP, "[E_OBJ_NOT_FOUND] No alias entry for %ls.", aId.GetPointer());
485                 return null;
486         }
487
488         while (pEnum->MoveNext() == E_SUCCESS)
489         {
490                 _AppControlAliasEntry* pEntry = null;
491                 pEnum->GetCurrent(pEntry);
492                 if (pEntry->provider == aId && pEntry->operation == oId)
493                 {
494                         SysLog(NID_APP, "Found matching AppControl (%ls, %ls)->(%ls, %ls)", aId.GetPointer(), oId.GetPointer(), pEntry->provider2.GetPointer(), pEntry->operation2.GetPointer());
495
496                         return pEntry;
497                 }
498         }
499
500         return null;
501 }
502
503
504 const _AppControlRegistry::_AppControlAliasEntry*
505 _AppControlRegistry::GetReverseAppControlAliasEntry(const String& aId, const String& oId) const
506 {
507         std::unique_ptr< IMapEnumeratorT<String, _AppControlAliasEntry*> > pEnum(__aliasList.GetMapEnumeratorN());
508
509         while (pEnum->MoveNext() == E_SUCCESS)
510         {
511                 _AppControlAliasEntry* pEntry = null;
512                 pEnum->GetValue(pEntry);
513                 if (pEntry->provider2 == aId && pEntry->operation2 == oId)
514                 {
515                         SysLog(NID_APP, "Found matching AppControl (%ls, %ls)<-(%ls, %ls)", aId.GetPointer(), oId.GetPointer(), pEntry->provider.GetPointer(), pEntry->operation.GetPointer());
516
517                         return pEntry;
518                 }
519         }
520
521         return null;
522 }
523
524
525 const _AppControlRegistry::_AppControlAliasEntry*
526 _AppControlRegistry::GetReverseRuntimeAliasEntry(const String& aId, const String& oId) const
527 {
528         std::unique_ptr< IEnumeratorT<_AppControlAliasEntry*> > pEnum(__runtimeAlias.GetEnumeratorN());
529
530         while (pEnum->MoveNext() == E_SUCCESS)
531         {
532                 _AppControlAliasEntry* pEntry = null;
533                 pEnum->GetCurrent(pEntry);
534                 if (pEntry->provider2 == aId && pEntry->operation2 == oId)
535                 {
536                         SysLog(NID_APP, "Found matching AppControl (%ls, %ls)->(%ls, %ls)", aId.GetPointer(), oId.GetPointer(), pEntry->provider2.GetPointer(), pEntry->operation2.GetPointer());
537
538                         return pEntry;
539                 }
540         }
541
542         return null;
543 }
544
545
546 AppControl*
547 _AppControlRegistry::GetAppControlN(const String& appId, const String& operationId) const
548 {
549         bool changeAppId = false;
550
551         String actualAppId = appId;
552         if (appId.StartsWith(TIZEN_ALIAS_APPID_PREFIX, 0))
553         {
554                 const String& tmp = GetAliasAppId(appId);
555
556                 if (!tmp.IsEmpty())
557                 {
558                         actualAppId = tmp;
559                         SysLog(NID_APP, "Found alias appId (%ls -> %ls).", appId.GetPointer(), tmp.GetPointer());
560
561                         changeAppId = true;
562                 }
563         }
564
565         bool b = _Aul::IsInstalled(actualAppId);
566         SysTryReturn(NID_APP, b == true, null, E_APP_NOT_INSTALLED, "[E_APP_NOT_INSTALLED] %ls not installed.", actualAppId.GetPointer());
567
568         return _AppControlImpl::CreateN(actualAppId, operationId, changeAppId);
569 }
570
571
572 AppId
573 _AppControlRegistry::GetAliasAppId(const AppId& appId) const
574 {
575         String tmp;
576         result r = __aliasAppId.GetValue(appId, tmp);
577         if (r != E_SUCCESS)
578         {
579                 tmp.Clear();
580         }
581
582         return tmp;
583 }
584
585
586 AppId
587 _AppControlRegistry::GetReverseAliasAppId(const AppId& appId) const
588 {
589         std::unique_ptr< IMapEnumeratorT<String, String> > pEnum(__aliasAppId.GetMapEnumeratorN());
590
591         String key;
592         String value;
593         while (pEnum->MoveNext() == E_SUCCESS)
594         {
595                 pEnum->GetKey(key);
596                 pEnum->GetValue(value);
597                 if (value == appId)
598                 {
599                         return key;
600                 }
601         }
602
603         SysLog(NID_APP, "No entry found for %ls", appId.GetPointer());
604         return L"";
605 }
606
607
608 } } // Tizen::App