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