1 /*
2 * Copyright (c) 2022-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
16 #include "napi_hisysevent_util.h"
17
18 #include <cinttypes>
19
20 #include "def.h"
21 #include "hilog/log.h"
22 #include "ipc_skeleton.h"
23 #include "json/json.h"
24 #include "ret_code.h"
25 #include "ret_def.h"
26 #include "stringfilter.h"
27 #include "tokenid_kit.h"
28
29 namespace OHOS {
30 namespace HiviewDFX {
31 namespace {
32 constexpr HiLogLabel LABEL = { LOG_CORE, 0xD002D08, "NAPI_HISYSEVENT_UTIL" };
33 constexpr uint32_t JS_STR_PARM_LEN_LIMIT = 1024 * 10; // 10k
34 constexpr uint32_t BUF_SIZE = 1024 * 11; // 11k
35 constexpr int SYS_EVENT_INFO_PARAM_INDEX = 0;
36 constexpr long long DEFAULT_TIME_STAMP = -1;
37 constexpr long long DEFAULT_SEQ = 0;
38 constexpr int32_t DEFAULT_MAX_EVENTS = 1000;
39 constexpr char PARAMS_ATTR[] = "params";
40 constexpr char TAG_ATTR[] = "tag";
41 constexpr char RULE_TYPE_ATTR[] = "ruleType";
42 constexpr char BEGIN_TIME_ATTR[] = "beginTime";
43 constexpr char END_TIME_ATTR[] = "endTime";
44 constexpr char MAX_EVENTS_ATTR[] = "maxEvents";
45 constexpr char BEGIN_SEQ_ATTR[] = "fromSeq";
46 constexpr char END_SEQ_ATTR[] = "toSeq";
47 constexpr char NAMES_ATTR[] = "names";
48 constexpr char CONDITION_ATTR[] = "condition";
49 constexpr char DOMAIN__KEY[] = "domain_";
50 constexpr char NAME__KEY[] = "name_";
51 constexpr char TYPE__KEY[] = "type_";
52 const std::string INVALID_KEY_TYPE_ARR[] = {
53 "[object Object]",
54 "null",
55 "()",
56 ","
57 };
58
CheckKeyTypeString(const std::string & str)59 bool CheckKeyTypeString(const std::string& str)
60 {
61 bool ret = true;
62 for (auto invalidType : INVALID_KEY_TYPE_ARR) {
63 if (str.find(invalidType) != std::string::npos) {
64 ret = false;
65 break;
66 }
67 }
68 return ret;
69 }
70
GetValueType(const napi_env env,const napi_value & value)71 napi_valuetype GetValueType(const napi_env env, const napi_value& value)
72 {
73 napi_valuetype valueType = napi_undefined;
74 napi_status ret = napi_typeof(env, value, &valueType);
75 if (ret != napi_ok) {
76 HiLog::Error(LABEL, "failed to parse the type of napi value.");
77 }
78 return valueType;
79 }
80
IsValueTypeValid(const napi_env env,const napi_value & jsObj,const napi_valuetype typeName)81 bool IsValueTypeValid(const napi_env env, const napi_value& jsObj,
82 const napi_valuetype typeName)
83 {
84 napi_valuetype valueType = GetValueType(env, jsObj);
85 if (valueType != typeName) {
86 HiLog::Error(LABEL, "napi value type not match: valueType=%{public}d, typeName=%{public}d.",
87 valueType, typeName);
88 return false;
89 }
90 return true;
91 }
92
CheckValueIsArray(const napi_env env,const napi_value & jsObj)93 bool CheckValueIsArray(const napi_env env, const napi_value& jsObj)
94 {
95 if (!IsValueTypeValid(env, jsObj, napi_valuetype::napi_object)) {
96 return false;
97 }
98 bool isArray = false;
99 napi_status ret = napi_is_array(env, jsObj, &isArray);
100 if (ret != napi_ok) {
101 HiLog::Error(LABEL, "failed to check array napi value.");
102 }
103 return isArray;
104 }
105
ParseBoolValue(const napi_env env,const napi_value & value,bool defalutValue=false)106 bool ParseBoolValue(const napi_env env, const napi_value& value, bool defalutValue = false)
107 {
108 bool boolValue = defalutValue;
109 napi_status ret = napi_get_value_bool(env, value, &boolValue);
110 if (ret != napi_ok) {
111 HiLog::Error(LABEL, "failed to parse napi value of boolean type.");
112 }
113 return boolValue;
114 }
115
ParseNumberValue(const napi_env env,const napi_value & value,double defaultValue=0.0)116 double ParseNumberValue(const napi_env env, const napi_value& value, double defaultValue = 0.0)
117 {
118 double numValue = defaultValue;
119 napi_status ret = napi_get_value_double(env, value, &numValue);
120 if (ret != napi_ok) {
121 HiLog::Error(LABEL, "failed to parse napi value of number type.");
122 }
123 return numValue;
124 }
125
ParseStringValue(const napi_env env,const napi_value & value,std::string defaultValue="")126 std::string ParseStringValue(const napi_env env, const napi_value& value, std::string defaultValue = "")
127 {
128 char buf[BUF_SIZE] = {0};
129 size_t bufLength = 0;
130 napi_status status = napi_get_value_string_utf8(env, value, buf, BUF_SIZE - 1, &bufLength);
131 if (status != napi_ok) {
132 HiLog::Error(LABEL, "failed to parse napi value of string type.");
133 return defaultValue;
134 }
135 std::string dest = std::string {buf};
136 return dest;
137 }
138
ParseBigIntValue(const napi_env env,const napi_value & value,double defaultValue=0.0)139 double ParseBigIntValue(const napi_env env, const napi_value& value, double defaultValue = 0.0)
140 {
141 std::string strFormat = ParseStringValue(env, value);
142 if (strFormat.empty()) {
143 return defaultValue;
144 }
145 bool lossless = true;
146 napi_status status;
147 double ret = defaultValue;
148 if (strFormat[0] == '-') {
149 int64_t int64Value = static_cast<int64_t>(defaultValue);
150 status = napi_get_value_bigint_int64(env, value, &int64Value, &lossless);
151 ret = static_cast<double>(int64Value);
152 } else {
153 uint64_t uint64Value = static_cast<uint64_t>(defaultValue);
154 status = napi_get_value_bigint_uint64(env, value, &uint64Value, &lossless);
155 ret = static_cast<double>(uint64Value);
156 }
157 if (status != napi_ok) {
158 HiLog::Error(LABEL, "failed to parse napi value of big int type.");
159 }
160 return ret;
161 }
162
GetTagAttribute(const napi_env env,const napi_value & object,std::string defaultValue="")163 std::string GetTagAttribute(const napi_env env, const napi_value& object, std::string defaultValue = "")
164 {
165 napi_value propertyValue = NapiHiSysEventUtil::GetPropertyByName(env, object, TAG_ATTR);
166 if (IsValueTypeValid(env, propertyValue, napi_valuetype::napi_null) ||
167 IsValueTypeValid(env, propertyValue, napi_valuetype::napi_undefined)) {
168 return defaultValue;
169 }
170 if (IsValueTypeValid(env, propertyValue, napi_valuetype::napi_string)) {
171 return ParseStringValue(env, propertyValue, defaultValue);
172 }
173 NapiHiSysEventUtil::ThrowParamTypeError(env, TAG_ATTR, "string");
174 HiLog::Error(LABEL, "type of listener tag is not napi_string.");
175 return defaultValue;
176 }
177
GetStringTypeAttribute(const napi_env env,const napi_value & object,const std::string & propertyName,std::string defaultValue="")178 std::string GetStringTypeAttribute(const napi_env env, const napi_value& object,
179 const std::string& propertyName, std::string defaultValue = "")
180 {
181 napi_value propertyValue = NapiHiSysEventUtil::GetPropertyByName(env, object, propertyName);
182 if (!IsValueTypeValid(env, propertyValue, napi_valuetype::napi_string)) {
183 NapiHiSysEventUtil::ThrowParamTypeError(env, propertyName, "string");
184 HiLog::Error(LABEL, "type is not napi_string.");
185 return defaultValue;
186 }
187 return ParseStringValue(env, propertyValue, defaultValue);
188 }
189
GetLonglongTypeAttribute(const napi_env env,const napi_value & object,const std::string & propertyName,long long defaultValue=0)190 long long GetLonglongTypeAttribute(const napi_env env, const napi_value& object,
191 const std::string& propertyName, long long defaultValue = 0)
192 {
193 napi_value propertyValue = NapiHiSysEventUtil::GetPropertyByName(env, object, propertyName);
194 bool isNumberType = IsValueTypeValid(env, propertyValue, napi_valuetype::napi_number);
195 bool isBigIntType = IsValueTypeValid(env, propertyValue, napi_valuetype::napi_bigint);
196 if (!isNumberType && !isBigIntType) {
197 HiLog::Error(LABEL, "type is not napi_number or napi_bigint.");
198 return defaultValue;
199 }
200 if (isBigIntType) {
201 return static_cast<long long>(ParseBigIntValue(env, propertyValue));
202 }
203 return static_cast<long long>(ParseNumberValue(env, propertyValue, defaultValue));
204 }
205
ParseInt32Value(const napi_env env,const napi_value & value,int32_t defaultValue=0)206 int32_t ParseInt32Value(const napi_env env, const napi_value& value, int32_t defaultValue = 0)
207 {
208 int32_t int32Value = 0;
209 napi_status ret = napi_get_value_int32(env, value, &int32Value);
210 if (ret != napi_ok) {
211 HiLog::Error(LABEL, "failed to parse napi value of number type.");
212 return defaultValue;
213 }
214 return int32Value;
215 }
216
GetInt32TypeAttribute(const napi_env env,const napi_value & object,const std::string & propertyName,int32_t defaultValue=0)217 int32_t GetInt32TypeAttribute(const napi_env env, const napi_value& object,
218 const std::string& propertyName, int32_t defaultValue = 0)
219 {
220 napi_value propertyValue = NapiHiSysEventUtil::GetPropertyByName(env, object, propertyName);
221 if (!IsValueTypeValid(env, propertyValue, napi_valuetype::napi_number)) {
222 NapiHiSysEventUtil::ThrowParamTypeError(env, propertyName, "number");
223 HiLog::Error(LABEL, "type is not napi_number.");
224 return defaultValue;
225 }
226 return ParseInt32Value(env, propertyValue);
227 }
228
AppendBoolArrayData(const napi_env env,HiSysEventInfo & info,const std::string & key,const napi_value array,size_t len)229 void AppendBoolArrayData(const napi_env env, HiSysEventInfo& info, const std::string& key,
230 const napi_value array, size_t len)
231 {
232 std::vector<bool> values;
233 napi_value element;
234 napi_status status;
235 for (uint32_t i = 0; i < len; i++) {
236 status = napi_get_element(env, array, i, &element);
237 if (status != napi_ok) {
238 HiLog::Error(LABEL, "failed to get the element of bool array.");
239 continue;
240 }
241 if (IsValueTypeValid(env, element, napi_valuetype::napi_boolean)) {
242 values.emplace_back(ParseBoolValue(env, element));
243 }
244 }
245 info.boolArrayParams[key] = values;
246 }
247
AppendNumberArrayData(const napi_env env,HiSysEventInfo & info,const std::string & key,const napi_value array,size_t len)248 void AppendNumberArrayData(const napi_env env, HiSysEventInfo& info, const std::string& key,
249 const napi_value array, size_t len)
250 {
251 std::vector<double> values;
252 napi_value element;
253 napi_status status;
254 for (uint32_t i = 0; i < len; i++) {
255 status = napi_get_element(env, array, i, &element);
256 if (status != napi_ok) {
257 HiLog::Error(LABEL, "failed to get the element of number array.");
258 continue;
259 }
260 if (IsValueTypeValid(env, element, napi_valuetype::napi_number)) {
261 values.emplace_back(ParseNumberValue(env, element));
262 }
263 }
264 info.doubleArrayParams[key] = values;
265 }
266
AppendBigIntArrayData(const napi_env env,HiSysEventInfo & info,const std::string & key,const napi_value array,size_t len)267 void AppendBigIntArrayData(const napi_env env, HiSysEventInfo& info, const std::string& key,
268 const napi_value array, size_t len)
269 {
270 std::vector<double> values;
271 napi_value element;
272 napi_status status;
273 for (uint32_t i = 0; i < len; i++) {
274 status = napi_get_element(env, array, i, &element);
275 if (status != napi_ok) {
276 HiLog::Error(LABEL, "failed to get the element of big int array.");
277 continue;
278 }
279 if (IsValueTypeValid(env, element, napi_valuetype::napi_bigint)) {
280 values.emplace_back(ParseBigIntValue(env, element));
281 }
282 }
283 info.doubleArrayParams[key] = values;
284 }
285
AppendStringArrayData(const napi_env env,HiSysEventInfo & info,const std::string & key,const napi_value array,size_t len)286 void AppendStringArrayData(const napi_env env, HiSysEventInfo& info, const std::string& key,
287 const napi_value array, size_t len)
288 {
289 std::vector<std::string> values;
290 napi_value element;
291 napi_status status;
292 for (uint32_t i = 0; i < len; i++) {
293 status = napi_get_element(env, array, i, &element);
294 if (status != napi_ok) {
295 HiLog::Error(LABEL, "failed to get the element of string array.");
296 continue;
297 }
298 if (IsValueTypeValid(env, element, napi_valuetype::napi_string)) {
299 values.emplace_back(ParseStringValue(env, element));
300 }
301 }
302 info.stringArrayParams[key] = values;
303 }
304
AddArrayParamToEventInfo(const napi_env env,HiSysEventInfo & info,const std::string & key,napi_value & array)305 void AddArrayParamToEventInfo(const napi_env env, HiSysEventInfo& info, const std::string& key, napi_value& array)
306 {
307 uint32_t len = 0;
308 napi_status status = napi_get_array_length(env, array, &len);
309 if (status != napi_ok) {
310 HiLog::Error(LABEL, "failed to get the length of param array.");
311 return;
312 }
313 if (len == 0) {
314 HiLog::Warn(LABEL, "array is empty.");
315 return;
316 }
317 napi_value firstItem;
318 status = napi_get_element(env, array, 0, &firstItem);
319 if (status != napi_ok) {
320 HiLog::Error(LABEL, "failed to get the first element in array.");
321 return;
322 }
323 napi_valuetype type;
324 status = napi_typeof(env, firstItem, &type);
325 if (status != napi_ok) {
326 HiLog::Error(LABEL, "failed to get the type of the first element in array.");
327 return;
328 }
329 switch (type) {
330 case napi_valuetype::napi_boolean:
331 AppendBoolArrayData(env, info, key, array, len);
332 HiLog::Debug(LABEL, "AppendBoolArrayData: %{public}s.", key.c_str());
333 break;
334 case napi_valuetype::napi_number:
335 AppendNumberArrayData(env, info, key, array, len);
336 HiLog::Debug(LABEL, "AppendNumberArrayData: %{public}s.", key.c_str());
337 break;
338 case napi_valuetype::napi_bigint:
339 AppendBigIntArrayData(env, info, key, array, len);
340 HiLog::Debug(LABEL, "AppendBigIntArrayData: %{public}s.", key.c_str());
341 break;
342 case napi_valuetype::napi_string:
343 AppendStringArrayData(env, info, key, array, len);
344 HiLog::Debug(LABEL, "AppendStringArrayData: %{public}s.", key.c_str());
345 break;
346 default:
347 break;
348 }
349 }
350
AddParamToEventInfo(const napi_env env,HiSysEventInfo & info,const std::string & key,napi_value & value)351 void AddParamToEventInfo(const napi_env env, HiSysEventInfo& info, const std::string& key, napi_value& value)
352 {
353 if (CheckValueIsArray(env, value)) {
354 AddArrayParamToEventInfo(env, info, key, value);
355 return;
356 }
357 napi_valuetype type = GetValueType(env, value);
358 switch (type) {
359 case napi_valuetype::napi_boolean:
360 info.boolParams[key] = ParseBoolValue(env, value);
361 break;
362 case napi_valuetype::napi_number:
363 info.doubleParams[key] = ParseNumberValue(env, value);
364 break;
365 case napi_valuetype::napi_string:
366 info.stringParams[key] = ParseStringValue(env, value);
367 break;
368 case napi_valuetype::napi_bigint:
369 info.doubleParams[key] = ParseBigIntValue(env, value);
370 break;
371 default:
372 break;
373 }
374 }
375
GetObjectTypeAttribute(const napi_env env,const napi_value & object,const std::string & propertyName,HiSysEventInfo & info)376 void GetObjectTypeAttribute(const napi_env env, const napi_value& object,
377 const std::string& propertyName, HiSysEventInfo& info)
378 {
379 napi_value propertyValue = NapiHiSysEventUtil::GetPropertyByName(env, object, propertyName);
380 if (!IsValueTypeValid(env, propertyValue, napi_valuetype::napi_object)) {
381 HiLog::Error(LABEL, "type is not napi_object.");
382 return;
383 }
384 napi_value keyArr = nullptr;
385 napi_status status = napi_get_property_names(env, propertyValue, &keyArr);
386 if (status != napi_ok) {
387 HiLog::Error(LABEL, "failed to parse property names of a js object.");
388 return;
389 }
390 uint32_t len = 0;
391 status = napi_get_array_length(env, keyArr, &len);
392 if (status != napi_ok) {
393 HiLog::Error(LABEL, "failed to get the length of the key-value pairs.");
394 return;
395 }
396 for (uint32_t i = 0; i < len; i++) {
397 napi_value key = nullptr;
398 napi_get_element(env, keyArr, i, &key);
399 if (!IsValueTypeValid(env, key, napi_valuetype::napi_string)) {
400 HiLog::Warn(LABEL, "this param would be discarded because of invalid type of the key.");
401 continue;
402 }
403 char buf[BUF_SIZE] = {0};
404 size_t valueLen = 0;
405 napi_get_value_string_utf8(env, key, buf, BUF_SIZE - 1, &valueLen);
406 if (!CheckKeyTypeString(buf)) {
407 HiLog::Warn(LABEL, "this param would be discarded because of invalid format of the key.");
408 continue;
409 }
410 napi_value val = NapiHiSysEventUtil::GetPropertyByName(env, propertyValue, buf);
411 AddParamToEventInfo(env, info, buf, val);
412 }
413 }
414
ParseStringArray(const napi_env env,napi_value & arrayValue,std::vector<std::string> & arrayDest)415 void ParseStringArray(const napi_env env, napi_value& arrayValue, std::vector<std::string>& arrayDest)
416 {
417 if (!CheckValueIsArray(env, arrayValue)) {
418 HiLog::Error(LABEL, "try to parse a array from a napi value without array type");
419 return;
420 }
421 uint32_t len = 0;
422 napi_status status = napi_get_array_length(env, arrayValue, &len);
423 if (status != napi_ok) {
424 return;
425 }
426 napi_value element;
427 for (uint32_t i = 0; i < len; i++) {
428 status = napi_get_element(env, arrayValue, i, &element);
429 if (status != napi_ok) {
430 return;
431 }
432 if (IsValueTypeValid(env, element, napi_valuetype::napi_string)) {
433 std::string str = ParseStringValue(env, element);
434 HiLog::Debug(LABEL, "parse string: %{public}s.", str.c_str());
435 arrayDest.emplace_back(str);
436 }
437 }
438 }
439
ParseListenerRule(const napi_env env,const napi_value & jsObj)440 ListenerRule ParseListenerRule(const napi_env env, const napi_value& jsObj)
441 {
442 if (!IsValueTypeValid(env, jsObj, napi_valuetype::napi_object)) {
443 return ListenerRule("", RuleType::WHOLE_WORD);
444 }
445 std::string domain = GetStringTypeAttribute(env, jsObj, NapiHiSysEventUtil::DOMAIN_ATTR);
446 HiLog::Debug(LABEL, "domain is %{public}s.", domain.c_str());
447 std::string name = GetStringTypeAttribute(env, jsObj, NapiHiSysEventUtil::NAME_ATTR);
448 HiLog::Debug(LABEL, "name is %{public}s.", name.c_str());
449 int32_t ruleType = GetInt32TypeAttribute(env, jsObj, RULE_TYPE_ATTR, RuleType::WHOLE_WORD);
450 HiLog::Debug(LABEL, "ruleType is %{public}d.", ruleType);
451 std::string tag = GetTagAttribute(env, jsObj);
452 HiLog::Debug(LABEL, "tag is %{public}s.", tag.c_str());
453 return ListenerRule(domain, name, tag, RuleType(ruleType));
454 }
455
IsQueryRuleValid(const napi_env env,const QueryRule & rule)456 bool IsQueryRuleValid(const napi_env env, const QueryRule& rule)
457 {
458 auto domain = rule.GetDomain();
459 if (!StringFilter::GetInstance().IsValidName(domain, MAX_DOMAIN_LENGTH)) {
460 NapiHiSysEventUtil::ThrowErrorByRet(env, NapiInnerError::ERR_INVALID_DOMAIN_IN_QUERY_RULE);
461 return false;
462 }
463 auto names = rule.GetEventList();
464 if (std::any_of(names.begin(), names.end(), [] (auto& name) {
465 return !StringFilter::GetInstance().IsValidName(name, MAX_EVENT_NAME_LENGTH);
466 })) {
467 NapiHiSysEventUtil::ThrowErrorByRet(env, NapiInnerError::ERR_INVALID_EVENT_NAME_IN_QUERY_RULE);
468 return false;
469 }
470 return true;
471 }
472
ParseQueryRule(const napi_env env,napi_value & jsObj)473 QueryRule ParseQueryRule(const napi_env env, napi_value& jsObj)
474 {
475 std::vector<std::string> names;
476 if (!IsValueTypeValid(env, jsObj, napi_valuetype::napi_object)) {
477 return QueryRule("", names);
478 }
479 std::string domain = GetStringTypeAttribute(env, jsObj, NapiHiSysEventUtil::DOMAIN_ATTR);
480 HiLog::Debug(LABEL, "domain is %{public}s.", domain.c_str());
481 napi_value propertyValue = NapiHiSysEventUtil::GetPropertyByName(env, jsObj, NAMES_ATTR);
482 ParseStringArray(env, propertyValue, names);
483 propertyValue = NapiHiSysEventUtil::GetPropertyByName(env, jsObj, CONDITION_ATTR);
484 std::string condition = ParseStringValue(env, propertyValue);
485 HiLog::Debug(LABEL, "condition is %{public}s.", condition.c_str());
486 return QueryRule(domain, names, RuleType::WHOLE_WORD, 0, condition);
487 }
488
SetNamedProperty(const napi_env env,napi_value & object,const std::string & propertyName,napi_value & propertyValue)489 void SetNamedProperty(const napi_env env, napi_value& object, const std::string& propertyName,
490 napi_value& propertyValue)
491 {
492 napi_status status = napi_set_named_property(env, object, propertyName.c_str(), propertyValue);
493 if (status != napi_ok) {
494 HiLog::Error(LABEL, "set property %{public}s failed.", propertyName.c_str());
495 }
496 }
497
IsBaseInfoKey(const std::string & propertyName)498 bool IsBaseInfoKey(const std::string& propertyName)
499 {
500 return propertyName == DOMAIN__KEY || propertyName == NAME__KEY || propertyName == TYPE__KEY;
501 }
502
translateKeyToAttrName(const std::string & key)503 std::string translateKeyToAttrName(const std::string& key)
504 {
505 if (key == DOMAIN__KEY) {
506 return NapiHiSysEventUtil::DOMAIN_ATTR;
507 }
508 if (key == NAME__KEY) {
509 return NapiHiSysEventUtil::NAME_ATTR;
510 }
511 if (key == TYPE__KEY) {
512 return NapiHiSysEventUtil::EVENT_TYPE_ATTR;
513 }
514 return "";
515 }
516
AppendBaseInfo(const napi_env env,napi_value & sysEventInfo,const std::string & key,Json::Value & value)517 void AppendBaseInfo(const napi_env env, napi_value& sysEventInfo, const std::string& key, Json::Value& value)
518 {
519 if ((key == DOMAIN__KEY || key == NAME__KEY) && value.isString()) {
520 NapiHiSysEventUtil::AppendStringPropertyToJsObject(env, translateKeyToAttrName(key),
521 value.asString(), sysEventInfo);
522 }
523 if (key == TYPE__KEY && value.isInt()) {
524 NapiHiSysEventUtil::AppendInt32PropertyToJsObject(env, translateKeyToAttrName(key),
525 static_cast<int32_t>(value.asInt()), sysEventInfo);
526 }
527 }
528
CreateBoolValue(const napi_env env,bool value,napi_value & val)529 void CreateBoolValue(const napi_env env, bool value, napi_value& val)
530 {
531 napi_status status = napi_get_boolean(env, value, &val);
532 HiLog::Debug(LABEL, "create napi value of bool type, value is %{public}d.", value);
533 if (status != napi_ok) {
534 HiLog::Error(LABEL, "failed to get create napi value of bool type.");
535 }
536 }
537
CreateDoubleValue(const napi_env env,double value,napi_value & val)538 void CreateDoubleValue(const napi_env env, double value, napi_value& val)
539 {
540 napi_status status = napi_create_double(env, value, &val);
541 HiLog::Debug(LABEL, "create napi value of double type, value is %{public}f.", value);
542 if (status != napi_ok) {
543 HiLog::Error(LABEL, "failed to get create napi value of double type.");
544 }
545 }
546
CreateUint32Value(const napi_env env,uint32_t value,napi_value & val)547 void CreateUint32Value(const napi_env env, uint32_t value, napi_value& val)
548 {
549 napi_status status = napi_create_uint32(env, value, &val);
550 HiLog::Debug(LABEL, "create napi value of uint32 type, value is %{public}u.", value);
551 if (status != napi_ok) {
552 HiLog::Error(LABEL, "failed to get create napi value of uint32 type.");
553 }
554 }
555
CreateParamItemTypeValue(const napi_env env,Json::Value & jsonValue,napi_value & value)556 bool CreateParamItemTypeValue(const napi_env env, Json::Value& jsonValue, napi_value& value)
557 {
558 if (jsonValue.isBool()) {
559 CreateBoolValue(env, jsonValue.asBool(), value);
560 return true;
561 }
562 if (jsonValue.isInt()) {
563 NapiHiSysEventUtil::CreateInt32Value(env, static_cast<int32_t>(jsonValue.asInt()), value);
564 return true;
565 }
566 if (jsonValue.isUInt()) {
567 CreateUint32Value(env, static_cast<uint32_t>(jsonValue.asUInt()), value);
568 return true;
569 }
570 #ifdef JSON_HAS_INT64
571 if (jsonValue.isInt64() && jsonValue.type() != Json::ValueType::uintValue) {
572 NapiHiSysEventUtil::CreateInt64Value(env, jsonValue.asInt64(), value);
573 return true;
574 }
575 if (jsonValue.isUInt64() && jsonValue.type() != Json::ValueType::intValue) {
576 NapiHiSysEventUtil::CreateUInt64Value(env, jsonValue.asUInt64(), value);
577 return true;
578 }
579 #endif
580 if (jsonValue.isDouble()) {
581 CreateDoubleValue(env, jsonValue.asDouble(), value);
582 return true;
583 }
584 if (jsonValue.isString()) {
585 NapiHiSysEventUtil::CreateStringValue(env, jsonValue.asString(), value);
586 return true;
587 }
588 return false;
589 }
590
AppendArrayParams(const napi_env env,napi_value & params,const std::string & key,Json::Value & value)591 void AppendArrayParams(const napi_env env, napi_value& params, const std::string& key, Json::Value& value)
592 {
593 size_t len = value.size();
594 napi_value array = nullptr;
595 napi_create_array_with_length(env, len, &array);
596 for (size_t i = 0; i < len; i++) {
597 napi_value item;
598 if (!CreateParamItemTypeValue(env, value[static_cast<int>(i)], item)) {
599 continue;
600 }
601 napi_set_element(env, array, i, item);
602 }
603 SetNamedProperty(env, params, key, array);
604 }
605
AppendParamsInfo(const napi_env env,napi_value & params,const std::string & key,Json::Value & jsonValue)606 void AppendParamsInfo(const napi_env env, napi_value& params, const std::string& key, Json::Value& jsonValue)
607 {
608 if (jsonValue.isArray()) {
609 AppendArrayParams(env, params, key, jsonValue);
610 return;
611 }
612 napi_value property = nullptr;
613 if (!CreateParamItemTypeValue(env, jsonValue, property)) {
614 return;
615 }
616 SetNamedProperty(env, params, key, property);
617 }
618 }
619
GetPropertyByName(const napi_env env,const napi_value & object,const std::string & propertyName)620 napi_value NapiHiSysEventUtil::GetPropertyByName(const napi_env env, const napi_value& object,
621 const std::string& propertyName)
622 {
623 napi_value result = nullptr;
624 napi_status status = napi_get_named_property(env, object, propertyName.c_str(), &result);
625 if (status != napi_ok) {
626 HiLog::Debug(LABEL, "failed to parse property named %{public}s from JS object.", propertyName.c_str());
627 }
628 return result;
629 }
630
ParseHiSysEventInfo(const napi_env env,napi_value * param,size_t paramNum,HiSysEventInfo & info)631 void NapiHiSysEventUtil::ParseHiSysEventInfo(const napi_env env, napi_value* param,
632 size_t paramNum, HiSysEventInfo& info)
633 {
634 if (paramNum <= SYS_EVENT_INFO_PARAM_INDEX) {
635 return;
636 }
637 if (!IsValueTypeValid(env, param[SYS_EVENT_INFO_PARAM_INDEX], napi_valuetype::napi_object)) {
638 NapiHiSysEventUtil::ThrowParamTypeError(env, "info", "object");
639 return;
640 }
641 info.domain = GetStringTypeAttribute(env, param[SYS_EVENT_INFO_PARAM_INDEX], NapiHiSysEventUtil::DOMAIN_ATTR);
642 HiLog::Debug(LABEL, "domain is %{public}s.", info.domain.c_str());
643 info.name = GetStringTypeAttribute(env, param[SYS_EVENT_INFO_PARAM_INDEX], NapiHiSysEventUtil::NAME_ATTR);
644 HiLog::Debug(LABEL, "name is %{public}s.", info.name.c_str());
645 info.eventType = HiSysEvent::EventType(GetInt32TypeAttribute(env,
646 param[SYS_EVENT_INFO_PARAM_INDEX], EVENT_TYPE_ATTR, HiSysEvent::EventType::FAULT));
647 HiLog::Debug(LABEL, "eventType is %{public}d.", info.eventType);
648 GetObjectTypeAttribute(env, param[SYS_EVENT_INFO_PARAM_INDEX], PARAMS_ATTR, info);
649 }
650
HasStrParamLenOverLimit(HiSysEventInfo & info)651 bool NapiHiSysEventUtil::HasStrParamLenOverLimit(HiSysEventInfo& info)
652 {
653 return any_of(info.stringParams.begin(), info.stringParams.end(), [] (auto& item) {
654 return item.second.size() > JS_STR_PARM_LEN_LIMIT;
655 }) || any_of(info.stringArrayParams.begin(), info.stringArrayParams.end(), [] (auto& item) {
656 auto allStr = item.second;
657 return any_of(allStr.begin(), allStr.end(), [] (auto& item) {
658 return item.size() > JS_STR_PARM_LEN_LIMIT;
659 });
660 });
661 }
662
CreateHiSysEventInfoJsObject(const napi_env env,const std::string & jsonStr,napi_value & sysEventInfo)663 void NapiHiSysEventUtil::CreateHiSysEventInfoJsObject(const napi_env env, const std::string& jsonStr,
664 napi_value& sysEventInfo)
665 {
666 Json::Value eventJson;
667 #ifdef JSONCPP_VERSION_STRING
668 Json::CharReaderBuilder jsonRBuilder;
669 Json::CharReaderBuilder::strictMode(&jsonRBuilder.settings_);
670 std::unique_ptr<Json::CharReader> const reader(jsonRBuilder.newCharReader());
671 JSONCPP_STRING errs;
672 if (!reader->parse(jsonStr.data(), jsonStr.data() + jsonStr.size(), &eventJson, &errs)) {
673 #else
674 Json::Reader reader(Json::Features::strictMode());
675 if (!reader.parse(jsonStr, eventJson)) {
676 #endif
677 HiLog::Error(LABEL, "parse event detail info failed, please check the style of json infomation: %{public}s",
678 jsonStr.c_str());
679 return;
680 }
681 napi_create_object(env, &sysEventInfo);
682 napi_value params = nullptr;
683 napi_create_object(env, ¶ms);
684 auto eventNameList = eventJson.getMemberNames();
685 for (auto it = eventNameList.cbegin(); it != eventNameList.cend(); it++) {
686 auto propertyName = *it;
687 if (IsBaseInfoKey(propertyName)) {
688 AppendBaseInfo(env, sysEventInfo, propertyName, eventJson[propertyName]);
689 } else {
690 AppendParamsInfo(env, params, propertyName, eventJson[propertyName]);
691 }
692 }
693 SetNamedProperty(env, sysEventInfo, PARAMS_ATTR, params);
694 }
695
696 void NapiHiSysEventUtil::CreateJsSysEventInfoArray(const napi_env env, const std::vector<std::string>& originValues,
697 napi_value& array)
698 {
699 auto len = originValues.size();
700 for (size_t i = 0; i < len; i++) {
701 napi_value item;
702 CreateHiSysEventInfoJsObject(env, originValues[i], item);
703 napi_status status = napi_set_element(env, array, i, item);
704 if (status != napi_ok) {
705 HiLog::Error(LABEL, "napi_set_element failed");
706 }
707 }
708 }
709
710 void NapiHiSysEventUtil::AppendStringPropertyToJsObject(const napi_env env, const std::string& key,
711 const std::string& value, napi_value& jsObj)
712 {
713 napi_value property = nullptr;
714 NapiHiSysEventUtil::CreateStringValue(env, value, property);
715 SetNamedProperty(env, jsObj, key, property);
716 }
717
718 void NapiHiSysEventUtil::AppendInt32PropertyToJsObject(const napi_env env, const std::string& key,
719 const int32_t& value, napi_value& jsObj)
720 {
721 napi_value property = nullptr;
722 NapiHiSysEventUtil::CreateInt32Value(env, value, property);
723 SetNamedProperty(env, jsObj, key, property);
724 }
725
726 int32_t NapiHiSysEventUtil::ParseListenerRules(const napi_env env, napi_value& array,
727 std::vector<ListenerRule>& listenerRules)
728 {
729 if (!CheckValueIsArray(env, array)) {
730 ThrowParamTypeError(env, "rules", "array");
731 return ERR_LISTENER_RULES_TYPE_NOT_ARRAY;
732 }
733 uint32_t len = 0;
734 napi_status status = napi_get_array_length(env, array, &len);
735 if (status != napi_ok) {
736 return ERR_NAPI_PARSED_FAILED;
737 }
738 napi_value firstItem;
739 status = napi_get_element(env, array, 0, &firstItem);
740 if (status != napi_ok) {
741 return ERR_NAPI_PARSED_FAILED;
742 }
743 napi_valuetype type;
744 status = napi_typeof(env, firstItem, &type);
745 if (status != napi_ok) {
746 return ERR_NAPI_PARSED_FAILED;
747 }
748 napi_value element;
749 for (uint32_t i = 0; i < len; i++) {
750 status = napi_get_element(env, array, i, &element);
751 if (status != napi_ok) {
752 return ERR_NAPI_PARSED_FAILED;
753 }
754 if (IsValueTypeValid(env, element, napi_valuetype::napi_object)) {
755 listenerRules.emplace_back(ParseListenerRule(env, element));
756 }
757 }
758 return NAPI_SUCCESS;
759 }
760
761 int32_t NapiHiSysEventUtil::ParseQueryRules(const napi_env env, napi_value& array, std::vector<QueryRule>& queryRules)
762 {
763 if (!CheckValueIsArray(env, array)) {
764 ThrowParamTypeError(env, "rules", "array");
765 return ERR_QUERY_RULES_TYPE_NOT_ARRAY;
766 }
767 uint32_t len = 0;
768 napi_status status = napi_get_array_length(env, array, &len);
769 if (status != napi_ok) {
770 return ERR_NAPI_PARSED_FAILED;
771 }
772 napi_value firstItem;
773 status = napi_get_element(env, array, 0, &firstItem);
774 if (status != napi_ok) {
775 return ERR_NAPI_PARSED_FAILED;
776 }
777 napi_valuetype type;
778 status = napi_typeof(env, firstItem, &type);
779 if (status != napi_ok) {
780 return ERR_NAPI_PARSED_FAILED;
781 }
782 napi_value element;
783 for (uint32_t i = 0; i < len; i++) {
784 status = napi_get_element(env, array, i, &element);
785 if (status != napi_ok) {
786 return ERR_NAPI_PARSED_FAILED;
787 }
788 if (IsValueTypeValid(env, element, napi_valuetype::napi_object)) {
789 auto queryRule = ParseQueryRule(env, element);
790 if (IsQueryRuleValid(env, queryRule)) {
791 queryRules.emplace_back(queryRule);
792 }
793 }
794 }
795 return NAPI_SUCCESS;
796 }
797
798 int32_t NapiHiSysEventUtil::ParseQueryArg(const napi_env env, napi_value& jsObj, QueryArg& queryArg)
799 {
800 if (!IsValueTypeValid(env, jsObj, napi_valuetype::napi_object)) {
801 ThrowParamTypeError(env, "queryArg", "object");
802 return ERR_QUERY_ARG_TYPE_INVALID;
803 }
804 queryArg.beginTime = GetLonglongTypeAttribute(env, jsObj, BEGIN_TIME_ATTR, DEFAULT_TIME_STAMP);
805 HiLog::Debug(LABEL, "queryArg.beginTime is %{public}lld.", queryArg.beginTime);
806 queryArg.endTime = GetLonglongTypeAttribute(env, jsObj, END_TIME_ATTR, DEFAULT_TIME_STAMP);
807 HiLog::Debug(LABEL, "queryArg.endTime is %{public}lld.", queryArg.endTime);
808 queryArg.maxEvents = GetInt32TypeAttribute(env, jsObj, MAX_EVENTS_ATTR, DEFAULT_MAX_EVENTS);
809 HiLog::Debug(LABEL, "queryArg.maxEvents is %{public}d.", queryArg.maxEvents);
810 queryArg.fromSeq = GetLonglongTypeAttribute(env, jsObj, BEGIN_SEQ_ATTR, DEFAULT_SEQ);
811 HiLog::Debug(LABEL, "queryArg.fromSeq is %{public}lld.", queryArg.fromSeq);
812 queryArg.toSeq = GetLonglongTypeAttribute(env, jsObj, END_SEQ_ATTR, DEFAULT_SEQ);
813 HiLog::Debug(LABEL, "queryArg.endSeq is %{public}lld.", queryArg.toSeq);
814 return NAPI_SUCCESS;
815 }
816
817 void NapiHiSysEventUtil::CreateNull(const napi_env env, napi_value& ret)
818 {
819 napi_status status = napi_get_null(env, &ret);
820 if (status != napi_ok) {
821 HiLog::Error(LABEL, "failed to create napi value of null.");
822 }
823 }
824
825 void NapiHiSysEventUtil::CreateInt32Value(const napi_env env, int32_t value, napi_value& ret)
826 {
827 napi_status status = napi_create_int32(env, value, &ret);
828 HiLog::Debug(LABEL, "create napi value of int32 type, value is %{public}d.", value);
829 if (status != napi_ok) {
830 HiLog::Error(LABEL, "failed to create napi value of int32 type.");
831 }
832 }
833
834 void NapiHiSysEventUtil::CreateInt64Value(const napi_env env, int64_t value, napi_value& ret)
835 {
836 napi_status status = napi_create_bigint_int64(env, value, &ret);
837 HiLog::Debug(LABEL, "create napi value of int64_t type, value is %{public}" PRId64 ".", value);
838 if (status != napi_ok) {
839 HiLog::Error(LABEL, "failed to create napi value of int64_t type.");
840 }
841 }
842
843 void NapiHiSysEventUtil::CreateUInt64Value(const napi_env env, uint64_t value, napi_value& ret)
844 {
845 napi_status status = napi_create_bigint_uint64(env, value, &ret);
846 HiLog::Debug(LABEL, "create napi value of uint64_t type, value is %{public}" PRIu64 ".", value);
847 if (status != napi_ok) {
848 HiLog::Error(LABEL, "failed to create napi value of uint64_t type.");
849 }
850 }
851
852 void NapiHiSysEventUtil::CreateStringValue(const napi_env env, std::string value, napi_value& ret)
853 {
854 napi_status status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &ret);
855 HiLog::Debug(LABEL, "create napi value of string type, value is %{public}s.", value.c_str());
856 if (status != napi_ok) {
857 HiLog::Error(LABEL, "failed to create napi value of string type.");
858 }
859 }
860
861 void NapiHiSysEventUtil::ThrowParamMandatoryError(napi_env env, const std::string paramName)
862 {
863 ThrowError(env, NapiError::ERR_PARAM_CHECK, "Parameter error. The " + paramName + " parameter is mandatory.");
864 }
865
866 void NapiHiSysEventUtil::ThrowParamTypeError(napi_env env, const std::string paramName, std::string paramType)
867 {
868 ThrowError(env, NapiError::ERR_PARAM_CHECK, "Parameter error. The type of " + paramName + " must be "
869 + paramType + ".");
870 }
871
872 void NapiHiSysEventUtil::ThrowSystemAppPermissionError(napi_env env)
873 {
874 ThrowError(env, NapiError::ERR_NON_SYS_APP_PERMISSION, "Permission denied. "
875 "System api can be invoked only by system applications.");
876 }
877
878 napi_value NapiHiSysEventUtil::CreateError(napi_env env, int32_t code, const std::string& msg)
879 {
880 napi_value err = nullptr;
881 napi_value napiCode = nullptr;
882 NapiHiSysEventUtil::CreateStringValue(env, std::to_string(code), napiCode);
883 napi_value napiStr = nullptr;
884 NapiHiSysEventUtil::CreateStringValue(env, msg, napiStr);
885 if (napi_create_error(env, napiCode, napiStr, &err) != napi_ok) {
886 HiLog::Error(LABEL, "failed to create napi error");
887 }
888 return err;
889 }
890
891 void NapiHiSysEventUtil::ThrowError(napi_env env, const int32_t code, const std::string& msg)
892 {
893 if (napi_throw_error(env, std::to_string(code).c_str(), msg.c_str()) != napi_ok) {
894 HiLog::Error(LABEL, "failed to throw err, code=%{public}d, msg=%{public}s.", code, msg.c_str());
895 }
896 }
897
898 std::pair<int32_t, std::string> NapiHiSysEventUtil::GetErrorDetailByRet(napi_env env, const int32_t retCode)
899 {
900 HiLog::Info(LABEL, "origin result code is %{public}d.", retCode);
901 const std::unordered_map<int32_t, std::pair<int32_t, std::string>> errMap = {
902 // common
903 {ERR_NO_PERMISSION, {NapiError::ERR_PERMISSION_CHECK,
904 "Permission denied. An attempt was made to read sysevent forbidden"
905 " by permission: ohos.permission.READ_DFX_SYSEVENT."}},
906 // write refer
907 {ERR_DOMAIN_NAME_INVALID, {NapiError::ERR_INVALID_DOMAIN, "Domain is invalid"}},
908 {ERR_EVENT_NAME_INVALID, {NapiError::ERR_INVALID_EVENT_NAME, "Event name is invalid"}},
909 {ERR_DOES_NOT_INIT, {NapiError::ERR_ENV_ABNORMAL, "Environment is abnormal"}},
910 {ERR_OVER_SIZE, {NapiError::ERR_CONTENT_OVER_LIMIT, "Size of event content is over limit"}},
911 {ERR_KEY_NAME_INVALID, {NapiError::ERR_INVALID_PARAM_NAME, "Name of param is invalid"}},
912 {ERR_VALUE_LENGTH_TOO_LONG, {NapiError::ERR_STR_LEN_OVER_LIMIT,
913 "Size of string type param is over limit"}},
914 {ERR_KEY_NUMBER_TOO_MUCH, {NapiError::ERR_PARAM_COUNT_OVER_LIMIT, "Count of params is over limit"}},
915 {ERR_ARRAY_TOO_MUCH, {NapiError::ERR_ARRAY_SIZE_OVER_LIMIT, "Size of array type param is over limit"}},
916 // ipc common
917 {ERR_SYS_EVENT_SERVICE_NOT_FOUND, {NapiError::ERR_ENV_ABNORMAL, "Environment is abnormal"}},
918 {ERR_CAN_NOT_WRITE_DESCRIPTOR, {NapiError::ERR_ENV_ABNORMAL, "Environment is abnormal"}},
919 {ERR_CAN_NOT_WRITE_PARCEL, {NapiError::ERR_ENV_ABNORMAL, "Environment is abnormal"}},
920 {ERR_CAN_NOT_WRITE_REMOTE_OBJECT, {NapiError::ERR_ENV_ABNORMAL, "Environment is abnormal"}},
921 {ERR_CAN_NOT_SEND_REQ, {NapiError::ERR_ENV_ABNORMAL, "Environment is abnormal"}},
922 {ERR_CAN_NOT_READ_PARCEL, {NapiError::ERR_ENV_ABNORMAL, "Environment is abnormal"}},
923 {ERR_SEND_FAIL, {NapiError::ERR_ENV_ABNORMAL, "Environment is abnormal"}},
924 // add watcher
925 {ERR_TOO_MANY_WATCHERS, {NapiError::ERR_WATCHER_COUNT_OVER_LIMIT, "Count of watchers is over limit"}},
926 {ERR_TOO_MANY_WATCH_RULES, {NapiError::ERR_WATCH_RULE_COUNT_OVER_LIMIT,
927 "Count of watch rules is over limit"}},
928 // remove watcher
929 {ERR_LISTENER_NOT_EXIST, {NapiError::ERR_WATCHER_NOT_EXIST, "Watcher is not exist"}},
930 {ERR_NAPI_LISTENER_NOT_FOUND, {NapiError::ERR_WATCHER_NOT_EXIST, "Watcher is not exist"}},
931 // query refer
932 {ERR_TOO_MANY_QUERY_RULES, {NapiError::ERR_QUERY_RULE_COUNT_OVER_LIMIT,
933 "Count of query rules is over limit"}},
934 {ERR_TOO_MANY_CONCURRENT_QUERIES, {NapiError::ERR_CONCURRENT_QUERY_COUNT_OVER_LIMIT,
935 "cCount of concurrent queries is over limit"}},
936 {ERR_QUERY_TOO_FREQUENTLY, {NapiError::ERR_QUERY_TOO_FREQUENTLY, "Frequency of event query is over limit"}},
937 {NapiInnerError::ERR_INVALID_DOMAIN_IN_QUERY_RULE,
938 {NapiError::ERR_INVALID_QUERY_RULE, "Query rule is invalid"}},
939 {ERR_QUERY_RULE_INVALID, {NapiError::ERR_INVALID_QUERY_RULE, "Query rule is invalid"}},
940 {NapiInnerError::ERR_INVALID_EVENT_NAME_IN_QUERY_RULE,
941 {NapiError::ERR_INVALID_QUERY_RULE, "Query rule is invalid"}},
942 // export
943 {ERR_EXPORT_FREQUENCY_OVER_LIMIT, {NapiError::ERR_QUERY_TOO_FREQUENTLY, "Export frequency is over limit."}},
944 // add subscriber
945 {ERR_TOO_MANY_EVENTS, {NapiError::ERR_QUERY_RULE_COUNT_OVER_LIMIT, "Count of query rules is over limit"}},
946 // remove subscriber
947 {ERR_REMOVE_SUBSCRIBE, {NapiError::ERR_REMOVE_SUBSCRIBE, "unsubscribe failed"}},
948 };
949 return errMap.find(retCode) == errMap.end() ?
950 std::make_pair(NapiError::ERR_ENV_ABNORMAL, "environment is abnormal") : errMap.at(retCode);
951 }
952
953 napi_value NapiHiSysEventUtil::CreateErrorByRet(napi_env env, const int32_t retCode)
954 {
955 auto detail = GetErrorDetailByRet(env, retCode);
956 return CreateError(env, detail.first, detail.second);
957 }
958
959 void NapiHiSysEventUtil::ThrowErrorByRet(napi_env env, const int32_t retCode)
960 {
961 auto detail = GetErrorDetailByRet(env, retCode);
962 ThrowError(env, detail.first, detail.second);
963 }
964
965 bool NapiHiSysEventUtil::IsSystemAppCall()
966 {
967 uint64_t tokenId = IPCSkeleton::GetCallingFullTokenID();
968 return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(tokenId);
969 }
970 } // namespace HiviewDFX
971 } // namespace OHOS