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