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