Upstream version 10.38.210.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / common / application_data.cc
index 5ecdad2..7ef3f00 100644 (file)
@@ -28,6 +28,7 @@
 #include "xwalk/application/common/manifest_handler.h"
 #include "xwalk/application/common/manifest_handlers/permissions_handler.h"
 #include "xwalk/application/common/manifest_handlers/widget_handler.h"
+#include "xwalk/application/common/manifest_handlers/tizen_application_handler.h"
 #include "xwalk/application/common/permission_policy_manager.h"
 #include "content/public/common/url_constants.h"
 #include "url/url_util.h"
@@ -42,75 +43,35 @@ namespace application {
 
 // static
 scoped_refptr<ApplicationData> ApplicationData::Create(
-    const base::FilePath& path,
-    Manifest::SourceType source_type,
-    const base::DictionaryValue& manifest_data,
-    const std::string& explicit_id,
+    const base::FilePath& path, const std::string& explicit_id,
+    SourceType source_type, scoped_ptr<Manifest> manifest,
     std::string* error_message) {
   DCHECK(error_message);
   base::string16 error;
-  scoped_ptr<xwalk::application::Manifest> manifest(
-      new xwalk::application::Manifest(source_type,
-                 scoped_ptr<base::DictionaryValue>(manifest_data.DeepCopy())));
-
-  if (!InitApplicationID(manifest.get(), path, explicit_id, &error)) {
-    *error_message = base::UTF16ToUTF8(error);
-    return NULL;
-  }
-
-  std::vector<InstallWarning> install_warnings;
-  if (!manifest->ValidateManifest(error_message, &install_warnings)) {
+  if (!manifest->ValidateManifest(error_message))
     return NULL;
-  }
 
-  scoped_refptr<ApplicationData> application = new ApplicationData(path,
-                                                           manifest.Pass());
-  application->install_warnings_.swap(install_warnings);
-
-  if (!application->Init(&error)) {
+  scoped_refptr<ApplicationData> app_data =
+      new ApplicationData(path, source_type, manifest.Pass());
+  if (!app_data->Init(explicit_id, &error)) {
     *error_message = base::UTF16ToUTF8(error);
     return NULL;
   }
 
-  return application;
-}
-
-// static
-bool ApplicationData::IsIDValid(const std::string& id) {
-  std::string temp = StringToLowerASCII(id);
-
-#if defined(OS_TIZEN)
-  // An ID with 10 characters is most likely a legacy Tizen ID.
-  if (temp.size() == kLegacyTizenIdSize) {
-    for (size_t i = 0; i < kLegacyTizenIdSize; ++i) {
-      const char c = temp[i];
-      const bool valid = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z');
-      if (!valid)
-        return false;
-    }
-
-    return true;
-  }
-#endif
-
-  // Verify that the id is legal.
-  if (temp.size() != (kIdSize * 2))
-    return false;
+  ManifestHandlerRegistry* registry =
+      ManifestHandlerRegistry::GetInstance(app_data->manifest_type());
 
-  // We only support lowercase IDs, because IDs can be used as URL components
-  // (where GURL will lowercase it).
-  for (size_t i = 0; i < temp.size(); ++i)
-    if (temp[i] < 'a' || temp[i] > 'p')
-      return false;
+  if (!registry->ValidateAppManifest(app_data, error_message))
+    return NULL;
 
-  return true;
+  return app_data;
 }
 
 // static
 GURL ApplicationData::GetBaseURLFromApplicationId(
     const std::string& application_id) {
-  return GURL(std::string(xwalk::application::kApplicationScheme) +
-              content::kStandardSchemeSeparator + application_id + "/");
+  return GURL(std::string(kApplicationScheme) +
+      url::kStandardSchemeSeparator + application_id + "/");
 }
 
 ApplicationData::ManifestData* ApplicationData::GetManifestData(
@@ -128,13 +89,11 @@ void ApplicationData::SetManifestData(const std::string& key,
   manifest_data_[key] = linked_ptr<ManifestData>(data);
 }
 
-Manifest::SourceType ApplicationData::GetSourceType() const {
-  return manifest_->GetSourceType();
-}
-
-const std::string& ApplicationData::ID() const {
-  return manifest_->GetApplicationID();
+#if defined(OS_TIZEN)
+std::string ApplicationData::GetPackageID() const {
+  return AppIdToPkgId(application_id_);
 }
+#endif
 
 const std::string ApplicationData::VersionString() const {
   if (!version_->components().empty())
@@ -143,59 +102,27 @@ const std::string ApplicationData::VersionString() const {
   return "";
 }
 
-bool ApplicationData::IsPlatformApp() const {
-  return manifest_->IsPackaged();
-}
-
 bool ApplicationData::IsHostedApp() const {
-  return GetManifest()->IsHosted();
-}
-
-// static
-bool ApplicationData::InitApplicationID(xwalk::application::Manifest* manifest,
-                                const base::FilePath& path,
-                                const std::string& explicit_id,
-                                base::string16* error) {
-  std::string application_id;
+  bool hosted = source_type_ == EXTERNAL_URL;
 #if defined(OS_TIZEN)
-  if (manifest->HasKey(keys::kTizenAppIdKey)) {
-    if (!manifest->GetString(keys::kTizenAppIdKey, &application_id)) {
-      NOTREACHED() << "Could not get Tizen application key";
-      return false;
-    }
-  }
-
-  if (!application_id.empty()) {
-    manifest->SetApplicationID(application_id);
-    return true;
+  if (manifest_->HasPath(widget_keys::kContentNamespace)) {
+    std::string ns;
+    if (manifest_->GetString(widget_keys::kContentNamespace, &ns) &&
+        ns == kTizenNamespacePrefix)
+      hosted = true;
   }
 #endif
-
-  if (!explicit_id.empty()) {
-    manifest->SetApplicationID(explicit_id);
-    return true;
-  }
-
-  application_id = GenerateIdForPath(path);
-  if (application_id.empty()) {
-    NOTREACHED() << "Could not create ID from path.";
-    return false;
-  }
-  manifest->SetApplicationID(application_id);
-  return true;
+  return hosted;
 }
 
 ApplicationData::ApplicationData(const base::FilePath& path,
-                     scoped_ptr<xwalk::application::Manifest> manifest)
+  SourceType source_type, scoped_ptr<Manifest> manifest)
     : manifest_version_(0),
+      path_(path),
       manifest_(manifest.release()),
-      finished_parsing_manifest_(false) {
-  DCHECK(path.empty() || path.IsAbsolute());
-  path_ = path;
-  if (manifest_->HasPath(widget_keys::kWidgetKey))
-    package_type_ = Package::WGT;
-  else
-    package_type_ = Package::XPK;
+      finished_parsing_manifest_(false),
+      source_type_(source_type) {
+  DCHECK(path_.empty() || path_.IsAbsolute());
 }
 
 ApplicationData::~ApplicationData() {
@@ -204,7 +131,7 @@ ApplicationData::~ApplicationData() {
 // static
 GURL ApplicationData::GetResourceURL(const GURL& application_url,
                                const std::string& relative_path) {
-  DCHECK(application_url.SchemeIs(xwalk::application::kApplicationScheme));
+  DCHECK(application_url.SchemeIs(kApplicationScheme));
   DCHECK_EQ("/", application_url.path());
 
   std::string path = relative_path;
@@ -221,40 +148,87 @@ GURL ApplicationData::GetResourceURL(const GURL& application_url,
   return ret_val;
 }
 
-Manifest::Type ApplicationData::GetType() const {
-  return manifest_->GetType();
+GURL ApplicationData::GetResourceURL(const std::string& relative_path) const {
+#if defined (OS_WIN)
+  if (!base::PathExists(path_.Append(base::UTF8ToWide(relative_path)))) {
+#else
+  if (!base::PathExists(path_.Append(relative_path))) {
+#endif
+    LOG(ERROR) << "The path does not exist in the application directory: "
+               << relative_path;
+    return GURL();
+  }
+
+  return GetResourceURL(URL(), relative_path);
 }
 
-bool ApplicationData::Init(base::string16* error) {
+bool ApplicationData::Init(const std::string& explicit_id,
+                           base::string16* error) {
   DCHECK(error);
+  ManifestHandlerRegistry* registry =
+      ManifestHandlerRegistry::GetInstance(manifest_type());
+  if (!registry->ParseAppManifest(this, error))
+    return false;
 
+  if (!LoadID(explicit_id, error))
+    return false;
   if (!LoadName(error))
     return false;
   if (!LoadVersion(error))
-      return false;
+    return false;
   if (!LoadDescription(error))
-      return false;
-  if (!LoadManifestVersion(error))
     return false;
 
   application_url_ = ApplicationData::GetBaseURLFromApplicationId(ID());
 
-  ManifestHandlerRegistry* registry =
-      ManifestHandlerRegistry::GetInstance(GetPackageType());
-  if (!registry->ParseAppManifest(this, error))
-    return false;
-
   finished_parsing_manifest_ = true;
   return true;
 }
 
+bool ApplicationData::LoadID(const std::string& explicit_id,
+                             base::string16* error) {
+  std::string application_id;
+#if defined(OS_TIZEN)
+  if (manifest_type() == Manifest::TYPE_WIDGET) {
+    const TizenApplicationInfo* tizen_app_info =
+        static_cast<TizenApplicationInfo*>(GetManifestData(
+            widget_keys::kTizenApplicationKey));
+    CHECK(tizen_app_info);
+    application_id = tizen_app_info->id();
+  } else if (manifest_->HasKey(keys::kTizenAppIdKey)) {
+    if (!manifest_->GetString(keys::kTizenAppIdKey, &application_id)) {
+      NOTREACHED() << "Could not get Tizen application key";
+      return false;
+    }
+  }
+
+  if (!application_id.empty()) {
+    application_id_ = application_id;
+    return true;
+  }
+#endif
+
+  if (!explicit_id.empty()) {
+    application_id_ = explicit_id;
+    return true;
+  }
+
+  application_id = GenerateIdForPath(path_);
+  if (application_id.empty()) {
+    NOTREACHED() << "Could not create ID from path.";
+    return false;
+  }
+  application_id_ = application_id;
+  return true;
+}
+
 bool ApplicationData::LoadName(base::string16* error) {
   DCHECK(error);
   base::string16 localized_name;
-  std::string name_key(GetNameKey(GetPackageType()));
+  std::string name_key(GetNameKey(manifest_type()));
 
   if (!manifest_->GetString(name_key, &localized_name) &&
-      package_type_ == Package::XPK) {
+      manifest_type() == Manifest::TYPE_MANIFEST) {
     *error = base::ASCIIToUTF16(errors::kInvalidName);
     return false;
   }
@@ -267,49 +241,91 @@ bool ApplicationData::LoadName(base::string16* error) {
 bool ApplicationData::LoadVersion(base::string16* error) {
   DCHECK(error);
   std::string version_str;
-  std::string version_key(GetVersionKey(GetPackageType()));
 
-  if (!manifest_->GetString(version_key, &version_str) &&
-      package_type_ == Package::XPK) {
-    *error = base::ASCIIToUTF16(errors::kInvalidVersion);
-    return false;
+  version_.reset(new base::Version());
+
+  if (manifest_type() == Manifest::TYPE_WIDGET) {
+    bool ok = manifest_->GetString(widget_keys::kVersionKey, &version_str);
+    if (!ok) {
+      *error = base::ASCIIToUTF16(errors::kInvalidVersion);
+      return true;
+    }
+
+    version_.reset(new base::Version(version_str));
+    return true;
+  }
+
+  // W3C Manifest (XPK and hosted):
+
+  bool hasDeprecatedKey = manifest_->HasKey(keys::kDeprecatedVersionKey);
+  bool hasKey = manifest_->HasKey(keys::kXWalkVersionKey);
+
+  if (!hasKey && !hasDeprecatedKey) {
+    // xwalk_version is optional.
+    return true;
+  }
+
+  bool ok = false;
+  if (hasKey) {
+    if (hasDeprecatedKey) {
+      LOG(WARNING) << "Deprecated key '" << keys::kDeprecatedVersionKey
+          << "' found in addition to '" << keys::kXWalkVersionKey
+          << "'. Consider removing.";
+    }
+    ok = manifest_->GetString(keys::kXWalkVersionKey, &version_str);
+  }
+
+  if (!hasKey && hasDeprecatedKey) {
+    LOG(WARNING) << "Deprecated key '" << keys::kDeprecatedVersionKey
+        << "' found. Please migrate to using '" << keys::kXWalkVersionKey
+        << "' instead.";
+    ok = manifest_->GetString(keys::kDeprecatedVersionKey, &version_str);
   }
+
   version_.reset(new base::Version(version_str));
-  if (package_type_ == Package::XPK &&
-      (!version_->IsValid() || version_->components().size() > 4)) {
+
+  if (!ok || !version_->IsValid() || version_->components().size() > 4) {
     *error = base::ASCIIToUTF16(errors::kInvalidVersion);
+    version_.reset(new base::Version());
     return false;
   }
-  return true;
+
+  return ok;
 }
 
 bool ApplicationData::LoadDescription(base::string16* error) {
   DCHECK(error);
-  if (manifest_->HasKey(keys::kDescriptionKey) &&
-      !manifest_->GetString(keys::kDescriptionKey, &description_) &&
-      package_type_ == Package::XPK) {
-    *error = base::ASCIIToUTF16(errors::kInvalidDescription);
-    return false;
+  // FIXME: Better to assert on use from Widget.
+  if (manifest_type() != Manifest::TYPE_MANIFEST)
+    return true;  // No error.
+
+  bool hasDeprecatedKey = manifest_->HasKey(keys::kDeprecatedDescriptionKey);
+  bool hasKey = manifest_->HasKey(keys::kXWalkDescriptionKey);
+
+  if (hasKey) {
+    if (hasDeprecatedKey) {
+      LOG(WARNING) << "Deprecated key '" << keys::kDeprecatedDescriptionKey
+          << "' found in addition to '" << keys::kXWalkDescriptionKey
+          << "'. Consider removing.";
+    }
+    bool ok = manifest_->GetString(keys::kXWalkDescriptionKey, &description_);
+    if (!ok)
+      *error = base::ASCIIToUTF16(errors::kInvalidDescription);
+    return ok;
   }
-  return true;
-}
 
-bool ApplicationData::LoadManifestVersion(base::string16* error) {
-  DCHECK(error);
-  // Get the original value out of the dictionary so that we can validate it
-  // more strictly.
-  if (manifest_->value()->HasKey(keys::kManifestVersionKey)) {
-    int manifest_version = 1;
-    if (!manifest_->GetInteger(keys::kManifestVersionKey, &manifest_version) ||
-        manifest_version < 1) {
-      if (package_type_ == Package::XPK) {
-        *error = base::ASCIIToUTF16(errors::kInvalidManifestVersion);
-        return false;
-      }
-    }
+  if (hasDeprecatedKey) {
+    LOG(WARNING) << "Deprecated key '" << keys::kDeprecatedDescriptionKey
+        << "' found. Please migrate to using '" << keys::kXWalkDescriptionKey
+        << "' instead.";
+    bool ok = manifest_->GetString(
+        keys::kDeprecatedDescriptionKey, &description_);
+    if (!ok)
+      *error = base::ASCIIToUTF16(errors::kInvalidDescription);
+    return ok;
   }
 
-  manifest_version_ = manifest_->GetManifestVersion();
+  // No error but also no description found.
   return true;
 }
 
@@ -347,11 +363,11 @@ PermissionSet ApplicationData::GetManifestPermissions() const {
 
 bool ApplicationData::HasCSPDefined() const {
 #if defined(OS_TIZEN)
-  return  manifest_->HasPath(GetCSPKey(package_type_)) ||
+  return  manifest_->HasPath(GetCSPKey(manifest_type())) ||
           manifest_->HasPath(widget_keys::kCSPReportOnlyKey) ||
           manifest_->HasPath(widget_keys::kAllowNavigationKey);
 #else
-  return manifest_->HasPath(GetCSPKey(package_type_));
+  return manifest_->HasPath(GetCSPKey(manifest_type()));
 #endif
 }