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