Upstream version 10.38.210.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / common / application_data.cc
index 7bf8ade..7ef3f00 100644 (file)
@@ -26,9 +26,9 @@
 #include "xwalk/application/common/constants.h"
 #include "xwalk/application/common/manifest.h"
 #include "xwalk/application/common/manifest_handler.h"
-#include "xwalk/application/common/manifest_handlers/main_document_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"
@@ -43,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(
@@ -129,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())
@@ -144,67 +102,27 @@ const std::string ApplicationData::VersionString() const {
   return "";
 }
 
-bool ApplicationData::IsPlatformApp() const {
-  return manifest_->IsPackaged();
-}
-
 bool ApplicationData::IsHostedApp() const {
-  return GetManifest()->IsHosted();
-}
-
-Manifest::PackageType ApplicationData::GetPackageType() const {
-  return manifest_->GetPackageType();
-}
-
-bool ApplicationData::HasMainDocument() const {
-  MainDocumentInfo* main_info = ToMainDocumentInfo(
-      GetManifestData(application_manifest_keys::kAppMainKey));
-
-  return main_info != NULL;
-}
-
-// 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),
-      is_dirty_(false),
+      path_(path),
       manifest_(manifest.release()),
-      finished_parsing_manifest_(false) {
-  DCHECK(path.empty() || path.IsAbsolute());
-  path_ = path;
+      finished_parsing_manifest_(false),
+      source_type_(source_type) {
+  DCHECK(path_.empty() || path_.IsAbsolute());
 }
 
 ApplicationData::~ApplicationData() {
@@ -213,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;
@@ -230,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) &&
-      manifest_->IsXPKPackaged()) {
+      manifest_type() == Manifest::TYPE_MANIFEST) {
     *error = base::ASCIIToUTF16(errors::kInvalidName);
     return false;
   }
@@ -276,63 +241,96 @@ 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) &&
-      manifest_->IsXPKPackaged()) {
-    *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 (manifest_->IsXPKPackaged() &&
-      (!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_) &&
-      manifest_->IsXPKPackaged()) {
-    *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 (manifest_->IsXPKPackaged()) {
-        *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;
 }
 
-void ApplicationData::SetEvents(const std::set<std::string>& events) {
-  events_ = events;
-  is_dirty_ = true;
-}
-
-const std::set<std::string>& ApplicationData::GetEvents() const {
-  return events_;
-}
-
 StoredPermission ApplicationData::GetPermission(
-    std::string& permission_name) const {
+    const std::string& permission_name) const {
   StoredPermissionMap::const_iterator iter =
       permission_map_.find(permission_name);
   if (iter == permission_map_.end())
@@ -344,7 +342,6 @@ bool ApplicationData::SetPermission(const std::string& permission_name,
                                     StoredPermission perm) {
   if (perm != UNDEFINED_STORED_PERM) {
     permission_map_[permission_name] = perm;
-    is_dirty_ = true;
     return true;
   }
   return false;
@@ -364,13 +361,15 @@ PermissionSet ApplicationData::GetManifestPermissions() const {
   return permissions;
 }
 
-#if defined(OS_TIZEN)
 bool ApplicationData::HasCSPDefined() const {
-  return (manifest_->HasPath(widget_keys::kCSPKey) ||
+#if defined(OS_TIZEN)
+  return  manifest_->HasPath(GetCSPKey(manifest_type())) ||
           manifest_->HasPath(widget_keys::kCSPReportOnlyKey) ||
-          manifest_->HasPath(widget_keys::kAllowNavigationKey));
-}
+          manifest_->HasPath(widget_keys::kAllowNavigationKey);
+#else
+  return manifest_->HasPath(GetCSPKey(manifest_type()));
 #endif
+}
 
 bool ApplicationData::SetApplicationLocale(const std::string& locale,
                                            base::string16* error) {