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