Upstream version 11.39.260.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / common / application_file_util.cc
index 798c911..928de8d 100644 (file)
 #include "xwalk/application/common/application_data.h"
 #include "xwalk/application/common/application_manifest_constants.h"
 #include "xwalk/application/common/constants.h"
-#include "xwalk/application/common/install_warning.h"
 #include "xwalk/application/common/manifest.h"
 #include "xwalk/application/common/manifest_handler.h"
 
+#if defined(OS_TIZEN)
+#include "xwalk/application/common/id_util.h"
+#endif
+
 namespace errors = xwalk::application_manifest_errors;
 namespace keys = xwalk::application_manifest_keys;
 namespace widget_keys = xwalk::application_widget_keys;
@@ -41,6 +44,8 @@ const char kAttributePrefix[] = "@";
 const char kNamespaceKey[] = "@namespace";
 const char kTextKey[] = "#text";
 
+const char kContentKey[] = "content";
+
 const xmlChar kWidgetNodeKey[] = "widget";
 const xmlChar kNameNodeKey[] = "name";
 const xmlChar kDescriptionNodeKey[] = "description";
@@ -55,6 +60,14 @@ const char kDirRTLKey[] = "rtl";
 const char kDirLROKey[] = "lro";
 const char kDirRLOKey[] = "rlo";
 
+const char* kSingletonElements[] = {
+  "allow-navigation",
+  "author",
+  "content-security-policy-report-only",
+  "content-security-policy",
+  "content"
+};
+
 inline char* ToCharPointer(void* ptr) {
   return reinterpret_cast<char *>(ptr);
 }
@@ -151,11 +164,35 @@ inline bool IsElementSupportSpanAndDir(xmlNode* root) {
   return false;
 }
 
+bool IsSingletonElement(const std::string& name) {
+  for (int i = 0; i < arraysize(kSingletonElements); ++i)
+    if (kSingletonElements[i] == name)
+#if defined(OS_TIZEN)
+      // On Tizen platform, need to check namespace of 'content'
+      // element further, a content element with tizen namespace
+      // will replace the one with widget namespace.
+      return name != kContentKey;
+#else
+      return true;
+#endif
+  return false;
+}
+
 }  // namespace
 
 namespace xwalk {
 namespace application {
 
+FileDeleter::FileDeleter(const base::FilePath& path, bool recursive)
+    : path_(path),
+      recursive_(recursive) {}
+
+FileDeleter::~FileDeleter() {
+  base::DeleteFile(path_, recursive_);
+}
+
+namespace {
+
 // Load XML node into Dictionary structure.
 // The keys for the XML node to Dictionary mapping are described below:
 // XML                                 Dictionary
@@ -228,6 +265,21 @@ base::DictionaryValue* LoadXMLNode(
     if (!value->HasKey(sub_node_name)) {
       value->Set(sub_node_name, sub_value);
       continue;
+    } else if (IsSingletonElement(sub_node_name)) {
+      continue;
+#if defined(OS_TIZEN)
+    } else if (sub_node_name == kContentKey) {
+      std::string current_namespace, new_namespace;
+      base::DictionaryValue* current_value;
+      value->GetDictionary(sub_node_name, &current_value);
+
+      current_value->GetString(kNamespaceKey, &current_namespace);
+      sub_value->GetString(kNamespaceKey, &new_namespace);
+      if (current_namespace != new_namespace &&
+          new_namespace == widget_keys::kTizenNamespacePrefix)
+        value->Set(sub_node_name, sub_value);
+      continue;
+#endif
     }
 
     base::Value* temp;
@@ -242,8 +294,7 @@ base::DictionaryValue* LoadXMLNode(
       DCHECK(temp->IsType(base::Value::TYPE_DICTIONARY));
       base::DictionaryValue* dict;
       temp->GetAsDictionary(&dict);
-      base::DictionaryValue* prev_value(new base::DictionaryValue());
-      prev_value = dict->DeepCopy();
+      base::DictionaryValue* prev_value = dict->DeepCopy();
 
       base::ListValue* list = new base::ListValue();
       list->Append(prev_value);
@@ -269,56 +320,18 @@ base::DictionaryValue* LoadXMLNode(
   return value.release();
 }
 
-scoped_refptr<ApplicationData> LoadApplication(
-    const base::FilePath& application_path,
-    Manifest::SourceType source_type,
-    std::string* error) {
-  return LoadApplication(application_path, std::string(),
-                         source_type, error);
-}
-
-scoped_refptr<ApplicationData> LoadApplication(
-    const base::FilePath& application_path,
-    const std::string& application_id,
-    Manifest::SourceType source_type,
-    std::string* error) {
-  scoped_ptr<base::DictionaryValue> manifest(
-      LoadManifest(application_path, error));
-  if (!manifest.get())
-    return NULL;
-
-  scoped_refptr<ApplicationData> application = ApplicationData::Create(
-                                                             application_path,
-                                                             source_type,
-                                                             *manifest,
-                                                             application_id,
-                                                             error);
-  if (!application.get())
-    return NULL;
-
-  std::vector<InstallWarning> warnings;
-  ManifestHandlerRegistry* registry =
-      manifest->HasKey(widget_keys::kWidgetKey)
-      ? ManifestHandlerRegistry::GetInstance(Manifest::TYPE_WGT)
-      : ManifestHandlerRegistry::GetInstance(Manifest::TYPE_XPK);
-
-  if (!registry->ValidateAppManifest(application, error, &warnings))
-    return NULL;
-
-  if (!warnings.empty()) {
-    LOG(WARNING) << "There are some warnings when validating the application "
-                 << application->ID();
-  }
+}  // namespace
 
-  return application;
-}
+template <Manifest::Type>
+scoped_ptr<Manifest> LoadManifest(
+    const base::FilePath& manifest_path, std::string* error);
 
-static base::DictionaryValue* LoadManifestXpk(
-    const base::FilePath& manifest_path,
-    std::string* error) {
+template <>
+scoped_ptr<Manifest> LoadManifest<Manifest::TYPE_MANIFEST>(
+    const base::FilePath& manifest_path, std::string* error) {
   JSONFileValueSerializer serializer(manifest_path);
   scoped_ptr<base::Value> root(serializer.Deserialize(NULL, error));
-  if (!root.get()) {
+  if (!root) {
     if (error->empty()) {
       // If |error| is empty, than the file could not be read.
       // It would be cleaner to have the JSON reader give a specific error
@@ -327,28 +340,28 @@ static base::DictionaryValue* LoadManifestXpk(
       *error = base::StringPrintf("%s", errors::kManifestUnreadable);
     } else {
       *error = base::StringPrintf("%s  %s",
-                                  errors::kManifestParseError,
-                                  error->c_str());
+          errors::kManifestParseError, error->c_str());
     }
-    return NULL;
+    return scoped_ptr<Manifest>();
   }
 
   if (!root->IsType(base::Value::TYPE_DICTIONARY)) {
     *error = base::StringPrintf("%s", errors::kManifestUnreadable);
-    return NULL;
+    return scoped_ptr<Manifest>();
   }
 
-  base::DictionaryValue* dv =
-      static_cast<base::DictionaryValue*>(root.release());
+  scoped_ptr<base::DictionaryValue> dv = make_scoped_ptr(
+      static_cast<base::DictionaryValue*>(root.release()));
 #if defined(OS_TIZEN)
   // Ignore any Tizen application ID, as this is automatically generated.
   dv->Remove(keys::kTizenAppIdKey, NULL);
 #endif
 
-  return dv;
+  return make_scoped_ptr(new Manifest(dv.Pass(), Manifest::TYPE_MANIFEST));
 }
 
-static base::DictionaryValue* LoadManifestWgt(
+template <>
+scoped_ptr<Manifest> LoadManifest<Manifest::TYPE_WIDGET>(
     const base::FilePath& manifest_path,
     std::string* error) {
   xmlDoc * doc = NULL;
@@ -356,7 +369,7 @@ static base::DictionaryValue* LoadManifestWgt(
   doc = xmlReadFile(manifest_path.MaybeAsASCII().c_str(), NULL, 0);
   if (doc == NULL) {
     *error = base::StringPrintf("%s", errors::kManifestUnreadable);
-    return NULL;
+    return scoped_ptr<Manifest>();
   }
   root_node = xmlDocGetRootElement(doc);
   base::DictionaryValue* dv = LoadXMLNode(root_node);
@@ -364,23 +377,51 @@ static base::DictionaryValue* LoadManifestWgt(
   if (dv)
     result->Set(ToConstCharPointer(root_node->name), dv);
 
-  return result.release();
+  return make_scoped_ptr(new Manifest(result.Pass(), Manifest::TYPE_WIDGET));
 }
 
-base::DictionaryValue* LoadManifest(const base::FilePath& application_path,
-      std::string* error) {
+scoped_ptr<Manifest> LoadManifest(const base::FilePath& manifest_path,
+    Manifest::Type type, std::string* error) {
+  if (type == Manifest::TYPE_MANIFEST)
+    return LoadManifest<Manifest::TYPE_MANIFEST>(manifest_path, error);
+
+  if (type == Manifest::TYPE_WIDGET)
+    return LoadManifest<Manifest::TYPE_WIDGET>(manifest_path, error);
+
+  *error = base::StringPrintf("%s", errors::kManifestUnreadable);
+  return scoped_ptr<Manifest>();
+}
+
+base::FilePath GetManifestPath(
+    const base::FilePath& app_directory, Manifest::Type type) {
   base::FilePath manifest_path;
+  switch (type) {
+    case Manifest::TYPE_WIDGET:
+      manifest_path = app_directory.Append(kManifestWgtFilename);
+      break;
+    case Manifest::TYPE_MANIFEST:
+      manifest_path = app_directory.Append(kManifestXpkFilename);
+      break;
+    default:
+      NOTREACHED();
+  }
 
-  manifest_path = application_path.Append(kManifestXpkFilename);
-  if (base::PathExists(manifest_path))
-    return LoadManifestXpk(manifest_path, error);
+  return manifest_path;
+}
+
+scoped_refptr<ApplicationData> LoadApplication(
+    const base::FilePath& app_root, const std::string& app_id,
+    ApplicationData::SourceType source_type, Manifest::Type manifest_type,
+    std::string* error) {
+  base::FilePath manifest_path = GetManifestPath(app_root, manifest_type);
 
-  manifest_path = application_path.Append(kManifestWgtFilename);
-  if (base::PathExists(manifest_path))
-    return LoadManifestWgt(manifest_path, error);
+  scoped_ptr<Manifest> manifest = LoadManifest(
+      manifest_path, manifest_type, error);
+  if (!manifest)
+    return NULL;
 
-  *error = base::StringPrintf("%s", errors::kManifestUnreadable);
-  return NULL;
+  return ApplicationData::Create(
+      app_root, app_id, source_type, manifest.Pass(), error);
 }
 
 base::FilePath ApplicationURLToRelativeFilePath(const GURL& url) {