• 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 #include "processor_config_loader.h"
16 
17 #include <fstream>
18 #include <map>
19 #include <unordered_set>
20 
21 #include "hiappevent_verify.h"
22 #include "hilog/log.h"
23 #include "json/json.h"
24 
25 #undef LOG_DOMAIN
26 #define LOG_DOMAIN 0xD002D07
27 
28 #undef LOG_TAG
29 #define LOG_TAG "ProcessorConfigLoader"
30 
31 namespace OHOS {
32 namespace HiviewDFX {
33 namespace HiAppEvent {
34 namespace {
35 constexpr int ERR_CODE_SUCC = 0;
36 constexpr int ERR_CODE_PARAM_INVALID = -2;
37 
38 const char* const DEBUG_MODE = "debugMode";
39 const char* const ROUTE_INFO = "routeInfo";
40 const char* const APP_ID = "appId";
41 const char* const START_REPORT = "onStartReport";
42 const char* const BACKGROUND_REPORT = "onBackgroundReport";
43 const char* const PERIOD_REPORT = "periodReport";
44 const char* const BATCH_REPORT = "batchReport";
45 const char* const USER_IDS = "userIds";
46 const char* const USER_PROPERTIES = "userProperties";
47 const char* const EVENT_CONFIGS = "eventConfigs";
48 const char* const EVENT_CONFIG_DOMAIN = "domain";
49 const char* const EVENT_CONFIG_NAME = "name";
50 const char* const EVENT_CONFIG_REALTIME = "isRealTime";
51 const char* const CONFIG_ID = "configId";
52 const char* const CUSTOM_CONFIG = "customConfigs";
53 
54 const char* const PROCESSOR_CONFIG_PATH = "/system/etc/hiappevent/processor.json";
55 
56 struct ConfigProp {
57     const char* const key;
58     std::function<int()> func;
59 };
60 }
61 
62 class ProcessorConfigLoader::Impl {
63 public:
64     bool LoadProcessorConfig(const std::string& processorName, const std::string& configName);
65     const ReportConfig& GetReportConfig() const;
66 
67 private:
68     int ParseRouteInfoProp();
69     int ParseAppIdProp();
70     int ParseUserIdsProp();
71     int ParseUserPropertiesProp();
72     int ParseDebugModeProp();
73     int ParseStartReportProp();
74     int ParseBackgroundReportProp();
75     int ParsePeriodReportProp();
76     int ParseBatchReportProp();
77     int ParseEventConfigsProp();
78     int ParseConfigIdProp();
79     int ParseCustomConfigsProp();
80 
81     bool ParseProcessorConfig();
82     int ParseStringProp(const std::string& key, std::string& out,
83             const std::function<bool(std::string)>& validationFunc);
84     int ParseBoolProp(const std::string& key, bool& out);
85     int ParseIntProp(const std::string& key, int& out, const std::function<bool(int)>& validationFunc);
86     int ParseUnorderedSetProp(const std::string& key, std::unordered_set<std::string>& out,
87         const std::function<bool(std::string)>& validationFunc);
88     int ParseConfigReportProp(const Json::Value& eventConfig, HiAppEvent::EventConfig& reportConf);
89 
90 private:
91     ReportConfig conf_;
92     Json::Value jsonConfig_;
93 };
94 
ProcessorConfigLoader()95 ProcessorConfigLoader::ProcessorConfigLoader()
96     : impl_(std::make_unique<Impl>())
97 {}
98 
99 ProcessorConfigLoader::~ProcessorConfigLoader() = default;
100 
GetReportConfig() const101 const ReportConfig& ProcessorConfigLoader::GetReportConfig() const
102 {
103     return impl_->GetReportConfig();
104 }
105 
LoadProcessorConfig(const std::string & processorName,const std::string & configName)106 bool ProcessorConfigLoader::LoadProcessorConfig(const std::string& processorName, const std::string& configName)
107 {
108     return impl_->LoadProcessorConfig(processorName, configName);
109 }
110 
ParseStringProp(const std::string & key,std::string & out,const std::function<bool (std::string)> & validationFunc)111 int ProcessorConfigLoader::Impl::ParseStringProp(const std::string& key, std::string& out,
112     const std::function<bool(std::string)>& validationFunc)
113 {
114     if (!jsonConfig_.isMember(key)) {
115         out = "";
116         return ERR_CODE_SUCC;
117     }
118     if (!jsonConfig_[key].isString() || !validationFunc(jsonConfig_[key].asString())) {
119         return ERR_CODE_PARAM_INVALID;
120     }
121     out = jsonConfig_[key].asString();
122     return ERR_CODE_SUCC;
123 }
124 
ParseBoolProp(const std::string & key,bool & out)125 int ProcessorConfigLoader::Impl::ParseBoolProp(const std::string& key, bool& out)
126 {
127     if (!jsonConfig_.isMember(key)) {
128         out = false;
129         return ERR_CODE_SUCC;
130     }
131     if (!jsonConfig_[key].isBool()) {
132         return ERR_CODE_PARAM_INVALID;
133     }
134     out = jsonConfig_[key].asBool();
135     return ERR_CODE_SUCC;
136 }
137 
ParseIntProp(const std::string & key,int & out,const std::function<bool (int)> & validationFunc)138 int ProcessorConfigLoader::Impl::ParseIntProp(const std::string& key, int& out,
139     const std::function<bool(int)>& validationFunc)
140 {
141     if (!jsonConfig_.isMember(key)) {
142         out = 0;
143         return ERR_CODE_SUCC;
144     }
145     if (!jsonConfig_[key].isIntegral() || !validationFunc(jsonConfig_[key].asInt())) {
146         return ERR_CODE_PARAM_INVALID;
147     }
148     out = jsonConfig_[key].asInt();
149     return ERR_CODE_SUCC;
150 }
151 
ParseUnorderedSetProp(const std::string & key,std::unordered_set<std::string> & out,const std::function<bool (std::string)> & validationFunc)152 int ProcessorConfigLoader::Impl::ParseUnorderedSetProp(const std::string& key, std::unordered_set<std::string>& out,
153     const std::function<bool(std::string)>& validationFunc)
154 {
155     std::unordered_set<std::string> curSet;
156     if (!jsonConfig_.isMember(key)) {
157         out = std::move(curSet);
158         return ERR_CODE_SUCC;
159     }
160     if (!jsonConfig_[key].isArray()) {
161         return ERR_CODE_PARAM_INVALID;
162     }
163     for (const auto& userId : jsonConfig_[key]) {
164         if (!userId.isString() || !validationFunc(userId.asString())) {
165             return ERR_CODE_PARAM_INVALID;
166         }
167         curSet.insert(userId.asString());
168     }
169     out = std::move(curSet);
170     return ERR_CODE_SUCC;
171 }
172 
ParseConfigReportProp(const Json::Value & eventConfig,HiAppEvent::EventConfig & reportConf)173 int ProcessorConfigLoader::Impl::ParseConfigReportProp(const Json::Value& eventConfig,
174     HiAppEvent::EventConfig& reportConf)
175 {
176     if (eventConfig.isMember(EVENT_CONFIG_DOMAIN)) {
177         if (!eventConfig[EVENT_CONFIG_DOMAIN].isString()) {
178             HILOG_WARN(LOG_CORE, "Parameter error. The event domain parameter is invalid.");
179             return ERR_CODE_PARAM_INVALID;
180         }
181         reportConf.domain = eventConfig[EVENT_CONFIG_DOMAIN].asString();
182     }
183     if (eventConfig.isMember(EVENT_CONFIG_NAME)) {
184         if (!eventConfig[EVENT_CONFIG_NAME].isString()) {
185             HILOG_WARN(LOG_CORE, "Parameter error. The event name parameter is invalid.");
186             return ERR_CODE_PARAM_INVALID;
187         }
188         reportConf.name = eventConfig[EVENT_CONFIG_NAME].asString();
189     }
190     if (eventConfig.isMember(EVENT_CONFIG_REALTIME)) {
191         if (!eventConfig[EVENT_CONFIG_REALTIME].isBool()) {
192             HILOG_WARN(LOG_CORE, "Parameter error. The event isRealTime parameter is invalid.");
193             return ERR_CODE_PARAM_INVALID;
194         }
195         reportConf.isRealTime = eventConfig[EVENT_CONFIG_REALTIME].asBool();
196     }
197     if (!IsValidEventConfig(reportConf)) {
198         HILOG_WARN(LOG_CORE, "Parameter error. The event config is invalid, domain=%{public}s, name=%{public}s.",
199             reportConf.domain.c_str(), reportConf.name.c_str());
200         return ERR_CODE_PARAM_INVALID;
201     }
202     return ERR_CODE_SUCC;
203 }
204 
ParseRouteInfoProp()205 int ProcessorConfigLoader::Impl::ParseRouteInfoProp()
206 {
207     return ParseStringProp(ROUTE_INFO, conf_.routeInfo, IsValidRouteInfo);
208 }
209 
ParseAppIdProp()210 int ProcessorConfigLoader::Impl::ParseAppIdProp()
211 {
212     return ParseStringProp(APP_ID, conf_.appId, IsValidAppId);
213 }
214 
ParseUserIdsProp()215 int ProcessorConfigLoader::Impl::ParseUserIdsProp()
216 {
217     return ParseUnorderedSetProp(USER_IDS, conf_.userIdNames, IsValidUserIdName);
218 }
219 
ParseUserPropertiesProp()220 int ProcessorConfigLoader::Impl::ParseUserPropertiesProp()
221 {
222     return ParseUnorderedSetProp(USER_PROPERTIES, conf_.userPropertyNames, IsValidUserPropName);
223 }
224 
ParseDebugModeProp()225 int ProcessorConfigLoader::Impl::ParseDebugModeProp()
226 {
227     return ParseBoolProp(DEBUG_MODE, conf_.debugMode);
228 }
229 
ParseStartReportProp()230 int ProcessorConfigLoader::Impl::ParseStartReportProp()
231 {
232     return ParseBoolProp(START_REPORT, conf_.triggerCond.onStartup);
233 }
234 
ParseBackgroundReportProp()235 int ProcessorConfigLoader::Impl::ParseBackgroundReportProp()
236 {
237     return ParseBoolProp(BACKGROUND_REPORT, conf_.triggerCond.onBackground);
238 }
239 
ParsePeriodReportProp()240 int ProcessorConfigLoader::Impl::ParsePeriodReportProp()
241 {
242     return ParseIntProp(PERIOD_REPORT, conf_.triggerCond.timeout, IsValidPeriodReport);
243 }
244 
ParseBatchReportProp()245 int ProcessorConfigLoader::Impl::ParseBatchReportProp()
246 {
247     return ParseIntProp(BATCH_REPORT, conf_.triggerCond.row, IsValidBatchReport);
248 }
249 
ParseConfigIdProp()250 int ProcessorConfigLoader::Impl::ParseConfigIdProp()
251 {
252     return ParseIntProp(CONFIG_ID, conf_.configId, IsValidConfigId);
253 }
254 
ParseEventConfigsProp()255 int ProcessorConfigLoader::Impl::ParseEventConfigsProp()
256 {
257     std::vector<HiAppEvent::EventConfig> eventConfigs;
258     if (!jsonConfig_.isMember(EVENT_CONFIGS)) {
259         conf_.eventConfigs = std::move(eventConfigs);
260         return ERR_CODE_SUCC;
261     }
262     if (!jsonConfig_[EVENT_CONFIGS].isArray()) {
263         return ERR_CODE_PARAM_INVALID;
264     }
265     for (const auto& eventConfig : jsonConfig_[EVENT_CONFIGS]) {
266         if (!eventConfig.isObject()) {
267             return ERR_CODE_PARAM_INVALID;
268         }
269         HiAppEvent::EventConfig reportConf;
270         if (ParseConfigReportProp(eventConfig, reportConf) != ERR_CODE_SUCC) {
271             return ERR_CODE_PARAM_INVALID;
272         }
273         eventConfigs.push_back(reportConf);
274     }
275     conf_.eventConfigs = std::move(eventConfigs);
276     return ERR_CODE_SUCC;
277 }
278 
ParseCustomConfigsProp()279 int ProcessorConfigLoader::Impl::ParseCustomConfigsProp()
280 {
281     std::unordered_map<std::string, std::string> customConfigs;
282     if (!jsonConfig_.isMember(CUSTOM_CONFIG)) {
283         conf_.customConfigs = std::move(customConfigs);
284         return ERR_CODE_SUCC;
285     }
286     if (!jsonConfig_[CUSTOM_CONFIG].isObject()) {
287         return ERR_CODE_PARAM_INVALID;
288     }
289     const Json::Value::Members& members = jsonConfig_[CUSTOM_CONFIG].getMemberNames();
290     for (const auto& name : members) {
291         if (!jsonConfig_[CUSTOM_CONFIG][name].isString() ||
292             !IsValidCustomConfig(name, jsonConfig_[CUSTOM_CONFIG][name].asString())) {
293             return ERR_CODE_PARAM_INVALID;
294         }
295         customConfigs.insert(std::pair<std::string, std::string>(name, jsonConfig_[CUSTOM_CONFIG][name].asString()));
296     }
297     conf_.customConfigs = std::move(customConfigs);
298     return ERR_CODE_SUCC;
299 }
300 
ParseProcessorConfig()301 bool ProcessorConfigLoader::Impl::ParseProcessorConfig()
302 {
303     const ConfigProp CONFIG_PROPS[] = {
304         { .key = ROUTE_INFO, .func = [this]() -> int { return this->ParseRouteInfoProp(); } },
305         { .key = APP_ID, .func = [this]() -> int { return this->ParseAppIdProp(); } },
306         { .key = USER_IDS, .func = [this]() -> int { return this->ParseUserIdsProp(); } },
307         { .key = USER_PROPERTIES, .func = [this]() -> int { return this->ParseUserPropertiesProp(); } },
308         { .key = DEBUG_MODE, .func = [this]() -> int { return this->ParseDebugModeProp(); } },
309         { .key = START_REPORT, .func = [this]() -> int { return this->ParseStartReportProp(); } },
310         { .key = BACKGROUND_REPORT, .func = [this]() -> int { return this->ParseBackgroundReportProp(); } },
311         { .key = PERIOD_REPORT, .func = [this]() -> int { return this->ParsePeriodReportProp(); } },
312         { .key = BATCH_REPORT, .func = [this]() -> int { return this->ParseBatchReportProp(); } },
313         { .key = EVENT_CONFIGS, .func = [this]() -> int { return this->ParseEventConfigsProp(); } },
314         { .key = CONFIG_ID, .func = [this]() -> int { return this->ParseConfigIdProp(); } },
315         { .key = CUSTOM_CONFIG, .func = [this]() -> int { return this->ParseCustomConfigsProp(); } }
316     };
317 
318     for (const auto& prop : CONFIG_PROPS) {
319         if (prop.func() != ERR_CODE_SUCC) {
320             HILOG_ERROR(LOG_CORE, "failed to load processor config item:%{public}s", prop.key);
321             return false;
322         }
323     }
324     return true;
325 }
326 
LoadProcessorConfig(const std::string & processorName,const std::string & configName)327 bool ProcessorConfigLoader::Impl::LoadProcessorConfig(const std::string& processorName, const std::string& configName)
328 {
329     std::ifstream file(PROCESSOR_CONFIG_PATH);
330     if (!file.is_open()) {
331         HILOG_ERROR(LOG_CORE, "failed to open the processor config file, path:%{public}s.", PROCESSOR_CONFIG_PATH);
332         return false;
333     }
334 
335     Json::Value jsonConfig;
336     Json::CharReaderBuilder builder;
337     Json::CharReaderBuilder::strictMode(&builder.settings_);
338     JSONCPP_STRING errs;
339     if (!parseFromStream(builder, file, &jsonConfig, &errs)) {
340         HILOG_ERROR(LOG_CORE, "failed to parse the processor config file, path:%{public}s.", PROCESSOR_CONFIG_PATH);
341         return false;
342     }
343     if (jsonConfig.empty() || !jsonConfig.isObject()) {
344         HILOG_ERROR(LOG_CORE, "the processor config file is invalid.");
345         return false;
346     }
347     if (!jsonConfig.isMember(configName) || !jsonConfig[configName].isObject()) {
348         HILOG_ERROR(LOG_CORE, "the configName=%{public}s is invalid in config file.", configName.c_str());
349         return false;
350     }
351     conf_.name = processorName;
352     conf_.configName = configName;
353     jsonConfig_ = jsonConfig[configName];
354 
355     return ParseProcessorConfig();
356 }
357 
GetReportConfig() const358 const ReportConfig& ProcessorConfigLoader::Impl::GetReportConfig() const
359 {
360     return conf_;
361 }
362 } // namespace HiAppEvent
363 } // namespace HiviewDFX
364 } // namespace OHOS