#include "widget-manifest-parser/application_data.h"
#include "widget-manifest-parser/application_manifest_constants.h"
#include "widget-manifest-parser/manifest.h"
+
#include "widget-manifest-parser/manifest_util.h"
using common_installer::widget_manifest_parser::ApplicationData;
namespace bf = boost::filesystem;
namespace common_installer {
-namespace widget_mnanifest_parser {
+namespace widget_manifest_parser {
class ManifestUtilTest : public testing::Test {
};
ASSERT_STREQ("Manifest file is missing or unreadable.", error.c_str());
}
-} // namespace widget_mnanifest_parser
+// Tests IsPropSupportDir method
+TEST_F(ManifestUtilTest, IsPropSupportDirTest) {
+ xmlChar kWidgetNodeKey[] = "widget";
+ xmlChar kNameNodeKey[] = "name";
+ xmlChar kVersionAttributeKey[] = "version";
+ xmlChar kShortAttributeKey[] = "short";
+ xmlNode node, sec_node;
+ node.name = kWidgetNodeKey;
+ sec_node.name = kNameNodeKey;
+ xmlAttr attr, sec_attr;
+ attr.name = kVersionAttributeKey;
+ sec_attr.name = kShortAttributeKey;
+ ASSERT_TRUE(IsPropSupportDir(&node, &attr));
+ ASSERT_TRUE(IsPropSupportDir(&sec_node, &sec_attr));
+ ASSERT_TRUE(!IsPropSupportDir(&node, &sec_attr));
+ ASSERT_TRUE(!IsPropSupportDir(&sec_node, &attr));
+ ASSERT_TRUE(!IsPropSupportDir(&node, &sec_attr));
+}
+
+// Tests IsElementSupportSpanAndDir method
+TEST_F(ManifestUtilTest, IsElementSupportSpanAndDirTest) {
+ std::map <const char*, bool> nodeNames = {
+ { "name", true },
+ { "description", true },
+ { "author", true },
+ { "license", true },
+ { "badlicense", false }
+ };
+ xmlNode node;
+ for (const auto& p : nodeNames) {
+ node.name = reinterpret_cast<xmlChar*>(const_cast<char*>(p.first));
+ EXPECT_TRUE(IsElementSupportSpanAndDir(&node) == p.second);
+ }
+}
+
+// Tests IsSingletonElement method
+TEST_F(ManifestUtilTest, IsSingletonElementTest) {
+ std::map<const char*, bool> kSingletonElements = {
+ { "allow-navigation", true },
+ { "author", true },
+ { "content-security-policy-report-only", true },
+ { "content-security-policy", true },
+ { "content", false },
+ { "badsingleton", false }
+ };
+ for (const auto& p : kSingletonElements)
+ EXPECT_TRUE(IsSingletonElement(p.first) == p.second);
+}
+
+// Tests IsTrimRequiredForElement
+TEST_F(ManifestUtilTest, IsTrimRequiredForElementTest) {
+ std::map<const char*, bool> elements {
+ { "name", true },
+ { "author", true },
+ { "badname", false },
+ { "badauthor", false }
+ };
+ xmlNode node;
+ for (const auto& p : elements) {
+ node.name = reinterpret_cast<xmlChar*>(const_cast<char*>(p.first));
+ EXPECT_TRUE(IsTrimRequiredForElement(&node) == p.second);
+ }
+}
+
+// Tests IsTrimRequiredForProp method
+TEST_F(ManifestUtilTest, IsTrimRequiredForPropTest) {
+ struct node{
+ bool operator <(const node& rhs) const {
+ return node_name_ < rhs.node_name_;
+ }
+ const char* node_name_;
+ const char* attr_name_;
+ };
+
+ std::map<node, bool> nodes = {
+ { {"widget", "id"}, true },
+ { {"widget", "version"}, true },
+ { {"widget", "defaultlocale"}, true },
+ { {"name", "short"}, true },
+ { {"author", "email"}, true },
+ { {"author", "href"}, true },
+ { {"license", "href"}, true },
+ { {"icon", "path"}, true },
+ { {"widget", "email"}, false },
+ { {"name", "path"}, false },
+ { {"author", "id"}, false }
+ };
+
+ xmlNode node;
+ xmlAttr attr;
+ for (const auto& p : nodes) {
+ node.name =
+ reinterpret_cast<xmlChar*>(const_cast<char*>(p.first.node_name_));
+ attr.name =
+ reinterpret_cast<xmlChar*>(const_cast<char*>(p.first.attr_name_));
+ EXPECT_TRUE(IsTrimRequiredForProp(&node, &attr) == p.second);
+ }
+}
+
+// Tests GetNodeDir method with proper values
+TEST_F(ManifestUtilTest, GetNodeDirTestProperValues) {
+ const char* xml = "<widget dir=\"rtl\">"
+ "<name>ppa emoS</name>"
+ "</widget>";
+ xmlDoc* doc = xmlParseMemory(xml, strlen(xml));
+ ASSERT_TRUE(doc);
+ xmlNode* root = doc->children;
+ ASSERT_TRUE(root);
+ std::string inherit_dir("ltr");
+ EXPECT_STREQ("rtl", GetNodeDir(root, inherit_dir).c_str());
+}
+
+// Tests GetNodeDir method with default dir
+TEST_F(ManifestUtilTest, GetNodeDirTestDefaultValues) {
+ const char* xml = "<widget>"
+ "<name>Some app</name>"
+ "</widget>";
+ xmlDoc* doc = xmlParseMemory(xml, strlen(xml));
+ ASSERT_TRUE(doc);
+ xmlNode* root = doc->children;
+ ASSERT_TRUE(root);
+ std::string inherit_dir("ltr");
+ EXPECT_STREQ("ltr", GetNodeDir(root, inherit_dir).c_str());
+}
+
+// Tests GetNodeText method with rtl text direction
+TEST_F(ManifestUtilTest, GetNodeTextTestXmlElementNode) {
+ const char* xml = "<widget dir=\"rtl\">"
+ "<name>ppa emoS</name>"
+ "</widget>";
+ std::map<char, int> control_chars = {
+ { '\xe2', 0 },
+ { '\x80', 1 },
+ { '\xab', 2 },
+ { '\xe2', 11 },
+ { '\x80', 12 },
+ { '\xac', 13 },
+ };
+ xmlDoc* doc = xmlParseMemory(xml, strlen(xml));
+ ASSERT_TRUE(doc);
+ xmlNode* root = doc->children;
+ ASSERT_TRUE(root);
+ std::string inherit_dir("ltr");
+ std::string s = GetNodeText(root, inherit_dir);
+ for (const auto& p : control_chars)
+ EXPECT_EQ(p.first, s[p.second]);
+}
+
+// Tests GetNodeText method with rtl and ltr text direction
+TEST_F(ManifestUtilTest, GetNodeTextTestTwoXmlElementNodes) {
+ const char* xml = "<widget dir=\"rtl\">"
+ "<name>ppa emoS</name>"
+ "<description dir=\"ltr\">Desc</description>"
+ "</widget>";
+ std::map<char, int> control_chars = {
+ { '\xe2', 0 }, { '\x80', 1 },
+ { '\xab', 2 }, { '\xe2', 11 },
+ { '\x80', 12 }, { '\xac', 13 },
+ { '\xe2', 14 }, { '\x80', 15 },
+ { '\xaa', 16 }, { '\xe2', 21 },
+ { '\x80', 22 }, { '\xac', 23 },
+ };
+ xmlDoc* doc = xmlParseMemory(xml, strlen(xml));
+ ASSERT_TRUE(doc);
+ xmlNode* root = doc->children;
+ ASSERT_TRUE(root);
+ std::string inherit_dir("ltr");
+ std::string s = GetNodeText(root, inherit_dir);
+ for (const auto& p : control_chars)
+ EXPECT_EQ(p.first, s[p.second]);
+}
+
+// Tests LoadXMLNode method with proper xml tree
+TEST_F(ManifestUtilTest, LoadXMLNodeTestProperXMLTree) {
+ const char* xml = "<root>"
+ "<widget dir=\"ltr\">"
+ "<name short=\"SA\">Some app</name>"
+ "<description>Desc</description>"
+ "<author dir=\"rtl\">enoemoS</author>"
+ "</widget>"
+ "</root>";
+ std::map<std::string, std::string> expected_vals = {
+ { "widget.@dir", "ltr" },
+ { "widget.name.@short",
+ std::string("\xE2\x80\xAA") + "SA" + "\xE2\x80\xAC" },
+ { "widget.name.#text",
+ std::string("\xE2\x80\xAA") + "Some app" + "\xE2\x80\xAC" },
+ { "widget.description.#text",
+ std::string("\xE2\x80\xAA") + "Desc" + "\xE2\x80\xAC" },
+ { "widget.author.@dir", "rtl" },
+ { "widget.author.#text",
+ std::string("\xE2\x80\xAB") + "enoemoS" + "\xE2\x80\xAC" }
+ };
+
+ xmlDoc* doc = xmlParseMemory(xml, strlen(xml));
+ ASSERT_TRUE(doc);
+ xmlNode* root = doc->children;
+ std::unique_ptr<utils::DictionaryValue> val =
+ common_installer::widget_manifest_parser::LoadXMLNode(root);
+
+ std::string test_str;
+ for (const auto& p : expected_vals) {
+ ASSERT_TRUE(val->GetString(p.first, &test_str));
+ EXPECT_STREQ(p.second.c_str(), test_str.c_str());
+ }
+}
+
+} // namespace widget_manifest_parser
} // namespace common_installer
#include "widget-manifest-parser/manifest_util.h"
#include <boost/filesystem/operations.hpp>
-#include <libxml2/libxml/tree.h>
#include <algorithm>
#include <cassert>
"content"
};
+} // namespace
+
+namespace common_installer {
+namespace widget_manifest_parser {
+
std::string GetNodeDir(xmlNode* node, const std::string& inherit_dir) {
assert(node);
std::string dir(inherit_dir);
std::string current_dir(GetNodeDir(root, inherit_dir));
std::string text;
for (xmlNode* node = root->children; node; node = node->next) {
-// TODO(jizydorczyk):
-// i18n support is needed
if (node->type == XML_TEXT_NODE || node->type == XML_CDATA_SECTION_NODE) {
text = text
+ common_installer::utils::StripWrappingBidiControlCharactersUTF8(
// According to widget specification, this two prop need to support dir.
// see detail on http://www.w3.org/TR/widgets/#the-dir-attribute
-inline bool IsPropSupportDir(xmlNode* root, xmlAttr* prop) {
+bool IsPropSupportDir(xmlNode* root, xmlAttr* prop) {
if (xmlStrEqual(root->name, kWidgetNodeKey)
&& xmlStrEqual(prop->name, kVersionAttributeKey))
return true;
// Only this four items need to support span and ignore other element.
// Besides xmlNodeListGetString can not support dir prop of span.
// See http://www.w3.org/TR/widgets/#the-span-element-and-its-attributes
-inline bool IsElementSupportSpanAndDir(xmlNode* root) {
+bool IsElementSupportSpanAndDir(xmlNode* root) {
if (xmlStrEqual(root->name, kNameNodeKey)
|| xmlStrEqual(root->name, kDescriptionNodeKey)
|| xmlStrEqual(root->name, kAuthorNodeKey)
// According to spec 'name' and 'author' should be result of applying the rule
// for getting text content with normalized white space to this element.
// http://www.w3.org/TR/widgets/#rule-for-getting-text-content-with-normalized-white-space-0
-inline bool IsTrimRequiredForElement(xmlNode* root) {
+bool IsTrimRequiredForElement(xmlNode* root) {
if (xmlStrEqual(root->name, kNameNodeKey) ||
xmlStrEqual(root->name, kAuthorNodeKey)) {
return true;
// According to spec some attributes requaire applying the rule for getting
// a single attribute value.
// http://www.w3.org/TR/widgets/#rule-for-getting-a-single-attribute-value-0
-inline bool IsTrimRequiredForProp(xmlNode* root, xmlAttr* prop) {
+bool IsTrimRequiredForProp(xmlNode* root, xmlAttr* prop) {
if (xmlStrEqual(root->name, kWidgetNodeKey) &&
(xmlStrEqual(prop->name, kIdAttributeKey) ||
xmlStrEqual(prop->name, kVersionAttributeKey) ||
return false;
}
-} // namespace
-
-namespace common_installer {
-namespace widget_manifest_parser {
-
-namespace {
-
// Load XML node into Dictionary structure.
// The keys for the XML node to Dictionary mapping are described below:
// XML Dictionary
// std::map<std::string*, std::map<std::string*,std::string>>
std::unique_ptr<utils::DictionaryValue> LoadXMLNode(
- xmlNode* root, const std::string& inherit_dir = "") {
+ xmlNode* root, const std::string& inherit_dir) {
std::unique_ptr<utils::DictionaryValue> value(new utils::DictionaryValue());
if (root->type != XML_ELEMENT_NODE)
return nullptr;
return value;
}
-} // namespace
-
std::unique_ptr<Manifest> LoadManifest(const std::string& manifest_path,
std::string* error) {
xmlDoc * doc = nullptr;