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 "napi_config_builder.h"
16
17 #include "hiappevent_base.h"
18 #include "hilog/log.h"
19 #include "napi_error.h"
20 #include "napi_util.h"
21 #include "resource_overlimit_mgr.h"
22
23 #undef LOG_DOMAIN
24 #define LOG_DOMAIN 0xD002D07
25
26 #undef LOG_TAG
27 #define LOG_TAG "NapiConfigBuilder"
28
29 namespace OHOS {
30 namespace HiviewDFX {
31 namespace {
32 constexpr size_t CONFIG_PARAM_NUM = 2;
33 constexpr size_t INDEX_OF_NAME_CONFIG = 0;
34 constexpr size_t INDEX_OF_VALUE_CONFIG = 1;
35 constexpr const char* const APP_CRASH = "APP_CRASH";
36 constexpr const char* const MAIN_THREAD_JANK = "MAIN_THREAD_JANK";
37 constexpr int CRASH_LOG_MAX_CAPACITY = 5 * 1024 * 1024; // 5M
38 struct crashConfig {
39 uint8_t type;
40 std::function<bool(const napi_env, const napi_value, const std::string&, uint32_t&)> func;
41 };
42
GetCrashConfigBoolValue(const napi_env env,const napi_value configs,const std::string & key,uint32_t & out)43 bool GetCrashConfigBoolValue(const napi_env env, const napi_value configs, const std::string& key, uint32_t& out)
44 {
45 napi_value value = NapiUtil::GetProperty(env, configs, key);
46 if (!NapiUtil::IsBoolean(env, value)) {
47 HILOG_ERROR(LOG_CORE, "Set crash config item(%{public}s) failed, the value should be bool type.", key.c_str());
48 return false;
49 }
50
51 out = NapiUtil::GetBoolean(env, value) == true ? 1 : 0;
52 return true;
53 }
54
GetCrashConfigUIntValue(const napi_env env,const napi_value configs,const std::string & key,uint32_t & out)55 bool GetCrashConfigUIntValue(const napi_env env, const napi_value configs, const std::string& key, uint32_t& out)
56 {
57 napi_value value = NapiUtil::GetProperty(env, configs, key);
58 if (!NapiUtil::IsNumber(env, value)) {
59 HILOG_ERROR(LOG_CORE, "Set crash config item(%{public}s) failed, the value should be a number.", key.c_str());
60 return false;
61 }
62
63 int64_t intValue = NapiUtil::GetInt64(env, value);
64 if (intValue < 0 || intValue > CRASH_LOG_MAX_CAPACITY) {
65 HILOG_ERROR(LOG_CORE, "Set crash config item(%{public}s) failed, the value is over range.", key.c_str());
66 return false;
67 }
68
69 out = static_cast<uint32_t>(intValue);
70 return true;
71 }
72 }
73
BuildEventConfig(const napi_env env,const napi_value params[],size_t len)74 std::unique_ptr<EventConfigPack> NapiConfigBuilder::BuildEventConfig(const napi_env env, const napi_value params[],
75 size_t len)
76 {
77 if (len < CONFIG_PARAM_NUM) {
78 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("setEventParam"));
79 return nullptr;
80 }
81 if (!NapiUtil::IsString(env, params[INDEX_OF_NAME_CONFIG])) {
82 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("name", "string"));
83 return nullptr;
84 }
85 if (!NapiUtil::IsObject(env, params[INDEX_OF_VALUE_CONFIG])) {
86 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("value", "object"));
87 return nullptr;
88 }
89
90 eventConfigPack_->eventName = NapiUtil::GetString(env, params[INDEX_OF_NAME_CONFIG]);
91 std::unordered_set<std::string> whiteList = { MAIN_THREAD_JANK, RESOURCE_OVERLIMIT };
92 if (eventConfigPack_->eventName == APP_CRASH) {
93 GetAppCrashConfig(env, params[INDEX_OF_VALUE_CONFIG]);
94 } else if (whiteList.count(eventConfigPack_->eventName) != 0) {
95 GetCommonConfig(env, params[INDEX_OF_VALUE_CONFIG]);
96 } else {
97 HILOG_ERROR(LOG_CORE, "Failed to set event config, name is invalid. name=%{public}s",
98 eventConfigPack_->eventName.c_str());
99 }
100 return std::move(eventConfigPack_);
101 }
102
GetAppCrashConfig(const napi_env env,const napi_value params)103 void NapiConfigBuilder::GetAppCrashConfig(const napi_env env, const napi_value params)
104 {
105 std::vector<std::string> configKeys;
106 NapiUtil::GetPropertyNames(env, params, configKeys);
107 if (configKeys.empty()) {
108 HILOG_INFO(LOG_CORE, "Set config failed, the config is empty.");
109 return;
110 }
111
112 std::map<std::string, crashConfig> crashConfigs = {
113 {"extend_pc_lr_printing", {.type = 0, .func = GetCrashConfigBoolValue}},
114 {"log_file_cutoff_sz_bytes", {.type = 1, .func = GetCrashConfigUIntValue}},
115 {"simplify_vma_printing", {.type = 2, .func = GetCrashConfigBoolValue}}
116 };
117
118 uint32_t configValue = 0;
119 for (const auto& configKey : configKeys) {
120 auto it = crashConfigs.find(configKey);
121 if (it == crashConfigs.end()) {
122 HILOG_WARN(LOG_CORE, "Set crash config item(%{public}s) failed, it is not supported.", configKey.c_str());
123 continue;
124 }
125
126 if ((it->second.func)(env, params, configKey, configValue)) {
127 eventConfigPack_->configUintMap[it->second.type] = configValue;
128 eventConfigPack_->isValid = true;
129 HILOG_INFO(LOG_CORE, "Set crash config item(%{public}s) success. Value=%{public}d", configKey.c_str(),
130 configValue);
131 }
132 }
133 }
134
GetCommonConfig(const napi_env env,const napi_value params)135 void NapiConfigBuilder::GetCommonConfig(const napi_env env, const napi_value params)
136 {
137 std::vector<std::string> configKeys;
138 NapiUtil::GetPropertyNames(env, params, configKeys);
139 if (configKeys.empty()) {
140 HILOG_INFO(LOG_CORE, "Set MainThreadJank config failed, the config is empty.");
141 return;
142 }
143
144 eventConfigPack_->isValid = true;
145 std::map<std::string, std::string> configMap;
146 for (const auto& configkey : configKeys) {
147 napi_value configValue = NapiUtil::GetProperty(env, params, configkey);
148 if (!NapiUtil::IsString(env, configValue)) {
149 HILOG_ERROR(LOG_CORE, "Failed to get config Value, the value type of the item(%{public}s) is not string.",
150 configkey.c_str());
151 eventConfigPack_->isValid = false;
152 return;
153 }
154 configMap[configkey] = NapiUtil::GetString(env, configValue);
155 }
156 eventConfigPack_->configStringMap = std::move(configMap);
157 }
158 } // namespace HiviewDFX
159 } // namespace OHOS