sync with master
[platform/framework/native/appfw.git] / src / app / FApp_AppInfo.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_AppInfo.cpp
20  * @brief       This is the implementation for the _AppInfo.cpp class.
21  */
22
23 #include <cstdio>
24 #include <cstring>
25 #include <unistd.h>
26 #include <limits.h>
27 #include <new>
28 #include <fcntl.h>
29
30 #include <FBaseErrors.h>
31 #include <FAppPkgPackageInfo.h>
32
33 #include <FBaseSysLog.h>
34 #include <FBaseRt_Process.h>
35
36 #include "FAppPkg_PackageInfoImpl.h"
37 #include "FApp_AppInfo.h"
38 #include "FApp_Aul.h"
39 #include "FApp_AppArg.h"
40
41 using namespace Tizen::App::Package;
42 using namespace Tizen::Base;
43 using namespace Tizen::Base::Runtime;
44
45 extern "C"
46 {
47 void _OSP_EXPORT_
48 InitAppInfo(const char* appId, const char* svcId, int argc, char* pArgv[], int fd)
49 {
50         result r = Tizen::App::_AppInfo::GetAppInfo()->Construct(appId, svcId, argc, pArgv);
51         if (IsFailed(r))
52         {
53                 SysLogException(NID_APP, E_SYSTEM, "Application initialization failure for %s.", appId);
54                 fprintf(stderr, "Application initialization failure for %s.\n", appId);
55
56                 _Process::Exit(-1);
57         }
58 }
59
60 void _OSP_EXPORT_
61 InitWebAppInfo(const char* appId, const char* rootPath)
62 {
63         result r = Tizen::App::_AppInfo::GetAppInfo()->Construct(appId, rootPath, Tizen::App::_APP_TYPE_WEB_APP);
64         if (IsFailed(r))
65         {
66                 SysLogException(NID_APP, E_SYSTEM, "Application initialization failure for %s.", appId);
67                 fprintf(stderr, "Application initialization failure for %s.\n", appId);
68
69                 _Process::Exit(-1);
70         }
71 }
72
73 extern void FBase_Initialize(void);
74
75 }
76
77 namespace Tizen { namespace App
78 {
79
80 const int MAX_APIVERSION = 8;
81 const int MAX_APPID = 10;
82 const char PACKAGE_PATH_FORMAT2[] = "/opt/apps/0000000000/";
83 const char PATH_ROOT[] = "/opt/apps/";
84 const char APPINFO_FILE_PATH[] = "info/version.info";
85 const char COMPAT_FILE_PATH[] = "info/compat.info";
86 const char TYPE_FILE_PATH[] = "info/type.info";
87
88
89 _AppInfo::_AppInfo(void)
90         : __appState(TERMINATED)
91         , __appType(_APP_TYPE_UI_APP)
92         , __appRootDirFd(-1)
93         , __appHandlerType(_APP_HANDLER_NONE)
94         , __parentWindowHandle(-1)
95         , __apiVersion(_API_VERSION_2_1)
96         , __pAppName(null)
97         , __pAppVersion(null)
98         , __argc(0)
99         , __pArgv(null)
100         , __isPackageInfoInitialized(false)
101         , __isOspCompat(false)
102         , __isSubMode(false)
103 {
104         SysStaticAssert(sizeof(pid_t) == sizeof(int));
105
106         //FBase_Initialize();
107 }
108
109 _AppInfo::~_AppInfo(void)
110 {
111         delete __pAppName;
112         delete __pAppVersion;
113 }
114
115 _AppInfo*
116 _AppInfo::GetAppInfo(void)
117 {
118         static _AppInfo info;
119
120         return &info;
121 }
122
123
124 result
125 _AppInfo::Construct(const char* appId, const char* exeName, int argc, char* argv[])
126 {
127         SysAssertf(appId != null, "Valid appId required to launch application.");
128
129      FBase_Initialize();
130
131         __appExecutableName = exeName;
132         __packageId = appId;
133
134         if (__appExecutableName == L"_AppControl")
135         {
136                 SysLog(NID_APP, "Handling for submode.");
137                 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(__packageId);
138
139                 __isSubMode = true;
140                 __appExecutableName = name;
141                 SysLog(NID_APP, "Executable name is changed to %ls.", __appExecutableName.GetPointer());
142         }
143
144         __appId = __packageId + L'.' + __appExecutableName;
145
146         result r = E_SUCCESS;
147         FILE* pFile = NULL;
148
149         {
150                 const int len = strlen(PACKAGE_PATH_FORMAT2);
151                 char appInfoPath[len + 1];
152                 strncpy(appInfoPath, PACKAGE_PATH_FORMAT2, len);
153                 appInfoPath[len] = '\0';
154
155                 // due to possible dependency problem, FIoFile is not used
156                 // app root path first
157
158                 strncpy(appInfoPath + strlen(PATH_ROOT), appId, MAX_APPID);
159
160                 // app root directory file descriptor
161                 __appRootDirFd = open(appInfoPath, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
162
163                 __appRootPath = appInfoPath;
164                 
165                 SysLog(NID_APP, "App root directory (%s:%d) open.", appInfoPath, __appRootDirFd);
166
167                 int fd = openat(__appRootDirFd, APPINFO_FILE_PATH, O_RDONLY);
168                 SysAssert(fd != -1);
169
170                 pFile = fdopen(fd, "r");
171                 SysTryCatch(NID_APP, pFile != NULL, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Opening appinfo file (%s) failed : %s.", appInfoPath, strerror(errno));
172
173                 char apiVersion[MAX_APIVERSION] = {0, };
174                 char* pRet = fgets(apiVersion, MAX_APIVERSION - 1, pFile);
175                 SysTryCatch(NID_APP, pRet != NULL, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Reading appinfo file (%s) failed : %s.", appInfoPath, strerror(errno));
176
177                 fclose(pFile);
178                 // fd is closed when the stream is closed by fclose();
179
180                 __apiVersion = GetApiVersionFromStr(apiVersion);
181
182                 __argc = argc;
183                 __pArgv = argv;
184
185                 // to reduce package manager overhead, libc API is used
186                 if (faccessat(__appRootDirFd, COMPAT_FILE_PATH, F_OK, 0) == 0)
187                 {
188                         SysLog(NID_APP, "OSP compatibility mode on.");
189                         __isOspCompat = true;
190                 }
191
192                 // type file may does not exist
193                 fd = openat(__appRootDirFd, TYPE_FILE_PATH, O_RDONLY);
194                 if (fd > 0)
195                 {
196                         pFile = fdopen(fd, "r");
197                         if (pFile)
198                         {
199                                 int i;
200                                 int line = fscanf(pFile, "%d", &i);
201
202                                 fclose(pFile);
203                                 // fd is closed when the stream is closed by fclose();
204
205                                 __appType = _APP_TYPE_UI_APP | i;
206                                 SysLog(NID_APP, "Reading app type %d -> %d", i, __appType);
207                         }
208                 }
209
210                 SysLog(NID_APP, "AppInfo initialization finished [%ls][%ls.%ls][%d].",
211                                 __appId.GetPointer(), __packageId.GetPointer(), __appExecutableName.GetPointer(), __apiVersion);
212         }
213
214         return E_SUCCESS;
215
216 CATCH:
217         __appId.Clear();
218         __appExecutableName.Clear();
219
220         delete __pAppName;
221         __pAppName = null;
222
223         delete __pAppVersion;
224         __pAppVersion = null;
225
226         if (pFile != NULL)
227         {
228                 fclose(pFile);
229         }
230
231         return r;
232 }
233
234
235 // initialize app context only
236 result
237 _AppInfo::Construct(const char* appId, const char* appRoot, _AppType type)
238 {
239         SysAssertf(appId != null, "Valid appId required to launch application.");
240
241      FBase_Initialize();
242
243         __appId = appId;
244
245         int index = 0;
246         if (__appId.LastIndexOf(L'.', __appId.GetLength() - 1, index) == E_SUCCESS)
247         {
248                 __appId.SubString(index + 1, __appExecutableName);
249                 __appId.SubString(0, index, __packageId);
250         }
251         else
252         {
253                 __appExecutableName = __appId;
254                 __packageId = __appId;
255         }
256
257         __appRootDirFd = open(appRoot, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
258         __apiVersion = _API_VERSION_2_1;
259         __appType = type;
260
261         __appRootPath = appRoot;
262         if (__appRootPath[__appRootPath.GetLength()] != L'/')
263         {
264                 __appRootPath.Append(L'/');
265         }
266
267         SysLog(NID_APP, "AppInfo initialization finished [%ls][%ls.%ls][%ls][%d].", __appId.GetPointer(), __packageId.GetPointer(), __appExecutableName.GetPointer(), __appRootPath.GetPointer(),  __apiVersion);
268
269         return E_SUCCESS;
270 }
271
272
273 result
274 _AppInfo::UpdateAppInfoFromPackageInfo(const PackageId& packageId)
275 {
276         _PackageManagerImpl* pPkg = null;
277         pPkg = _PackageManagerImpl::GetInstance();
278         SysTryReturnResult(NID_APP, pPkg != null, E_INVALID_STATE, "Invalid PackageManager instance.");
279
280         result r = E_SUCCESS;
281         PackageInfo* pInfo = null;
282         pInfo = pPkg->GetPackageInfoN(packageId);
283         SysTryReturn(NID_APP, pInfo != null, r, r, "[%s] Propagating.", GetErrorMessage(r));
284
285         const _PackageInfoImpl* pPkgInfo = _PackageInfoImpl::GetInstance(pInfo);
286         SysTryReturnResult(NID_APP, pPkgInfo != null, E_INVALID_STATE, "Invalid PackageInfo instance.");
287
288         delete __pAppName;
289         __pAppName = new (std::nothrow) String(pPkgInfo->GetName());
290         SysTryCatch(NID_APP, __pAppName != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] AppName allocation failure.");
291
292         delete __pAppVersion;
293         __pAppVersion = new (std::nothrow) String(pPkgInfo->GetVersion());
294         SysTryCatch(NID_APP, __pAppVersion != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] AppVersion allocation failure.");
295
296         __isPackageInfoInitialized = true;
297
298         delete pInfo;
299
300         SysLog(NID_APP, "AppInfo updated [%ls][%ls].", __pAppName->GetPointer(), __pAppVersion->GetPointer());
301
302         return r;
303
304 CATCH:
305         delete pInfo;
306
307         delete __pAppName;
308         __pAppName = null;
309
310         delete __pAppVersion;
311         __pAppVersion = null;
312
313         return r;
314 }
315
316
317 // [FIXME] refactoring to use hash
318 _ApiVersion
319 _AppInfo::GetApiVersionFromStr(const char* pVer)
320 {
321         String ver(pVer);
322         ver.Trim();
323
324         if (ver == L"3.0")
325         {
326                 return _API_VERSION_2_1;
327         }
328         else if (ver == L"2.0")
329         {
330                 return _API_VERSION_2_0;
331         }
332         else if (ver == L"1.2")
333         {
334                 return _API_VERSION_1_2;
335         }
336         else if (ver == L"1.1")
337         {
338                 return _API_VERSION_1_1;
339         }
340         else if (ver == L"1.0.2")
341         {
342                 return _API_VERSION_1_0_2;
343         }
344         else if (ver == L"1.0")
345         {
346                 return _API_VERSION_1_0;
347         }
348         else
349         {
350                 return _API_VERSION_2_1;
351         }
352 }
353
354
355 _ApiVersion
356 _AppInfo::GetApiVersion(void)
357 {
358         return GetAppInfo()->__apiVersion;
359 }
360
361
362 bool
363 _AppInfo::IsOspCompat(void)
364 {
365         return GetAppInfo()->__isOspCompat;
366 }
367
368
369 result
370 _AppInfo::SetApiVersion(_ApiVersion v)
371 {
372         GetAppInfo()->__apiVersion = v;
373         return E_SUCCESS;
374 }
375
376
377 int
378 _AppInfo::GetProcessId(void)
379 {
380         static int processId = static_cast<int>(getpid());
381
382         return processId;
383 }
384
385 int
386 _AppInfo::GetAppRootDirFd(void)
387 {
388         return GetAppInfo()->__appRootDirFd;
389 }
390
391
392 AppId
393 _AppInfo::GetApplicationId(void)
394 {
395         const String& appId = GetAppInfo()->__appId;
396
397         SysAssertf(!appId.IsEmpty(), "AppId is not initialized properly.");
398
399         return appId;
400 }
401
402
403 PackageId
404 _AppInfo::GetPackageId(void)
405 {
406         const String& packageId = GetAppInfo()->__packageId;
407
408         SysAssertf(!packageId.IsEmpty(), "PackageId is not initialized properly.");
409
410         return packageId;
411 }
412
413
414 String
415 _AppInfo::GetAppExecutableName(void)
416 {
417         return GetAppInfo()->__appExecutableName;
418 }
419
420
421 bool
422 _AppInfo::IsSubMode(void)
423 {
424         return GetAppInfo()->__isSubMode;
425 }
426
427
428 String
429 _AppInfo::GetAppName(void)
430 {
431         if (!GetAppInfo()->__isPackageInfoInitialized)
432         {
433                 const String& packageId = GetAppInfo()->__packageId;
434
435                 SysAssertf(!packageId.IsEmpty(), "PackageId is not initialized properly.");
436
437                 result r = GetAppInfo()->UpdateAppInfoFromPackageInfo(packageId);
438                 SysAssertf(r == E_SUCCESS, "AppInfo update failure due to package problem.");
439         }
440
441         return *(GetAppInfo()->__pAppName);
442 }
443
444
445 String
446 _AppInfo::GetAppRootPath(void)
447 {
448         return GetAppInfo()->__appRootPath;
449 }
450
451 String
452 _AppInfo::GetAppVersion(void)
453 {
454         if (!GetAppInfo()->__isPackageInfoInitialized)
455         {
456                 const String& packageId = GetAppInfo()->__packageId;
457
458                 SysAssertf(!packageId.IsEmpty(), "PackageId is not initialized properly.");
459
460                 result r = GetAppInfo()->UpdateAppInfoFromPackageInfo(packageId);
461                 SysAssertf(r == E_SUCCESS, "AppInfo update failure due to package problem.");
462         }
463
464         return *(GetAppInfo()->__pAppVersion);
465 }
466
467
468 AppState
469 _AppInfo::GetAppState(void)
470 {
471         return GetAppInfo()->__appState;
472 }
473
474
475 void
476 _AppInfo::SetAppState(AppState appState)
477 {
478         GetAppInfo()->__appState = appState;
479 }
480
481
482 int
483 _AppInfo::GetAppType(void)
484 {
485         return GetAppInfo()->__appType;
486 }
487
488
489 void
490 _AppInfo::SetAppType(_AppType appType)
491 {
492         GetAppInfo()->__appType |= appType;
493 }
494
495
496 int
497 _AppInfo::GetArgc(void)
498 {
499         return GetAppInfo()->__argc;
500 }
501
502
503 char**
504 _AppInfo::GetArgv(void)
505 {
506         return GetAppInfo()->__pArgv;
507 }
508
509
510 int
511 _AppInfo::GetAppHandlerType(void)
512 {
513         return GetAppInfo()->__appHandlerType;
514 }
515
516
517 void
518 _AppInfo::SetAppHandlerType(int appHandlerType)
519 {
520         GetAppInfo()->__appHandlerType = appHandlerType;
521 }
522
523
524 unsigned int
525 _AppInfo::GetParentWindowHandle(void)
526 {
527         return GetAppInfo()->__parentWindowHandle;
528 }
529
530
531 void
532 _AppInfo::SetParentWindowHandle(unsigned int handle)
533 {
534         GetAppInfo()->__parentWindowHandle = handle;
535 }
536
537
538 void
539 _AppInfo::UpdatePackageInfo(bool update)
540 {
541         GetAppInfo()->__isPackageInfoInitialized = !update;
542 }
543
544 }} // Tizen::App