• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "adapter/ohos/capability/feature_config/config_xml_parser_base.h"
17 
18 #include <array>
19 
20 #include "adapter/ohos/capability/feature_config/feature_param_manager.h"
21 #include "base/log/log.h"
22 
23 namespace OHOS::Ace {
24 
25 enum ParseXmlNodeIndex : uint32_t {
26     PARSE_XML_UNDEFINED = 0,
27     PARSE_XML_PERFORMANCE_OPT_CONFIG,
28     PARSE_XML_BUNDLE_NAME,
29     PARSE_XML_FEATURE,
30     PARSE_XML_MAX_SIZE,
31 };
32 
33 namespace {
34 static const std::array<std::string, PARSE_XML_MAX_SIZE> XML_NODE_NAME_ARRAY = {
35     "undefine",             // PARSE_XML_UNDEFINED
36     "PerformanceOptConfig", // PARSE_XML_PERFORMANCE_OPT_CONFIG
37     "bundleName",           // PARSE_XML_BUNDLE_NAME
38     "feature",              // PARSE_XML_FEATURE
39 };
40 
41 static const std::array<std::string, 1> SYS_PATH = { "/etc" };
42 static constexpr char CONFIG_PATH[] = "/arkui/arkui_async_build_config.xml";
43 } // namespace
44 
~ConfigXMLParserBase()45 ConfigXMLParserBase::~ConfigXMLParserBase()
46 {
47     Destroy();
48 }
49 
Destroy()50 void ConfigXMLParserBase::Destroy()
51 {
52     if (xmlSysDocument_ != nullptr) {
53         xmlFreeDoc(xmlSysDocument_);
54         xmlSysDocument_ = nullptr;
55     }
56 }
57 
LoadPerformanceConfigXML()58 ParseErrCode ConfigXMLParserBase::LoadPerformanceConfigXML()
59 {
60     for (const std::string& configRootPath : SYS_PATH) {
61         std::string graphicFilePath = configRootPath + CONFIG_PATH;
62         xmlSysDocument_ = xmlReadFile(graphicFilePath.c_str(), nullptr, 0);
63         if (xmlSysDocument_ != nullptr) {
64             LOGD("ConfigXMLParserBase success to get sys graphic config: %{public}s", graphicFilePath.c_str());
65             break;
66         }
67     }
68     if (!xmlSysDocument_) {
69         LOGE("ConfigXMLParserBase read system file failed");
70         return PARSE_SYS_FILE_LOAD_FAIL;
71     }
72     return PARSE_EXEC_SUCCESS;
73 }
74 
ParsePerformanceConfigXMLWithBundleName(const std::string & bundleName)75 ParseErrCode ConfigXMLParserBase::ParsePerformanceConfigXMLWithBundleName(const std::string& bundleName)
76 {
77     if (!xmlSysDocument_) {
78         LOGE("ConfigXMLParserBase xmlSysDocument is empty, LoadGraphicConfiguration first");
79         return PARSE_SYS_FILE_LOAD_FAIL;
80     }
81     xmlNode* root = xmlDocGetRootElement(xmlSysDocument_);
82     if (root == nullptr) {
83         LOGE("ConfigXMLParserBase xmlDocGetRootElement failed");
84         return PARSE_GET_ROOT_FAIL;
85     }
86 
87     auto ret = ParseInternalWithBundleName(*root, bundleName);
88     if (ret != PARSE_EXEC_SUCCESS) {
89         LOGE("ConfigXMLParserBase ParseInternalWithBundleName failed");
90     }
91     return ret;
92 }
93 
ParseInternalWithBundleName(xmlNode & node,const std::string & bundleName)94 ParseErrCode ConfigXMLParserBase::ParseInternalWithBundleName(xmlNode& node, const std::string& bundleName)
95 {
96     // skip root node
97     xmlNode* currNode = node.children;
98     if (currNode == nullptr) {
99         return PARSE_GET_CHILD_FAIL;
100     }
101 
102     // find first PerformanceOptConfig node
103     auto ret = PARSE_EXEC_SUCCESS;
104     for (; currNode; currNode = currNode->next) {
105         ret = ParseXmlNodeNameWithIndex(*currNode, PARSE_XML_PERFORMANCE_OPT_CONFIG);
106         if (ret == PARSE_EXEC_SUCCESS) {
107             break;
108         }
109     }
110     if (currNode == nullptr) {
111         return PARSE_XML_NAME_ERROR;
112     }
113 
114     currNode = currNode->children;
115     if (currNode == nullptr) {
116         return PARSE_GET_CHILD_FAIL;
117     }
118 
119     // find parse feature nodes
120     for (; currNode; currNode = currNode->next) {
121         if (ParseXmlNodeNameWithIndex(*currNode, PARSE_XML_BUNDLE_NAME) != PARSE_EXEC_SUCCESS) {
122             continue;
123         }
124 
125         std::string xmlBundleName = ExtractPropertyValue("name", *currNode);
126         if (xmlBundleName == bundleName && currNode->children) {
127             ParseFeatures(*(currNode->children));
128             break;
129         }
130     }
131     return ret;
132 }
133 
ParseFeatures(xmlNode & node)134 void ConfigXMLParserBase::ParseFeatures(xmlNode& node)
135 {
136     auto& featureMap = FeatureParamManager::GetInstance().featureParamMap_;
137 
138     // travel features
139     xmlNode* currNode = &node;
140     for (; currNode; currNode = currNode->next) {
141         if (ParseXmlNodeNameWithIndex(*currNode, PARSE_XML_FEATURE) != PARSE_EXEC_SUCCESS) {
142             continue;
143         }
144 
145         std::string featureName = ExtractPropertyValue("id", *currNode);
146         auto it = featureMap.find(featureName);
147         if (it != featureMap.end()) {
148             it->second->ParseFeatureParam(*currNode);
149         }
150     }
151 }
152 
ExtractPropertyValue(const std::string & propName,xmlNode & node)153 std::string ConfigXMLParserBase::ExtractPropertyValue(const std::string& propName, xmlNode& node)
154 {
155     LOGD("ConfigXMLParserBase extracting value : %{public}s", propName.c_str());
156     std::string propValue = "";
157     xmlChar* tempValue = nullptr;
158 
159     if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
160         tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
161     }
162 
163     if (tempValue != nullptr) {
164         LOGD("ConfigXMLParserBase not a empty tempValue");
165         propValue = reinterpret_cast<const char*>(tempValue);
166         xmlFree(tempValue);
167         tempValue = nullptr;
168     }
169 
170     return propValue;
171 }
172 
ParseXmlNodeNameWithIndex(xmlNode & node,uint32_t nodeNameIndex)173 ParseErrCode ConfigXMLParserBase::ParseXmlNodeNameWithIndex(xmlNode& node, uint32_t nodeNameIndex)
174 {
175     if (nodeNameIndex >= XML_NODE_NAME_ARRAY.size()) {
176         return PARSE_SIZE_ERROR;
177     }
178 
179     if (xmlStrcasecmp(node.name, reinterpret_cast<const xmlChar*>(XML_NODE_NAME_ARRAY[nodeNameIndex].c_str())) != 0) {
180         return PARSE_XML_NAME_ERROR;
181     }
182 
183     return PARSE_EXEC_SUCCESS;
184 }
185 } // namespace OHOS::Ace
186