4813d72b535e1926157e57ee6b3ed1c2977f0377
[platform/core/appfw/wgt-backend.git] / src / wgt / extension_config_parser.cc
1 // Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by a apache 2.0 license that can be
3 // found in the LICENSE file.
4
5 #include "wgt/extension_config_parser.h"
6 #include <manifest_parser/utils/string_util.h>
7 #include <manifest_parser/manifest_handler.h>
8
9 #include <cassert>
10 #include <utility>
11
12 namespace wgt {
13
14 namespace {
15 const xmlChar kExtensionNodeKey[] = "extension";
16 const xmlChar kNamePrivilegeKey[] = "privilege";
17 const xmlChar kPrivigeNameAttributeKey[] = "name";
18 const char kAttributePrefix[] = "@";
19 const xmlChar kDirAttributeKey[] = "dir";
20 const char kXmlTextKey[] = "#text";
21 const char kNamespaceKey[] = "@namespace";
22 const char kExtensionPath[] = "extension.privilege";
23 const char kExtensionNameKey[] = "@name";
24 }  // namespace
25
26 ExtensionConfigParser::ExtensionConfigParser(std::string config_xml) {
27   config_xml_ = config_xml;
28 }
29
30 std::unique_ptr<parser::DictionaryValue>
31     ExtensionConfigParser::LoadExtensionConfig(const std::string& config_xml) {
32   xmlDoc *doc = nullptr;
33   xmlNode* root_node = nullptr;
34   doc = xmlReadFile(config_xml.c_str(), nullptr, XML_PARSE_NOENT);
35   if (!doc) {
36     LOG(ERROR) << "Failed to read xml document model from" << config_xml;
37     return nullptr;
38   }
39   root_node = xmlDocGetRootElement(doc);
40   std::unique_ptr<parser::DictionaryValue> dv = LoadXMLNode(root_node);
41   std::unique_ptr<parser::DictionaryValue> result(new parser::DictionaryValue);
42   if (dv)
43     result->Set(reinterpret_cast<const char*>(root_node->name), dv.release());
44   return result;
45 }
46
47 std::string ExtensionConfigParser::GetNodeDir(
48     xmlNode* node, const std::string& inherit_dir) {
49   std::string dir(inherit_dir);
50   for (xmlAttr* prop = node->properties; prop; prop = prop->next) {
51     if (xmlStrEqual(prop->name, kDirAttributeKey)) {
52       char* prop_value = reinterpret_cast<char*>(xmlNodeListGetString(
53           node->doc, prop->children, 1));
54       dir = prop_value;
55       xmlFree(prop_value);
56       break;
57     }
58   }
59   return dir;
60 }
61 std::string ExtensionConfigParser::GetNodeText(
62     xmlNode* root, const std::string& inherit_dir) {
63   if (root->type != XML_ELEMENT_NODE)
64     return std::string();
65   std::string current_dir(GetNodeDir(root, inherit_dir));
66   std::string text;
67   if (!current_dir.empty())
68     text += parser::utils::GetDirUTF8Start(current_dir);
69   for (xmlNode* node = root->children; node; node = node->next) {
70     if (node->type == XML_TEXT_NODE || node->type == XML_CDATA_SECTION_NODE)
71       text = text + std::string(reinterpret_cast<char*>(node->content));
72     else
73       text += GetNodeText(node, current_dir);
74   }
75   if (!current_dir.empty())
76     text += parser::utils::GetDirUTF8End();
77   return text;
78 }
79 bool ExtensionConfigParser::IsPropSupportDir(xmlNode* root, xmlAttr* prop) {
80   if (xmlStrEqual(root->name, kNamePrivilegeKey)
81       && xmlStrEqual(prop->name, kPrivigeNameAttributeKey)) {
82     return true;
83   }
84   return false;
85 }
86 bool ExtensionConfigParser::IsTrimRequiredForElement(xmlNode* root) {
87   if (xmlStrEqual(root->name, kNamePrivilegeKey)) {
88     return true;
89   }
90   return false;
91 }
92 bool ExtensionConfigParser::IsTrimRequiredForProp(
93     xmlNode* root, xmlAttr* prop) {
94   if (xmlStrEqual(root->name, kNamePrivilegeKey) &&
95       xmlStrEqual(prop->name, kPrivigeNameAttributeKey)) {
96     return true;
97   }
98   return false;
99 }
100 std::unique_ptr<parser::DictionaryValue>
101     ExtensionConfigParser::LoadXMLNode(
102     xmlNode* root, const std::string& inherit_dir) {
103   std::unique_ptr<parser::DictionaryValue> value(new parser::DictionaryValue());
104   if (root->type != XML_ELEMENT_NODE)
105     return nullptr;
106
107   std::string current_dir(GetNodeDir(root, inherit_dir));
108
109   xmlAttr* prop = nullptr;
110   for (prop = root->properties; prop; prop = prop->next) {
111     xmlChar* value_ptr = xmlNodeListGetString(root->doc, prop->children, 1);
112     std::string prop_value(reinterpret_cast<char*>(value_ptr));
113     xmlFree(value_ptr);
114     if (IsPropSupportDir(root, prop))
115       prop_value = parser::utils::GetDirTextUTF8(prop_value, current_dir);
116
117     if (IsTrimRequiredForProp(root, prop))
118       prop_value = parser::utils::CollapseWhitespaceUTF8(prop_value);
119
120     value->SetString(
121         std::string(kAttributePrefix)
122         + reinterpret_cast<const char*>(prop->name),
123         prop_value);
124   }
125
126   if (root->ns)
127     value->SetString(kNamespaceKey,
128         reinterpret_cast<const char*>(root->ns->href));
129
130   for (xmlNode* node = root->children; node; node = node->next) {
131     std::string sub_node_name(reinterpret_cast<const char*>(node->name));
132     std::unique_ptr<parser::DictionaryValue> sub_value =
133         LoadXMLNode(node, current_dir);
134
135     if (!sub_value) {
136       continue;
137     }
138     if (!value->HasKey(sub_node_name)) {
139       value->Set(sub_node_name, sub_value.release());
140       continue;
141     }
142
143     parser::Value* temp;
144     value->Get(sub_node_name, &temp);
145
146     if (temp->IsType(parser::Value::TYPE_LIST)) {
147       parser::ListValue* list;
148       temp->GetAsList(&list);
149       list->Append(sub_value.release());
150     } else {
151       assert(temp->IsType(parser::Value::TYPE_DICTIONARY));
152       parser::DictionaryValue* dict;
153       temp->GetAsDictionary(&dict);
154       parser::DictionaryValue* prev_value = dict->DeepCopy();
155
156       parser::ListValue* list = new parser::ListValue();
157       list->Append(prev_value);
158       list->Append(sub_value.release());
159       value->Set(sub_node_name, list);
160     }
161   }
162
163   std::string text;
164   xmlChar* text_ptr = xmlNodeListGetString(root->doc, root->children, 1);
165   if (text_ptr) {
166     text = reinterpret_cast<char*>(text_ptr);
167     xmlFree(text_ptr);
168   }
169   if (IsTrimRequiredForElement(root))
170     text = parser::utils::CollapseWhitespaceUTF8(text);
171   if (!text.empty())
172     value->SetString(kXmlTextKey, text);
173
174   return value;
175 }
176 std::vector<std::string> ExtensionConfigParser::GetExtensionPrivilegeList() {
177   std::unique_ptr<parser::DictionaryValue> dic
178     = LoadExtensionConfig(config_xml_);
179   std::vector<std::string> privilege_list;
180
181   for (auto& item : parser::GetOneOrMany(dic.get(), kExtensionPath, "")) {
182     std::string privilege;
183     if (item->GetString(kExtensionNameKey, &privilege)) {
184       LOG(DEBUG) << "User defined extra privilege: " << privilege;
185       privilege_list.push_back(privilege);
186     }
187   }
188   return privilege_list;
189 }
190 }  // namespace wgt