Merge "[2.2.1] Apply reviewed header file (Base to Collection)" into tizen_2.2
[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 #include <unique_ptr.h>
29
30 #include <appinfo.h>
31
32 #include <FBaseErrors.h>
33 #include <FAppPkgPackageInfo.h>
34 #include <FBaseSysLog.h>
35
36 #include <FBaseRt_Process.h>
37 #include <FBase_StringConverter.h>
38
39 #include "FAppPkg_PackageInfoImpl.h"
40 #include "FApp_AppInfo.h"
41
42 using namespace Tizen::App::Package;
43 using namespace Tizen::Base;
44 using namespace Tizen::Base::Runtime;
45
46 extern "C"
47 {
48 void _OSP_EXPORT_
49 AppInfo_Update(void)
50 {
51         result r = Tizen::App::_AppInfo::GetInstance()->Construct();
52         if (IsFailed(r))
53         {
54                 SysLogException(NID_APP, E_SYSTEM, "Application initialization failure.");
55                 fprintf(stderr, "Application initialization failure.\n");
56
57                 _Process::Exit(-1);
58         }
59 }
60
61 void _OSP_EXPORT_
62 InitAppInfo(const char* packageId, const char* svcId, int argc, char* pArgv[], int fd)
63 {
64         AppInfo_Update();
65 }
66
67 void _OSP_EXPORT_
68 InitWebAppInfo(const char* appId, const char* rootPath)
69 {
70         result r = Tizen::App::_AppInfo::GetInstance()->Construct(appId, rootPath, Tizen::App::_APP_TYPE_WEB_APP);
71         if (IsFailed(r))
72         {
73                 SysLogException(NID_APP, E_SYSTEM, "Application initialization failure for %s.", appId);
74                 fprintf(stderr, "Application initialization failure for %s.\n", appId);
75
76                 _Process::Exit(-1);
77         }
78 }
79
80 extern void FBase_Initialize(void);
81
82 }
83
84 namespace Tizen { namespace App
85 {
86
87 const int MAX_APIVERSION = 8;
88 const int MAX_APPID = 10;
89 const char PACKAGE_PATH_FORMAT[] = "/opt/usr/apps/0000000000/";
90 const char PATH_ROOT[] = "/opt/usr/apps/";
91 const char APPINFO_FILE_PATH[] = "info/version.info";
92 const char COMPAT_FILE_PATH[] = "info/compat.info";
93 const char VIRTUAL_ROOT_FILE_PATH[] = "info/virtual.info";
94 const char TYPE_FILE_PATH[] = "info/type.info";
95 const char SUBMODE_NAME[] = "_AppControl";
96
97
98 _AppInfo::_AppInfo(void)
99         : __appState(TERMINATED)
100         , __appType(_APP_TYPE_NONE)
101         , __appRootDirFd(-1)
102         , __appSdDirFd(-1)
103         , __appHandlerType(_APP_HANDLER_NONE)
104         , __parentWindowHandle(-1)
105         , __pAppName(null)
106         , __pAppVersion(null)
107         , __isPackageInfoInitialized(false)
108         , __isSubMode(false)
109         , __isVirtualRoot(false)
110         , __isMultiWindow(false)
111 {
112         SysStaticAssert(sizeof(pid_t) == sizeof(int));
113
114         //FBase_Initialize();
115 }
116
117 _AppInfo::~_AppInfo(void)
118 {
119         delete __pAppName;
120         delete __pAppVersion;
121
122         // closing may or may not succeed
123         close(__appRootDirFd);
124         close(__appSdDirFd);
125 }
126
127 _AppInfo*
128 _AppInfo::GetInstance(void)
129 {
130         static _AppInfo info;
131
132         return &info;
133 }
134
135
136 result
137 _AppInfo::Construct(void)
138 {
139         SysAssertf(appinfo_is_initialized() == 1, "appinfo is not initialized.");
140
141         FBase_Initialize();
142
143         const char* pPackageId = appinfo_get_packageid();
144         const char* pExecName = appinfo_get_execname();
145
146
147         if (strncmp(pExecName, SUBMODE_NAME, strlen(SUBMODE_NAME)) == 0)
148         {
149                 SysLog(NID_APP, "Handling for submode.");
150                 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(String(pPackageId));
151
152                 __isSubMode = true;
153
154                 std::unique_ptr<char[]> pActualExec(_StringConverter::CopyToCharArrayN(name));
155                 appinfo_update_submode_execname_and_appid(pActualExec.get());
156                 SysLog(NID_APP, "Executable name is changed to %s.", pActualExec.get());
157         }
158
159         result r = E_SUCCESS;
160         FILE* pFile = NULL;
161
162         {
163                 char appInfoPath[PATH_MAX] = {0, };
164
165                 int len = strlen(PACKAGE_PATH_FORMAT);
166                 strncpy(appInfoPath, PACKAGE_PATH_FORMAT, len);
167                 appInfoPath[len] = '\0';
168                 strncpy(appInfoPath + strlen(PATH_ROOT), pPackageId, MAX_APPID);
169
170                 // app root directory file descriptor
171                 __appRootDirFd = open(appInfoPath, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
172                 __appRootPath = appInfoPath;
173                 
174                 SysLog(NID_APP, "App root directory (%s:%d) open.", appInfoPath, __appRootDirFd);
175
176                 int fd = openat(__appRootDirFd, APPINFO_FILE_PATH, O_RDONLY);
177                 SysAssertf(fd != -1, "Failed to open info file, errno: %d (%s)", errno, strerror(errno));
178
179                 pFile = fdopen(fd, "r");
180                 SysTryCatch(NID_APP, pFile != NULL, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Opening appinfo file (%s) failed : %s.", appInfoPath, strerror(errno));
181
182                 // sdcard
183                 char sdInfoPath[PATH_MAX] = {0, };
184                 strncpy(sdInfoPath, "/opt/storage/sdcard/app2sd/", strlen("/opt/storage/sdcard/app2sd/"));
185                 strncat(sdInfoPath, pPackageId, MAX_APPID);
186
187                 __appSdDirFd = open(sdInfoPath, O_RDONLY);
188                 SysLog(NID_APP, "sd root directory (%s:%d) open.", sdInfoPath, __appSdDirFd);
189
190                 char apiVersion[MAX_APIVERSION] = {0, };
191                 char* pRet = fgets(apiVersion, MAX_APIVERSION - 1, pFile);
192                 SysTryCatch(NID_APP, pRet != NULL, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Reading appinfo file (%s) failed : %s.", appInfoPath, strerror(errno));
193
194                 fclose(pFile);
195                 // fd is closed when the stream is closed by fclose();
196
197                 appinfo_set_api_version(appinfo_get_api_version_from_str(apiVersion));
198
199                 // to reduce package manager overhead, libc API is used
200                 if (faccessat(__appRootDirFd, COMPAT_FILE_PATH, F_OK, 0) == 0)
201                 {
202                         SysLog(NID_APP, "OSP compatibility mode on.");
203                         appinfo_set_compat(1);
204                 }
205
206                 if (faccessat(__appRootDirFd, VIRTUAL_ROOT_FILE_PATH, F_OK, 0) == 0)
207                 {
208                         SysLog(NID_APP, "virtual root mode on.");
209                         __isVirtualRoot = 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 [%s][%s.%s][%d].", appinfo_get_appid(), appinfo_get_packageid(), appinfo_get_execname(), appinfo_get_api_version());
231         }
232
233         return E_SUCCESS;
234
235 CATCH:
236         if (pFile != NULL)
237         {
238                 fclose(pFile);
239         }
240
241         return r;
242 }
243
244
245 // initialize app context only
246 result
247 _AppInfo::Construct(const char* appId, const char* appRoot, _AppType type)
248 {
249         SysAssertf(appId != null, "Valid appId required to launch application.");
250
251         FBase_Initialize();
252
253         if (appinfo_is_initialized() == 0)
254         {
255                 appinfo_init(appId, 0);
256         }
257
258         __appRootDirFd = open(appRoot, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
259         appinfo_set_api_version(APP_INFO_VERSION_2_2);
260         __appType = type;
261
262         __appRootPath = appRoot;
263         if (__appRootPath[__appRootPath.GetLength()] != L'/')
264         {
265                 __appRootPath.Append(L'/');
266         }
267
268         SysLog(NID_APP, "AppInfo [%s][%s.%s][%ls][%d].", appinfo_get_appid(), appinfo_get_packageid(), appinfo_get_execname()), __appRootPath.GetPointer(), appinfo_get_api_version();
269
270         return E_SUCCESS;
271 }
272
273
274 result
275 _AppInfo::UpdateAppInfoFromPackageInfo(const PackageId& packageId)
276 {
277         _PackageManagerImpl* pPkg = _PackageManagerImpl::GetInstance();
278         SysTryReturnResult(NID_APP, pPkg != null, E_INVALID_STATE, "Invalid PackageManager instance.");
279
280         result r = E_SUCCESS;
281         std::unique_ptr<PackageInfo> pInfo(pPkg->GetPackageInfoN(packageId));
282         if (pInfo.get() == null)
283         {
284                 r = GetLastResult();
285                 SysPropagate(NID_APP, r);
286                 return r;
287         }
288
289         const _PackageInfoImpl* pPkgInfo = _PackageInfoImpl::GetInstance(pInfo.get());
290         SysTryReturnResult(NID_APP, pPkgInfo != null, E_INVALID_STATE, "Invalid PackageInfo instance.");
291
292         delete __pAppName;
293         __pAppName = new (std::nothrow) String(pPkgInfo->GetName());
294         SysTryCatch(NID_APP, __pAppName != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] AppName allocation failure.");
295
296         delete __pAppVersion;
297         __pAppVersion = new (std::nothrow) String(pPkgInfo->GetVersion());
298         SysTryCatch(NID_APP, __pAppVersion != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] AppVersion allocation failure.");
299
300         __isPackageInfoInitialized = true;
301
302         SysLog(NID_APP, "AppInfo updated [%ls][%ls].", __pAppName->GetPointer(), __pAppVersion->GetPointer());
303
304         return r;
305
306 CATCH:
307         delete __pAppName;
308         __pAppName = null;
309
310         delete __pAppVersion;
311         __pAppVersion = null;
312
313         return r;
314 }
315
316
317 _ApiVersion
318 _AppInfo::GetApiVersion(void)
319 {
320         return static_cast<_ApiVersion>(appinfo_get_api_version());
321 }
322
323
324 bool
325 _AppInfo::IsOspCompat(void)
326 {
327         return (appinfo_is_compat() == 1);
328 }
329
330 bool
331 _AppInfo::IsVirtualRoot(void)
332 {
333         return GetInstance()->__isVirtualRoot;
334 }
335
336 result
337 _AppInfo::SetApiVersion(_ApiVersion v)
338 {
339         appinfo_set_api_version(static_cast<app_info_version_e>(v));
340         return E_SUCCESS;
341 }
342
343
344 int
345 _AppInfo::GetProcessId(void)
346 {
347         static int processId = static_cast<int>(getpid());
348
349         return processId;
350 }
351
352 int
353 _AppInfo::GetAppRootDirFd(void)
354 {
355         return GetInstance()->__appRootDirFd;
356 }
357
358
359 AppId
360 _AppInfo::GetApplicationId(void)
361 {
362         return String(appinfo_get_appid());
363 }
364
365
366 PackageId
367 _AppInfo::GetPackageId(void)
368 {
369         return String(appinfo_get_packageid());
370 }
371
372
373 String
374 _AppInfo::GetAppExecutableName(void)
375 {
376         return String(appinfo_get_execname());
377 }
378
379
380 bool
381 _AppInfo::IsSubMode(void)
382 {
383         return GetInstance()->__isSubMode;
384 }
385
386
387 String
388 _AppInfo::GetAppName(void)
389 {
390         if (!GetInstance()->__isPackageInfoInitialized)
391         {
392                 const String& packageId = GetInstance()->GetPackageId();
393
394                 SysAssertf(!packageId.IsEmpty(), "PackageId is not initialized properly.");
395
396                 result r = GetInstance()->UpdateAppInfoFromPackageInfo(packageId);
397                 SysAssertf(r == E_SUCCESS, "AppInfo update failure due to package problem.");
398         }
399
400         return *(GetInstance()->__pAppName);
401 }
402
403
404 String
405 _AppInfo::GetAppRootPath(void)
406 {
407         return GetInstance()->__appRootPath;
408 }
409
410 String
411 _AppInfo::GetAppVersion(void)
412 {
413         if (!GetInstance()->__isPackageInfoInitialized)
414         {
415                 const String& packageId = GetInstance()->GetPackageId();
416
417                 SysAssertf(!packageId.IsEmpty(), "PackageId is not initialized properly.");
418
419                 result r = GetInstance()->UpdateAppInfoFromPackageInfo(packageId);
420                 SysAssertf(r == E_SUCCESS, "AppInfo update failure due to package problem.");
421         }
422
423         return *(GetInstance()->__pAppVersion);
424 }
425
426
427 AppState
428 _AppInfo::GetAppState(void)
429 {
430         return GetInstance()->__appState;
431 }
432
433
434 void
435 _AppInfo::SetAppState(AppState appState)
436 {
437         GetInstance()->__appState = appState;
438 }
439
440
441 int
442 _AppInfo::GetAppType(void)
443 {
444         return GetInstance()->__appType;
445 }
446
447
448 void
449 _AppInfo::SetAppType(_AppType appType)
450 {
451         GetInstance()->__appType |= appType;
452 }
453
454
455 int
456 _AppInfo::GetAppHandlerType(void)
457 {
458         return GetInstance()->__appHandlerType;
459 }
460
461
462 void
463 _AppInfo::SetAppHandlerType(int appHandlerType)
464 {
465         GetInstance()->__appHandlerType = appHandlerType;
466 }
467
468
469 unsigned int
470 _AppInfo::GetParentWindowHandle(void)
471 {
472         return GetInstance()->__parentWindowHandle;
473 }
474
475
476 void
477 _AppInfo::SetParentWindowHandle(unsigned int handle)
478 {
479         GetInstance()->__parentWindowHandle = handle;
480 }
481
482
483 void
484 _AppInfo::UpdatePackageInfo(bool update)
485 {
486         GetInstance()->__isPackageInfoInitialized = !update;
487 }
488
489 bool
490 _AppInfo::IsMultiWindow(void)
491 {
492         return GetInstance()->__isMultiWindow;
493 }
494
495 void
496 _AppInfo::SetMultiWindow(bool enable)
497 {
498         GetInstance()->__isMultiWindow = enable;
499 }
500
501 }} // Tizen::App