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