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