• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "napi_hiappevent_processor.h"
16 
17 #include <cinttypes>
18 #include <map>
19 #include <string>
20 #include <unordered_set>
21 
22 #include "app_event_observer_mgr.h"
23 #include "hiappevent_base.h"
24 #include "hiappevent_verify.h"
25 #include "hilog/log.h"
26 #include "module_loader.h"
27 #include "napi_error.h"
28 #include "napi_util.h"
29 
30 namespace OHOS {
31 namespace HiviewDFX {
32 namespace NapiHiAppEventProcessor {
33 namespace {
34 constexpr HiLogLabel LABEL = { LOG_CORE, HIAPPEVENT_DOMAIN, "Napi_HiAppEvent_Processor" };
35 
36 constexpr int ERR_CODE_SUCC = 0;
37 constexpr int ERR_CODE_PARAM_FORMAT = -1;
38 constexpr int ERR_CODE_PARAM_INVALID = -2;
39 
40 const std::string PROCESSOR_NAME = "name";
41 const std::string DEBUG_MODE = "debugMode";
42 const std::string ROUTE_INFO = "routeInfo";
43 const std::string APP_ID = "appId";
44 const std::string START_REPORT = "onStartReport";
45 const std::string BACKGROUND_REPORT = "onBackgroundReport";
46 const std::string PERIOD_REPORT = "periodReport";
47 const std::string BATCH_REPORT = "batchReport";
48 const std::string USER_IDS = "userIds";
49 const std::string USER_PROPERTIES = "userProperties";
50 const std::string EVENT_CONFIGS = "eventConfigs";
51 const std::string EVENT_CONFIG_DOMAIN = "domain";
52 const std::string EVENT_CONFIG_NAME = "name";
53 const std::string EVENT_CONFIG_REALTIME = "isRealTime";
54 
55 const std::string CONFIG_PROP_TYPE_STR = "string";
56 const std::string CONFIG_PROP_TYPE_STR_ARRAY = "string array";
57 const std::string CONFIG_PROP_TYPE_BOOL = "boolean";
58 const std::string CONFIG_PROP_TYPE_NUM = "number";
59 const std::string CONFIG_PROP_TYPE_EVENT_CONFIG = "AppEventReportConfig array";
60 }
61 
GenConfigStrProp(const napi_env env,const napi_value config,const std::string & key,std::string & out,const bool optional=true)62 bool GenConfigStrProp(const napi_env env, const napi_value config, const std::string& key, std::string& out,
63     const bool optional = true)
64 {
65     if (!NapiUtil::HasProperty(env, config, key)) {
66         return optional;
67     }
68     napi_value value = NapiUtil::GetProperty(env, config, key);
69     if (value == nullptr || !NapiUtil::IsString(env, value)) {
70         return false;
71     }
72     out = NapiUtil::GetString(env, value);
73     return true;
74 }
75 
GenConfigStrsProp(const napi_env env,const napi_value config,const std::string & key,std::unordered_set<std::string> & out)76 bool GenConfigStrsProp(const napi_env env, const napi_value config, const std::string& key,
77     std::unordered_set<std::string>& out)
78 {
79     if (NapiUtil::HasProperty(env, config, key)) {
80         napi_value value = NapiUtil::GetProperty(env, config, key);
81         if (value == nullptr || !NapiUtil::IsArray(env, value) || !NapiUtil::IsArrayType(env, value, napi_string)) {
82             return false;
83         }
84         NapiUtil::GetStringsToSet(env, value, out);
85     }
86     return true;
87 }
88 
GenConfigBoolProp(const napi_env env,const napi_value config,const std::string & key,bool & out)89 bool GenConfigBoolProp(const napi_env env, const napi_value config, const std::string& key, bool& out)
90 {
91     if (NapiUtil::HasProperty(env, config, key)) {
92         napi_value value = NapiUtil::GetProperty(env, config, key);
93         if (value == nullptr || !NapiUtil::IsBoolean(env, value)) {
94             return false;
95         }
96         out = NapiUtil::GetBoolean(env, value);
97     }
98     return true;
99 }
100 
GenConfigIntProp(const napi_env env,const napi_value config,const std::string & key,int32_t & out)101 bool GenConfigIntProp(const napi_env env, const napi_value config, const std::string& key, int32_t& out)
102 {
103     if (NapiUtil::HasProperty(env, config, key)) {
104         napi_value value = NapiUtil::GetProperty(env, config, key);
105         if (value == nullptr || !NapiUtil::IsNumber(env, value)) {
106             return false;
107         }
108         out = NapiUtil::GetInt32(env, value);
109     }
110     return true;
111 }
112 
GenConfigNameProp(const napi_env env,const napi_value config,const std::string & key,ReportConfig & out)113 int GenConfigNameProp(const napi_env env, const napi_value config, const std::string& key, ReportConfig& out)
114 {
115     std::string name;
116     if (!GenConfigStrProp(env, config, key, name, false)) {
117         NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg(key, CONFIG_PROP_TYPE_STR));
118         return ERR_CODE_PARAM_FORMAT;
119     }
120     if (!IsValidProcessorName(name)) {
121         NapiUtil::ThrowError(env, NapiError::ERR_PARAM, "Invalid processor name.");
122         return ERR_CODE_PARAM_FORMAT;
123     }
124     out.name = name;
125     return ERR_CODE_SUCC;
126 }
127 
GenConfigRouteInfoProp(const napi_env env,const napi_value config,const std::string & key,ReportConfig & out)128 int GenConfigRouteInfoProp(const napi_env env, const napi_value config, const std::string& key, ReportConfig& out)
129 {
130     std::string routeInfo;
131     if (!GenConfigStrProp(env, config, key, routeInfo) || !IsValidRouteInfo(routeInfo)) {
132         return ERR_CODE_PARAM_INVALID;
133     }
134     out.routeInfo = routeInfo;
135     return ERR_CODE_SUCC;
136 }
137 
GenConfigAppIdProp(const napi_env env,const napi_value config,const std::string & key,ReportConfig & out)138 int GenConfigAppIdProp(const napi_env env, const napi_value config, const std::string& key, ReportConfig& out)
139 {
140     std::string appId;
141     if (!GenConfigStrProp(env, config, key, appId) || !IsValidAppId(appId)) {
142         return ERR_CODE_PARAM_INVALID;
143     }
144     out.appId = appId;
145     return ERR_CODE_SUCC;
146 }
147 
GenConfigUserIdsProp(const napi_env env,const napi_value config,const std::string & key,ReportConfig & out)148 int GenConfigUserIdsProp(const napi_env env, const napi_value config, const std::string& key, ReportConfig& out)
149 {
150     std::unordered_set<std::string> userIdNames;
151     if (!GenConfigStrsProp(env, config, key, userIdNames)) {
152         return ERR_CODE_PARAM_INVALID;
153     }
154     for (auto userId : userIdNames) {
155         if (!IsValidUserIdName(userId)) {
156             return ERR_CODE_PARAM_INVALID;
157         }
158     }
159     out.userIdNames = userIdNames;
160     return ERR_CODE_SUCC;
161 }
162 
GenConfigUserPropertiesProp(const napi_env env,const napi_value config,const std::string & key,ReportConfig & out)163 int GenConfigUserPropertiesProp(const napi_env env, const napi_value config, const std::string& key, ReportConfig& out)
164 {
165     std::unordered_set<std::string> userPropertyNames;
166     if (!GenConfigStrsProp(env, config, key, userPropertyNames)) {
167         return ERR_CODE_PARAM_INVALID;
168     }
169     for (auto userProperty : userPropertyNames) {
170         if (!IsValidUserPropName(userProperty)) {
171             return ERR_CODE_PARAM_INVALID;
172         }
173     }
174     out.userPropertyNames = userPropertyNames;
175     return ERR_CODE_SUCC;
176 }
177 
GenConfigDebugModeProp(const napi_env env,const napi_value config,const std::string & key,ReportConfig & out)178 int GenConfigDebugModeProp(const napi_env env, const napi_value config, const std::string& key, ReportConfig& out)
179 {
180     return GenConfigBoolProp(env, config, key, out.debugMode) ? ERR_CODE_SUCC : ERR_CODE_PARAM_INVALID;
181 }
182 
GenConfigStartReportProp(const napi_env env,const napi_value config,const std::string & key,ReportConfig & out)183 int GenConfigStartReportProp(const napi_env env, const napi_value config, const std::string& key, ReportConfig& out)
184 {
185     return GenConfigBoolProp(env, config, key, out.triggerCond.onStartup) ? ERR_CODE_SUCC : ERR_CODE_PARAM_INVALID;
186 }
187 
GenConfigBackgroundReportProp(const napi_env env,const napi_value config,const std::string & key,ReportConfig & out)188 int GenConfigBackgroundReportProp(const napi_env env, const napi_value config, const std::string& key,
189     ReportConfig& out)
190 {
191     return GenConfigBoolProp(env, config, key, out.triggerCond.onBackground) ? ERR_CODE_SUCC : ERR_CODE_PARAM_INVALID;
192 }
193 
GenConfigPeriodReportProp(const napi_env env,const napi_value config,const std::string & key,ReportConfig & out)194 int GenConfigPeriodReportProp(const napi_env env, const napi_value config, const std::string& key, ReportConfig& out)
195 {
196     int timeout = 0;
197     if (!GenConfigIntProp(env, config, key, timeout) || !IsValidPeriodReport(timeout)) {
198         return ERR_CODE_PARAM_INVALID;
199     }
200     out.triggerCond.timeout = timeout;
201     return ERR_CODE_SUCC;
202 }
203 
GenConfigBatchReportProp(const napi_env env,const napi_value config,const std::string & key,ReportConfig & out)204 int GenConfigBatchReportProp(const napi_env env, const napi_value config, const std::string& key, ReportConfig& out)
205 {
206     int row = 0;
207     if (!GenConfigIntProp(env, config, key, row) || !IsValidBatchReport(row)) {
208         return ERR_CODE_PARAM_INVALID;
209     }
210     out.triggerCond.row = row;
211     return ERR_CODE_SUCC;
212 }
213 
GenConfigReportProp(const napi_env env,const napi_value config,HiAppEvent::EventConfig & out)214 int GenConfigReportProp(const napi_env env, const napi_value config, HiAppEvent::EventConfig& out)
215 {
216     HiAppEvent::EventConfig reportConf;
217     if (!GenConfigStrProp(env, config, EVENT_CONFIG_DOMAIN, reportConf.domain)) {
218         HiLog::Warn(LABEL, "Parameter error. The event domain parameter is invalid.");
219         return ERR_CODE_PARAM_INVALID;
220     }
221     if (!GenConfigStrProp(env, config, EVENT_CONFIG_NAME, reportConf.name)) {
222         HiLog::Warn(LABEL, "Parameter error. The event name parameter is invalid.");
223         return ERR_CODE_PARAM_INVALID;
224     }
225     if (!GenConfigBoolProp(env, config, EVENT_CONFIG_REALTIME, reportConf.isRealTime)) {
226         HiLog::Warn(LABEL, "Parameter error. The event isRealTime parameter is invalid.");
227         return ERR_CODE_PARAM_INVALID;
228     }
229     if (!IsValidEventConfig(reportConf)) {
230         HiLog::Warn(LABEL, "Parameter error. The event config is invalid, domain=%{public}s, name=%{public}s.",
231             reportConf.domain.c_str(), reportConf.name.c_str());
232         return ERR_CODE_PARAM_INVALID;
233     }
234     out = reportConf;
235     return ERR_CODE_SUCC;
236 }
237 
GenConfigEventConfigsProp(const napi_env env,const napi_value config,const std::string & key,ReportConfig & out)238 int GenConfigEventConfigsProp(const napi_env env, const napi_value config, const std::string& key, ReportConfig& out)
239 {
240     if (NapiUtil::HasProperty(env, config, key)) {
241         napi_value napiArr = NapiUtil::GetProperty(env, config, key);
242         if (!NapiUtil::IsArray(env, napiArr)) {
243             return ERR_CODE_PARAM_INVALID;
244         }
245         std::vector<HiAppEvent::EventConfig> eventConfigs;
246         uint32_t length = NapiUtil::GetArrayLength(env, napiArr);
247         for (uint32_t i = 0; i < length; i++) {
248             napi_value element = NapiUtil::GetElement(env, napiArr, i);
249             HiAppEvent::EventConfig reportConf;
250             int ret = GenConfigReportProp(env, element, reportConf);
251             if (ret != ERR_CODE_SUCC) {
252                 return ret;
253             }
254             eventConfigs.push_back(reportConf);
255         }
256         out.eventConfigs = eventConfigs;
257     }
258     return ERR_CODE_SUCC;
259 }
260 
261 typedef struct ConfigProp {
262     std::string type;
263     std::string key;
264     int (*func)(const napi_env, const napi_value, const std::string&, ReportConfig&);
265 } ConfigProp;
266 
267 const ConfigProp CONFIG_PROPS[] = {
268     {
269         .type = CONFIG_PROP_TYPE_STR,
270         .key = PROCESSOR_NAME,
271         .func = GenConfigNameProp
272     },
273     {
274         .type = CONFIG_PROP_TYPE_STR,
275         .key = ROUTE_INFO,
276         .func = GenConfigRouteInfoProp
277     },
278     {
279         .type = CONFIG_PROP_TYPE_STR,
280         .key = APP_ID,
281         .func = GenConfigAppIdProp
282     },
283     {
284         .type = CONFIG_PROP_TYPE_STR_ARRAY,
285         .key = USER_IDS,
286         .func = GenConfigUserIdsProp
287     },
288     {
289         .type = CONFIG_PROP_TYPE_STR_ARRAY,
290         .key = USER_PROPERTIES,
291         .func = GenConfigUserPropertiesProp
292     },
293     {
294         .type = CONFIG_PROP_TYPE_BOOL,
295         .key = DEBUG_MODE,
296         .func = GenConfigDebugModeProp
297     },
298     {
299         .type = CONFIG_PROP_TYPE_BOOL,
300         .key = START_REPORT,
301         .func = GenConfigStartReportProp
302     },
303     {
304         .type = CONFIG_PROP_TYPE_BOOL,
305         .key = BACKGROUND_REPORT,
306         .func = GenConfigBackgroundReportProp
307     },
308     {
309         .type = CONFIG_PROP_TYPE_NUM,
310         .key = PERIOD_REPORT,
311         .func = GenConfigPeriodReportProp
312     },
313     {
314         .type = CONFIG_PROP_TYPE_NUM,
315         .key = BATCH_REPORT,
316         .func = GenConfigBatchReportProp
317     },
318     {
319         .type = CONFIG_PROP_TYPE_EVENT_CONFIG,
320         .key = EVENT_CONFIGS,
321         .func = GenConfigEventConfigsProp
322     }
323 };
324 
TransConfig(const napi_env env,const napi_value config,ReportConfig & out)325 int TransConfig(const napi_env env, const napi_value config, ReportConfig& out)
326 {
327     if (!NapiUtil::IsObject(env, config)) {
328         HiLog::Error(LABEL, "failed to add processor, params format error");
329         NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("config", "Processor"));
330         return -1;
331     }
332     for (auto prop : CONFIG_PROPS) {
333         int ret = (prop.func)(env, config, prop.key, out);
334         if (ret == ERR_CODE_PARAM_FORMAT) {
335             HiLog::Error(LABEL, "failed to add processor, params format error");
336             return -1;
337         } else if (ret == ERR_CODE_PARAM_INVALID) {
338             HiLog::Warn(LABEL, "Parameter error. The %{public}s parameter is invalid.", prop.key.c_str());
339         }
340     }
341     return 0;
342 }
343 
AddProcessor(const napi_env env,const napi_value config,napi_value & out)344 bool AddProcessor(const napi_env env, const napi_value config, napi_value& out)
345 {
346     ReportConfig conf;
347     int ret = TransConfig(env, config, conf);
348     if (ret != 0) {
349         out = NapiUtil::CreateInt64(env, -1);
350         return false;
351     }
352     std::string name = conf.name;
353     if (name.empty()) {
354         HiLog::Error(LABEL, "processor name can not be empty.");
355         out = NapiUtil::CreateInt64(env, -1);
356         return false;
357     }
358     if (HiAppEvent::ModuleLoader::GetInstance().Load(name) != 0) {
359         HiLog::Warn(LABEL, "failed to add processor=%{public}s, name no found", name.c_str());
360         out = NapiUtil::CreateInt64(env, -1);
361         return true;
362     }
363     int64_t processorId = AppEventObserverMgr::GetInstance().RegisterObserver(name, conf);
364     if (processorId <= 0) {
365         HiLog::Warn(LABEL, "failed to add processor=%{public}s, register processor error", name.c_str());
366         out = NapiUtil::CreateInt64(env, -1);
367         return false;
368     }
369     out = NapiUtil::CreateInt64(env, processorId);
370     return true;
371 }
372 
RemoveProcessor(const napi_env env,const napi_value id)373 bool RemoveProcessor(const napi_env env, const napi_value id)
374 {
375     if (!NapiUtil::IsNumber(env, id)) {
376         HiLog::Warn(LABEL, "failed to remove processor, params format error");
377         NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("id", "number"));
378         return false;
379     }
380     int64_t processorId = NapiUtil::GetInt64(env, id);
381     if (processorId <= 0) {
382         HiLog::Error(LABEL, "failed to remove processor id=%{public}" PRId64, processorId);
383         return true;
384     }
385     if (AppEventObserverMgr::GetInstance().UnregisterObserver(processorId) != 0) {
386         HiLog::Warn(LABEL, "failed to remove processor id=%{public}" PRId64, processorId);
387         return false;
388     }
389     return true;
390 }
391 } // namespace NapiHiAppEventProcessor
392 } // namespace HiviewDFX
393 } // namespace OHOS
394