move general AppControl launch logic to plugin
[platform/framework/native/appfw.git] / src / app / FApp_AppControlRegistry.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file         FApp_AppControlRegistry.cpp
19  * @brief       This is the implementation for the _AppControlRegistry.cpp class.
20  */
21
22 #include <new>
23 #include <unique_ptr.h>
24 #include <bundle.h>
25 #include <appsvc.h>
26 #include <new>
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 "FApp_AppControlImpl.h"
40 #include "FApp_AppControlRegistry.h"
41 #include "FApp_AppMessageImpl.h"
42 #include "FApp_TemplateUtil.h"
43
44 using namespace Tizen::Base;
45 using namespace Tizen::Base::Collection;
46 using namespace Tizen::Io;
47
48 namespace
49 {
50
51 const wchar_t ACTL_DEFAULT_FILE[] = L"/usr/etc/app-control-info.ini";
52 const wchar_t ACTL_LEGACY_FILE[] = L"/usr/etc/app-control-alias.ini";
53 const wchar_t ACTL_DEFAULT_PLUGIN[] = L"libosp-ac-platform.so";
54
55 const wchar_t TIZEN_ALIAS_APPID_PREFIX[] = L"tizen.";
56
57 const String ACTL_REGISTRY_PATH = L"Path";
58 const String ACTL_REGISTRY_ALIAS_PROVIDER = L"PROVIDER_ALIAS";
59
60 const int PKG_APPID_LEN = 256;
61 const int REG_VALUE_BUFFER_LEN = 256;
62
63 }
64
65
66 namespace Tizen { namespace App
67 {
68
69 _AppControlRegistry* _AppControlRegistry::__pSelf = null;
70
71 _AppControlRegistry::_AppControlRegistry(void)
72 {
73         __tizenList.Construct();
74
75         __aliasList.Construct();
76 }
77
78 _AppControlRegistry::~_AppControlRegistry(void)
79 {
80         _DeleteCollectionMapValue<String, _AppControlAliasEntry>(__aliasList);
81 }
82
83 _AppControlRegistry*
84 _AppControlRegistry::GetInstance(void)
85 {
86         if (__pSelf == null)
87         {
88                 SysLog(NID_APP, "Create new instance");
89                 __pSelf = new (std::nothrow) _AppControlRegistry();
90                 SysTryReturn(NID_APP, __pSelf != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
91                 SysAssertf(__pSelf != null, "AppControl registry instance creation failure");
92
93                 __pSelf->LoadTizenAppControlRegistry();
94
95                 __pSelf->LoadLegacyList();
96         }
97
98         return __pSelf;
99 }
100
101
102 result
103 _AppControlRegistry::LoadTizenAppControlRegistry(void)
104 {
105         _RegistryImpl reg;
106
107         const String regPath = ACTL_DEFAULT_FILE;
108
109         result r = reg.Construct(regPath, REG_OPEN_READ_ONLY, null);
110         SysTryReturn(NID_APP, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
111
112         const int secCount = reg.GetAllSectionCount();
113         SysTryReturnResult(NID_APP, !(secCount <= 0), E_OBJ_NOT_FOUND, "Registry contains no data.");
114
115         SysLog(NID_APP, "Loading %d sections from %ls", secCount, regPath.GetPointer());
116
117         int index = 0;
118         int size = 0;
119         //int num = 0;
120         String path;
121
122         for (int i = 0; i < secCount; i++)
123         {
124                 ///////////////////////////////////////////////////////////////////////
125                 // appcontrol Id
126                 String sec_name(reg.GetSectionName(i));
127                 sec_name.Trim();
128
129                 if (sec_name.IsEmpty())
130                 {
131                         continue;
132                 }
133
134                 ///////////////////////////////////////////////////////////////////////
135                 // Path
136                 index = reg.GetEntryIndex(i, ACTL_REGISTRY_PATH);
137                 if (index >= 0)
138                 {
139                         size = REG_VALUE_BUFFER_LEN;
140                         reg.GetEntryValue(i, index, REG_VALUE_TYPE_STRING, &path, &size);
141                 }
142
143                 __tizenList.Add(sec_name, path);
144         }
145
146         SysLog(NID_APP, "Finished loading %d tizen AppControl entries", __tizenList.GetCount());
147
148         return E_SUCCESS;
149 }
150
151 result
152 _AppControlRegistry::LoadLegacyList(void)
153 {
154         _RegistryImpl reg;
155
156         const String& regPath(ACTL_LEGACY_FILE);
157
158         result r = reg.Construct(regPath, REG_OPEN_READ_ONLY, null);
159         SysTryReturn(NID_APP, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
160
161         const int sec_count = reg.GetAllSectionCount();
162         SysTryReturnResult(NID_APP, !(sec_count <= 0), E_OBJ_NOT_FOUND, "Registry contains no data.");
163
164         SysLog(NID_APP, "Loading %d sections from %ls", sec_count, regPath.GetPointer());
165
166         String aliasProvider;
167         String value;
168
169
170         // actual parameter manipulation
171         for (int i = 0; i < sec_count; i++)
172         {
173                 ///////////////////////////////////////////////////////////////////////
174                 // appcontrol Id
175                 const String& secName(reg.GetSectionName(i));
176
177                 ///////////////////////////////////////////////////////////////////////
178                 // aliased appcontrol name
179                 const int index = reg.GetEntryIndex(i, ACTL_REGISTRY_ALIAS_PROVIDER);
180                 if (index >= 0)
181                 {
182                         int size = REG_VALUE_BUFFER_LEN;
183                         reg.GetEntryValue(i, index, REG_VALUE_TYPE_STRING, &aliasProvider, &size);
184                 }
185
186                 ///////////////////////////////////////////////////////////////////////
187                 // Operations
188                 IList* pList = reg.GetAllEntryNamesN(secName);
189                 if (pList == null)
190                 {
191                         continue;
192                 }
193
194                 std::unique_ptr<IEnumerator> pEnum(pList->GetEnumeratorN());
195
196                 while (pEnum->MoveNext() == E_SUCCESS)
197                 {
198                         String* pStr = dynamic_cast<String*>(pEnum->GetCurrent());
199
200                         if (pStr == null || pStr->IsEmpty() || pStr->Equals(ACTL_REGISTRY_ALIAS_PROVIDER, false))
201                         {
202                                 continue;
203                         }
204
205                         r = reg.GetValue(secName, *pStr, value);
206                         if (IsFailed(r))
207                         {
208                                 SysLog(NID_APP, "[%s] Propagating.", GetErrorMessage(r));
209                                 continue;
210                         }
211
212                         // add entry to aliasList
213                         _AppControlAliasEntry* pEntry = new (std::nothrow) _AppControlAliasEntry(secName, *pStr, aliasProvider, value);
214                         SysTryReturnResult(NID_APP, pEntry != null, E_OUT_OF_MEMORY, "Insufficient memory.");
215
216                         if (pEntry)
217                         {
218                                 SysLog(NID_APP, "(%ls, %ls)", secName.GetPointer(), aliasProvider.GetPointer());
219                                 __aliasList.Add(secName, pEntry);
220                         }
221                 }
222
223                 pList->RemoveAll(true);
224                 delete pList;
225         }
226
227         SysLog(NID_APP, "Finished loading %d entries.", __aliasList.GetCount());
228
229         return E_SUCCESS;
230 }
231
232
233 AppControl*
234 _AppControlRegistry::GetTizenAppControlN(const String& aId, const String& oId) const
235 {
236         int count = 0;
237         const String* pAppId = &aId;
238         const String* pOperation = &oId;
239
240         // legacy check first
241         do
242         {
243                 const _AppControlAliasEntry* const pEntry = GetAppControlAliasEntry(*pAppId, *pOperation);
244                 // number does not matter
245                 if (count >= 5 || pEntry == null)
246                 {
247                         break;
248                 }
249
250                 pAppId = &pEntry->provider2;
251                 pOperation = &pEntry->operation2;
252                 count++;
253         }
254         while (true);
255
256
257         SysAssert(pAppId != null);
258         SysAssert(pOperation != null);
259
260         SysLog(NID_APP, "Found matching AppControl (%ls, %ls)", pAppId->GetPointer(), pOperation->GetPointer());
261
262         const String& soName = GetTizenAppControlProvider(*pAppId, *pOperation);
263         SysAssert(!soName.IsEmpty());
264
265         return _AppControlImpl::CreateN(soName, *pAppId, *pOperation, _APPCONTROL_PROPERTY_PUBLIC);
266 }
267
268
269 String
270 _AppControlRegistry::GetTizenAppControlProvider(const String& appId, const String& oId) const
271 {
272         String val;
273         result r = __tizenList.GetValue(appId, val);
274         if (r == E_SUCCESS)
275         {
276                 SysLog(NID_APP, "Found TIZEN AppControl stub %ls for %ls.", val.GetPointer(), appId.GetPointer());
277                 return val;
278         }
279
280         SysLog(NID_APP, "Default platform AppControl %ls is used.", ACTL_DEFAULT_PLUGIN);
281         return String(ACTL_DEFAULT_PLUGIN);
282 }
283
284
285 //
286 // data structure for _AppControlRegistry::FindAppControlListN() only
287 //
288 struct AppSvcIterData
289 {
290 public:
291         AppSvcIterData(const _AppControlRegistry* pRegs, ArrayList* pArr, const String& op) : pThis(pRegs), pArray(pArr), operation(op) {}
292
293         const _AppControlRegistry* pThis;
294         ArrayList* pArray;
295         const String& operation;
296 };
297
298 //
299 // callback function for _AppControlRegistry::FindAppControlListN()
300 //
301 static int
302 AppSvcIterFnCb(const char* pAppId, void* pData)
303 {
304         SysAssert(pData != null);
305
306         AppSvcIterData* pAppSvcIterData = static_cast<AppSvcIterData*>(pData);
307         ArrayList* pList = pAppSvcIterData->pArray;
308         SysAssert(pList != null);
309         const _AppControlRegistry* pThis = pAppSvcIterData->pThis;
310         SysAssert(pThis != null);
311         const String& operation = pAppSvcIterData->operation;
312
313         if (pAppId == NULL)
314         {
315                 SysLog(NID_APP, "Empty appId received.");
316                 return -1;
317         }
318
319         String appId = pAppId;
320         AppControl* pAc = pThis->GetTizenAppControlN(appId, operation);
321         if (pAc == null)
322         {
323                 SysLog(NID_APP, "AppControl allocation failure for %ls.", appId.GetPointer());
324                 return -1;
325         }
326
327         pList->Add(pAc);
328
329         return 0;
330 }
331
332 Tizen::Base::Collection::ArrayList*
333 _AppControlRegistry::FindAppControlListN(const String* pOid, const String* pUri, const String* pMimeType, const String* pCategory) const
334 {
335         String operation = (pOid) ? *pOid : TIZEN_OPERATION_MAIN;
336
337         std::unique_ptr<bundle, BundleDeleter> pBundle(bundle_create());
338         SysTryReturn(NID_APP, pBundle.get(), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Bundle creation failure.");
339
340         _AppMessageImpl::SetOperation(pBundle.get(), operation);
341
342         if (pUri)
343         {
344                 _AppMessageImpl::SetUri(pBundle.get(), *pUri);
345         }
346
347         if (pMimeType)
348         {
349                 _AppMessageImpl::SetMime(pBundle.get(), *pMimeType);
350         }
351
352         if (pCategory)
353         {
354                 _AppMessageImpl::SetCategory(pBundle.get(), *pCategory);
355         }
356
357         ArrayList* pList = new (std::nothrow) ArrayList;
358         SysTryReturn(NID_APP, pList != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] ArrayList creation failure.");
359         pList->Construct();
360
361         AppSvcIterData data(this, pList, operation);
362
363         appsvc_get_list(pBundle.get(), AppSvcIterFnCb, reinterpret_cast<void*>(&data));
364
365         if (pList->GetCount() == 0)
366         {
367                 SysLog(NID_APP, "Found no AppControl entry for operation %ls.", operation.GetPointer());
368
369                 delete pList;
370                 pList = null;
371         }
372
373         return pList;
374 }
375
376 const _AppControlRegistry::_AppControlAliasEntry*
377 _AppControlRegistry::GetAppControlAliasEntry(const String& aId, const String& oId) const
378 {
379         std::unique_ptr< IEnumeratorT<_AppControlAliasEntry*> > pEnum(__aliasList.GetValuesN(aId));
380         if (pEnum.get() == null)
381         {
382                 SysLog(NID_APP, "[E_OBJ_NOT_FOUND] No alias entry for %ls.", aId.GetPointer());
383                 return null;
384         }
385
386         while (pEnum->MoveNext() == E_SUCCESS)
387         {
388                 _AppControlAliasEntry* pEntry = null;
389                 pEnum->GetCurrent(pEntry);
390                 if (pEntry->provider == aId && pEntry->operation == oId)
391                 {
392                         SysLog(NID_APP, "Found matching AppControl (%ls, %ls)->(%ls, %ls)", aId.GetPointer(), oId.GetPointer(), pEntry->provider2.GetPointer(), pEntry->operation2.GetPointer());
393
394                         return pEntry;
395                 }
396         }
397
398         return null;
399 }
400
401
402 AppId
403 _AppControlRegistry::GetAliasAppId(const AppId& appId) const
404 {
405         std::unique_ptr<bundle, BundleDeleter> pBundle(bundle_create());
406
407         if (pBundle.get())
408         {
409                 std::unique_ptr<char[]> pAppId(_StringConverter::CopyToCharArrayN(appId));
410
411                 // appsvc_set_appid() lookup for actual app ID internally
412                 appsvc_set_appid(pBundle.get(), pAppId.get());
413                 const char* pTmp = appsvc_get_appid(pBundle.get());
414
415                 if (pTmp)
416                 {
417                         return String(pTmp);
418                 }
419         }
420
421         return String();
422 }
423
424 } } // Tizen::App