Modify DataControl manager for thread-safe
[platform/framework/native/appfw.git] / src / app / FApp_AppInfo.cpp
index 9f44c33..bb8d05a 100644 (file)
 #include <limits.h>
 #include <new>
 #include <fcntl.h>
+#include <unique_ptr.h>
+
+#include <appinfo.h>
 
 #include <FBaseErrors.h>
 #include <FAppPkgPackageInfo.h>
-
 #include <FBaseSysLog.h>
+
 #include <FBaseRt_Process.h>
+#include <FBase_StringConverter.h>
 
 #include "FAppPkg_PackageInfoImpl.h"
-#include "FApp_AppInfo.h"
 #include "FApp_Aul.h"
-#include "FApp_AppArg.h"
+#include "FApp_AppInfo.h"
 
 using namespace Tizen::App::Package;
 using namespace Tizen::Base;
@@ -44,22 +47,28 @@ using namespace Tizen::Base::Runtime;
 extern "C"
 {
 void _OSP_EXPORT_
-InitAppInfo(const char* appId, const char* svcId, int argc, char* pArgv[], int fd)
+AppInfo_Update(void)
 {
-       result r = Tizen::App::_AppInfo::GetAppInfo()->Construct(appId, svcId, argc, pArgv);
+       result r = Tizen::App::_AppInfo::GetInstance()->Construct();
        if (IsFailed(r))
        {
-               SysLogException(NID_APP, E_SYSTEM, "Application initialization failure for %s.", appId);
-               fprintf(stderr, "Application initialization failure for %s.\n", appId);
+               SysLogException(NID_APP, E_SYSTEM, "Application initialization failure.");
+               fprintf(stderr, "Application initialization failure.\n");
 
                _Process::Exit(-1);
        }
 }
 
 void _OSP_EXPORT_
+InitAppInfo(const char* packageId, const char* svcId, int argc, char* pArgv[], int fd)
+{
+       AppInfo_Update();
+}
+
+void _OSP_EXPORT_
 InitWebAppInfo(const char* appId, const char* rootPath)
 {
-       result r = Tizen::App::_AppInfo::GetAppInfo()->Construct(appId, rootPath, Tizen::App::_APP_TYPE_WEB_APP);
+       result r = Tizen::App::_AppInfo::GetInstance()->Construct(appId, rootPath, Tizen::App::_APP_TYPE_WEB_APP);
        if (IsFailed(r))
        {
                SysLogException(NID_APP, E_SYSTEM, "Application initialization failure for %s.", appId);
@@ -79,28 +88,27 @@ namespace Tizen { namespace App
 const int MAX_APIVERSION = 8;
 const int MAX_APPID = 10;
 const char PACKAGE_PATH_FORMAT[] = "/opt/usr/apps/0000000000/";
-const char PACKAGE_PATH_FORMAT2[] = "/opt/apps/0000000000/";
 const char PATH_ROOT[] = "/opt/usr/apps/";
-const char PATH_ROOT2[] = "/opt/apps/";
 const char APPINFO_FILE_PATH[] = "info/version.info";
 const char COMPAT_FILE_PATH[] = "info/compat.info";
+const char VIRTUAL_ROOT_FILE_PATH[] = "info/virtual.info";
 const char TYPE_FILE_PATH[] = "info/type.info";
+const char SUBMODE_NAME[] = "_AppControl";
 
 
 _AppInfo::_AppInfo(void)
        : __appState(TERMINATED)
        , __appType(_APP_TYPE_NONE)
        , __appRootDirFd(-1)
+       , __appSdDirFd(-1)
        , __appHandlerType(_APP_HANDLER_NONE)
        , __parentWindowHandle(-1)
-       , __apiVersion(_API_VERSION_2_1)
        , __pAppName(null)
        , __pAppVersion(null)
-       , __argc(0)
-       , __pArgv(null)
        , __isPackageInfoInitialized(false)
-       , __isOspCompat(false)
        , __isSubMode(false)
+       , __isVirtualRoot(false)
+       , __isMultiWindow(false)
 {
        SysStaticAssert(sizeof(pid_t) == sizeof(int));
 
@@ -114,10 +122,11 @@ _AppInfo::~_AppInfo(void)
 
        // closing may or may not succeed
        close(__appRootDirFd);
+       close(__appSdDirFd);
 }
 
 _AppInfo*
-_AppInfo::GetAppInfo(void)
+_AppInfo::GetInstance(void)
 {
        static _AppInfo info;
 
@@ -126,60 +135,45 @@ _AppInfo::GetAppInfo(void)
 
 
 result
-_AppInfo::Construct(const char* appId, const char* exeName, int argc, char* argv[])
+_AppInfo::Construct(void)
 {
-       SysAssertf(appId != null, "Valid appId required to launch application.");
+       SysAssertf(appinfo_is_initialized() == 1, "appinfo is not initialized.");
 
-     FBase_Initialize();
+       FBase_Initialize();
 
-       __appExecutableName = exeName;
-       __packageId = appId;
+       const char* pPackageId = appinfo_get_packageid();
+       const char* pExecName = appinfo_get_execname();
 
-       if (__appExecutableName == L"_AppControl")
+       if (strncmp(pExecName, SUBMODE_NAME, strlen(SUBMODE_NAME)) == 0)
        {
                SysLog(NID_APP, "Handling for submode.");
-               const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(__packageId);
 
-               __isSubMode = true;
-               __appExecutableName = name;
-               SysLog(NID_APP, "Executable name is changed to %ls.", __appExecutableName.GetPointer());
+               const char* pAppId = appinfo_get_appid();
+               const String& mainId = _Aul::GetMainAppId(pAppId);
+               if (!mainId.IsEmpty())
+               {
+                       std::unique_ptr<char[]> pMainId(_StringConverter::CopyToCharArrayN(mainId));
+                       appinfo_update_submode_appid(pMainId.get());
+               
+                       __isSubMode = true;
+               
+                       SysLog(NID_APP, "Executable name is changed to %s.", pMainId.get());
+               }
        }
 
-       __appId = __packageId + L'.' + __appExecutableName;
-
        result r = E_SUCCESS;
        FILE* pFile = NULL;
 
        {
                char appInfoPath[PATH_MAX] = {0, };
-#if 0
-               const int len = strlen(PACKAGE_PATH_FORMAT2);
-               strncpy(appInfoPath, PACKAGE_PATH_FORMAT2, len);
-               appInfoPath[len] = '\0';
-
-               // due to possible dependency problem, FIoFile is not used
-               // app root path first
 
-               strncpy(appInfoPath + strlen(PATH_ROOT2), appId, MAX_APPID);
-#else
-               // [FIXME] temporary code for directory location migration
-               int len = strlen(PACKAGE_PATH_FORMAT2);
-               strncpy(appInfoPath, PACKAGE_PATH_FORMAT2, len);
+               int len = strlen(PACKAGE_PATH_FORMAT);
+               strncpy(appInfoPath, PACKAGE_PATH_FORMAT, len);
                appInfoPath[len] = '\0';
-               strncpy(appInfoPath + strlen(PATH_ROOT2), appId, MAX_APPID);
+               strncpy(appInfoPath + strlen(PATH_ROOT), pPackageId, MAX_APPID);
 
-               if (euidaccess(appInfoPath, R_OK) != 0)
-               {
-                       len = strlen(PACKAGE_PATH_FORMAT);
-                       strncpy(appInfoPath, PACKAGE_PATH_FORMAT, len);
-                       appInfoPath[len] = '\0';
-                       
-                       strncpy(appInfoPath + strlen(PATH_ROOT), appId, MAX_APPID);
-               }
-#endif
                // app root directory file descriptor
                __appRootDirFd = open(appInfoPath, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
-
                __appRootPath = appInfoPath;
                
                SysLog(NID_APP, "App root directory (%s:%d) open.", appInfoPath, __appRootDirFd);
@@ -190,6 +184,14 @@ _AppInfo::Construct(const char* appId, const char* exeName, int argc, char* argv
                pFile = fdopen(fd, "r");
                SysTryCatch(NID_APP, pFile != NULL, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Opening appinfo file (%s) failed : %s.", appInfoPath, strerror(errno));
 
+               // sdcard
+               char sdInfoPath[PATH_MAX] = {0, };
+               strncpy(sdInfoPath, "/opt/storage/sdcard/app2sd/", strlen("/opt/storage/sdcard/app2sd/"));
+               strncat(sdInfoPath, pPackageId, MAX_APPID);
+
+               __appSdDirFd = open(sdInfoPath, O_RDONLY);
+               SysLog(NID_APP, "sd root directory (%s:%d) open.", sdInfoPath, __appSdDirFd);
+
                char apiVersion[MAX_APIVERSION] = {0, };
                char* pRet = fgets(apiVersion, MAX_APIVERSION - 1, pFile);
                SysTryCatch(NID_APP, pRet != NULL, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Reading appinfo file (%s) failed : %s.", appInfoPath, strerror(errno));
@@ -197,16 +199,19 @@ _AppInfo::Construct(const char* appId, const char* exeName, int argc, char* argv
                fclose(pFile);
                // fd is closed when the stream is closed by fclose();
 
-               __apiVersion = GetApiVersionFromStr(apiVersion);
-
-               __argc = argc;
-               __pArgv = argv;
+               appinfo_set_api_version(appinfo_get_api_version_from_str(apiVersion));
 
                // to reduce package manager overhead, libc API is used
                if (faccessat(__appRootDirFd, COMPAT_FILE_PATH, F_OK, 0) == 0)
                {
                        SysLog(NID_APP, "OSP compatibility mode on.");
-                       __isOspCompat = true;
+                       appinfo_set_compat(1);
+               }
+
+               if (faccessat(__appRootDirFd, VIRTUAL_ROOT_FILE_PATH, F_OK, 0) == 0)
+               {
+                       SysLog(NID_APP, "virtual root mode on.");
+                       __isVirtualRoot = true;
                }
 
                // type file may does not exist
@@ -227,22 +232,12 @@ _AppInfo::Construct(const char* appId, const char* exeName, int argc, char* argv
                        }
                }
 
-               SysLog(NID_APP, "AppInfo initialization finished [%ls][%ls.%ls][%d].",
-                               __appId.GetPointer(), __packageId.GetPointer(), __appExecutableName.GetPointer(), __apiVersion);
+               SysLog(NID_APP, "AppInfo [%s][%s.%s][%d].", appinfo_get_appid(), appinfo_get_packageid(), appinfo_get_execname(), appinfo_get_api_version());
        }
 
        return E_SUCCESS;
 
 CATCH:
-       __appId.Clear();
-       __appExecutableName.Clear();
-
-       delete __pAppName;
-       __pAppName = null;
-
-       delete __pAppVersion;
-       __pAppVersion = null;
-
        if (pFile != NULL)
        {
                fclose(pFile);
@@ -258,24 +253,15 @@ _AppInfo::Construct(const char* appId, const char* appRoot, _AppType type)
 {
        SysAssertf(appId != null, "Valid appId required to launch application.");
 
-     FBase_Initialize();
-
-       __appId = appId;
+       FBase_Initialize();
 
-       int index = 0;
-       if (__appId.LastIndexOf(L'.', __appId.GetLength() - 1, index) == E_SUCCESS)
+       if (appinfo_is_initialized() == 0)
        {
-               __appId.SubString(index + 1, __appExecutableName);
-               __appId.SubString(0, index, __packageId);
-       }
-       else
-       {
-               __appExecutableName = __appId;
-               __packageId = __appId;
+               appinfo_init(appId, 0);
        }
 
        __appRootDirFd = open(appRoot, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
-       __apiVersion = _API_VERSION_2_1;
+       appinfo_set_api_version(APP_INFO_VERSION_2_2);
        __appType = type;
 
        __appRootPath = appRoot;
@@ -284,7 +270,7 @@ _AppInfo::Construct(const char* appId, const char* appRoot, _AppType type)
                __appRootPath.Append(L'/');
        }
 
-       SysLog(NID_APP, "AppInfo initialization finished [%ls][%ls.%ls][%ls][%d].", __appId.GetPointer(), __packageId.GetPointer(), __appExecutableName.GetPointer(), __appRootPath.GetPointer(),  __apiVersion);
+       SysLog(NID_APP, "AppInfo [%s][%s.%s][%ls][%d].", appinfo_get_appid(), appinfo_get_packageid(), appinfo_get_execname()), __appRootPath.GetPointer(), appinfo_get_api_version();
 
        return E_SUCCESS;
 }
@@ -293,16 +279,19 @@ _AppInfo::Construct(const char* appId, const char* appRoot, _AppType type)
 result
 _AppInfo::UpdateAppInfoFromPackageInfo(const PackageId& packageId)
 {
-       _PackageManagerImpl* pPkg = null;
-       pPkg = _PackageManagerImpl::GetInstance();
+       _PackageManagerImpl* pPkg = _PackageManagerImpl::GetInstance();
        SysTryReturnResult(NID_APP, pPkg != null, E_INVALID_STATE, "Invalid PackageManager instance.");
 
        result r = E_SUCCESS;
-       PackageInfo* pInfo = null;
-       pInfo = pPkg->GetPackageInfoN(packageId);
-       SysTryReturn(NID_APP, pInfo != null, r, r, "[%s] Propagating.", GetErrorMessage(r));
+       std::unique_ptr<PackageInfo> pInfo(pPkg->GetPackageInfoN(packageId));
+       if (pInfo.get() == null)
+       {
+               r = GetLastResult();
+               SysPropagate(NID_APP, r);
+               return r;
+       }
 
-       const _PackageInfoImpl* pPkgInfo = _PackageInfoImpl::GetInstance(pInfo);
+       const _PackageInfoImpl* pPkgInfo = _PackageInfoImpl::GetInstance(pInfo.get());
        SysTryReturnResult(NID_APP, pPkgInfo != null, E_INVALID_STATE, "Invalid PackageInfo instance.");
 
        delete __pAppName;
@@ -315,15 +304,11 @@ _AppInfo::UpdateAppInfoFromPackageInfo(const PackageId& packageId)
 
        __isPackageInfoInitialized = true;
 
-       delete pInfo;
-
        SysLog(NID_APP, "AppInfo updated [%ls][%ls].", __pAppName->GetPointer(), __pAppVersion->GetPointer());
 
        return r;
 
 CATCH:
-       delete pInfo;
-
        delete __pAppName;
        __pAppName = null;
 
@@ -334,66 +319,29 @@ CATCH:
 }
 
 
-// [FIXME] refactoring to use hash
-_ApiVersion
-_AppInfo::GetApiVersionFromStr(const char* pVer)
-{
-       String ver(pVer);
-       ver.Trim();
-
-       if (ver == L"2.2")
-       {
-               return _API_VERSION_2_2;
-       }
-       else if (ver == L"2.1")
-       {
-               return _API_VERSION_2_1;
-       }
-       else if (ver == L"2.0")
-       {
-               return _API_VERSION_2_0;
-       }
-       else if (ver == L"1.2")
-       {
-               return _API_VERSION_1_2;
-       }
-       else if (ver == L"1.1")
-       {
-               return _API_VERSION_1_1;
-       }
-       else if (ver == L"1.0.2")
-       {
-               return _API_VERSION_1_0_2;
-       }
-       else if (ver == L"1.0")
-       {
-               return _API_VERSION_1_0;
-       }
-       else
-       {
-               return _API_VERSION_2_2;
-       }
-}
-
-
 _ApiVersion
 _AppInfo::GetApiVersion(void)
 {
-       return GetAppInfo()->__apiVersion;
+       return static_cast<_ApiVersion>(appinfo_get_api_version());
 }
 
 
 bool
 _AppInfo::IsOspCompat(void)
 {
-       return GetAppInfo()->__isOspCompat;
+       return (appinfo_is_compat() == 1);
 }
 
+bool
+_AppInfo::IsVirtualRoot(void)
+{
+       return GetInstance()->__isVirtualRoot;
+}
 
 result
 _AppInfo::SetApiVersion(_ApiVersion v)
 {
-       GetAppInfo()->__apiVersion = v;
+       appinfo_set_api_version(static_cast<app_info_version_e>(v));
        return E_SUCCESS;
 }
 
@@ -409,160 +357,150 @@ _AppInfo::GetProcessId(void)
 int
 _AppInfo::GetAppRootDirFd(void)
 {
-       return GetAppInfo()->__appRootDirFd;
+       return GetInstance()->__appRootDirFd;
 }
 
 
 AppId
 _AppInfo::GetApplicationId(void)
 {
-       const String& appId = GetAppInfo()->__appId;
-
-       SysAssertf(!appId.IsEmpty(), "AppId is not initialized properly.");
-
-       return appId;
+       return String(appinfo_get_appid());
 }
 
 
 PackageId
 _AppInfo::GetPackageId(void)
 {
-       const String& packageId = GetAppInfo()->__packageId;
-
-       SysAssertf(!packageId.IsEmpty(), "PackageId is not initialized properly.");
-
-       return packageId;
+       return String(appinfo_get_packageid());
 }
 
 
 String
 _AppInfo::GetAppExecutableName(void)
 {
-       return GetAppInfo()->__appExecutableName;
+       return String(appinfo_get_execname());
 }
 
 
 bool
 _AppInfo::IsSubMode(void)
 {
-       return GetAppInfo()->__isSubMode;
+       return GetInstance()->__isSubMode;
 }
 
 
 String
 _AppInfo::GetAppName(void)
 {
-       if (!GetAppInfo()->__isPackageInfoInitialized)
+       if (!GetInstance()->__isPackageInfoInitialized)
        {
-               const String& packageId = GetAppInfo()->__packageId;
+               const String& packageId = GetInstance()->GetPackageId();
 
                SysAssertf(!packageId.IsEmpty(), "PackageId is not initialized properly.");
 
-               result r = GetAppInfo()->UpdateAppInfoFromPackageInfo(packageId);
+               result r = GetInstance()->UpdateAppInfoFromPackageInfo(packageId);
                SysAssertf(r == E_SUCCESS, "AppInfo update failure due to package problem.");
        }
 
-       return *(GetAppInfo()->__pAppName);
+       return *(GetInstance()->__pAppName);
 }
 
 
 String
 _AppInfo::GetAppRootPath(void)
 {
-       return GetAppInfo()->__appRootPath;
+       return GetInstance()->__appRootPath;
 }
 
 String
 _AppInfo::GetAppVersion(void)
 {
-       if (!GetAppInfo()->__isPackageInfoInitialized)
+       if (!GetInstance()->__isPackageInfoInitialized)
        {
-               const String& packageId = GetAppInfo()->__packageId;
+               const String& packageId = GetInstance()->GetPackageId();
 
                SysAssertf(!packageId.IsEmpty(), "PackageId is not initialized properly.");
 
-               result r = GetAppInfo()->UpdateAppInfoFromPackageInfo(packageId);
+               result r = GetInstance()->UpdateAppInfoFromPackageInfo(packageId);
                SysAssertf(r == E_SUCCESS, "AppInfo update failure due to package problem.");
        }
 
-       return *(GetAppInfo()->__pAppVersion);
+       return *(GetInstance()->__pAppVersion);
 }
 
 
 AppState
 _AppInfo::GetAppState(void)
 {
-       return GetAppInfo()->__appState;
+       return GetInstance()->__appState;
 }
 
 
 void
 _AppInfo::SetAppState(AppState appState)
 {
-       GetAppInfo()->__appState = appState;
+       GetInstance()->__appState = appState;
 }
 
 
 int
 _AppInfo::GetAppType(void)
 {
-       return GetAppInfo()->__appType;
+       return GetInstance()->__appType;
 }
 
 
 void
 _AppInfo::SetAppType(_AppType appType)
 {
-       GetAppInfo()->__appType |= appType;
-}
-
-
-int
-_AppInfo::GetArgc(void)
-{
-       return GetAppInfo()->__argc;
-}
-
-
-char**
-_AppInfo::GetArgv(void)
-{
-       return GetAppInfo()->__pArgv;
+       GetInstance()->__appType |= appType;
 }
 
 
 int
 _AppInfo::GetAppHandlerType(void)
 {
-       return GetAppInfo()->__appHandlerType;
+       return GetInstance()->__appHandlerType;
 }
 
 
 void
 _AppInfo::SetAppHandlerType(int appHandlerType)
 {
-       GetAppInfo()->__appHandlerType = appHandlerType;
+       GetInstance()->__appHandlerType = appHandlerType;
 }
 
 
 unsigned int
 _AppInfo::GetParentWindowHandle(void)
 {
-       return GetAppInfo()->__parentWindowHandle;
+       return GetInstance()->__parentWindowHandle;
 }
 
 
 void
 _AppInfo::SetParentWindowHandle(unsigned int handle)
 {
-       GetAppInfo()->__parentWindowHandle = handle;
+       GetInstance()->__parentWindowHandle = handle;
 }
 
 
 void
 _AppInfo::UpdatePackageInfo(bool update)
 {
-       GetAppInfo()->__isPackageInfoInitialized = !update;
+       GetInstance()->__isPackageInfoInitialized = !update;
+}
+
+bool
+_AppInfo::IsMultiWindow(void)
+{
+       return GetInstance()->__isMultiWindow;
+}
+
+void
+_AppInfo::SetMultiWindow(bool enable)
+{
+       GetInstance()->__isMultiWindow = enable;
 }
 
 }} // Tizen::App