#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;
const char kNamespaceKey[] = "@namespace";
const char kTextKey[] = "#text";
+const char kContentKey[] = "content";
+
const xmlChar kWidgetNodeKey[] = "widget";
const xmlChar kNameNodeKey[] = "name";
const xmlChar kDescriptionNodeKey[] = "description";
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);
}
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
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, ¤t_value);
+
+ current_value->GetString(kNamespaceKey, ¤t_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;
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);
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
*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;
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);
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) {