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