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