1 /*
2 * Copyright (c) 2021-2022 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_builder.h"
16
17 #include "hiappevent_base.h"
18 #include "hiappevent_verify.h"
19 #include "hilog/log.h"
20 #include "napi_error.h"
21 #include "napi_util.h"
22
23 namespace OHOS {
24 namespace HiviewDFX {
25 namespace {
26 const HiLogLabel LABEL = { LOG_CORE, HIAPPEVENT_DOMAIN, "Napi_HiAppEvent_Builder" };
27 const std::string DOMAIN_PROPERTY = "domain";
28 const std::string NAME_PROPERTY = "name";
29 const std::string TYPE_PROPERTY = "eventType";
30 const std::string PARAM_PROPERTY = "params";
31 constexpr size_t MAX_STRING_LEN = 8 * 1024 + 2; // 2 for '\0' and extra symbol
32 constexpr size_t MAX_LENGTH_OF_PARAM_NAME = 16;
33 const std::string PARAM_VALUE_TYPE = "boolean|number|string|array[boolean|number|string]";
34 }
35 using namespace OHOS::HiviewDFX::ErrorCode;
36
IsValidEventDomain(const napi_env env,const napi_value domain)37 bool NapiHiAppEventBuilder::IsValidEventDomain(const napi_env env, const napi_value domain)
38 {
39 if (domain == nullptr) {
40 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("domain"), isV9_);
41 return false;
42 }
43 if (!NapiUtil::IsString(env, domain)) {
44 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("domain", "string"), isV9_);
45 return false;
46 }
47 return true;
48 }
49
IsValidEventName(const napi_env env,const napi_value name)50 bool NapiHiAppEventBuilder::IsValidEventName(const napi_env env, const napi_value name)
51 {
52 if (name == nullptr) {
53 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("name"), isV9_);
54 return false;
55 }
56 if (!NapiUtil::IsString(env, name)) {
57 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("name", "string"), isV9_);
58 return false;
59 }
60 return true;
61 }
62
IsValidEventType(const napi_env env,const napi_value type)63 bool NapiHiAppEventBuilder::IsValidEventType(const napi_env env, const napi_value type)
64 {
65 if (type == nullptr) {
66 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("eventType"), isV9_);
67 return false;
68 }
69 if (!NapiUtil::IsNumber(env, type) || !OHOS::HiviewDFX::IsValidEventType(NapiUtil::GetInt32(env, type))) {
70 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("eventType", "EventType"), isV9_);
71 return false;
72 }
73 return true;
74 }
75
IsValidEventParam(const napi_env env,const napi_value param)76 bool NapiHiAppEventBuilder::IsValidEventParam(const napi_env env, const napi_value param)
77 {
78 if (param == nullptr) {
79 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("params"), isV9_);
80 return false;
81 }
82 if (!NapiUtil::IsObject(env, param)) {
83 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("params", "object"), isV9_);
84 return false;
85 }
86 return true;
87 }
88
IsValidEventInfo(const napi_env env,const napi_value eventInfo)89 bool NapiHiAppEventBuilder::IsValidEventInfo(const napi_env env, const napi_value eventInfo)
90 {
91 if (!NapiUtil::IsObject(env, eventInfo)) {
92 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("info", "AppEventInfo"), isV9_);
93 return false;
94 }
95 return IsValidEventDomain(env, NapiUtil::GetProperty(env, eventInfo, DOMAIN_PROPERTY))
96 && IsValidEventName(env, NapiUtil::GetProperty(env, eventInfo, NAME_PROPERTY))
97 && IsValidEventType(env, NapiUtil::GetProperty(env, eventInfo, TYPE_PROPERTY))
98 && IsValidEventParam(env, NapiUtil::GetProperty(env, eventInfo, PARAM_PROPERTY));
99 }
100
IsOldWriteParams(const napi_env env,const napi_value params[],size_t len)101 bool NapiHiAppEventBuilder::IsOldWriteParams(const napi_env env, const napi_value params[], size_t len)
102 {
103 return IsValidEventName(env, params[0]) // 0 means the index of event name
104 && IsValidEventType(env, params[1]) // 1 means the index of event type
105 && IsValidEventParam(env, params[2]); // 2 means the index of event param
106 }
107
IsNewWriteParams(const napi_env env,const napi_value params[],size_t len)108 bool NapiHiAppEventBuilder::IsNewWriteParams(const napi_env env, const napi_value params[], size_t len)
109 {
110 return IsValidEventInfo(env, params[0]);
111 }
112
AddArrayParam2EventPack(napi_env env,const std::string & key,const napi_value arr)113 void NapiHiAppEventBuilder::AddArrayParam2EventPack(napi_env env, const std::string &key,
114 const napi_value arr)
115 {
116 napi_valuetype type = NapiUtil::GetArrayType(env, arr);
117 switch (type) {
118 case napi_boolean: {
119 std::vector<bool> bools;
120 NapiUtil::GetBooleans(env, arr, bools);
121 appEventPack_->AddParam(key, bools);
122 break;
123 }
124 case napi_number: {
125 std::vector<double> doubles;
126 NapiUtil::GetDoubles(env, arr, doubles);
127 appEventPack_->AddParam(key, doubles);
128 break;
129 }
130 case napi_string: {
131 std::vector<std::string> strs;
132 NapiUtil::GetStrings(env, arr, strs, MAX_STRING_LEN);
133 appEventPack_->AddParam(key, strs);
134 break;
135 }
136 case napi_null: {
137 appEventPack_->AddParam(key);
138 break;
139 }
140 default: {
141 HiLog::Error(LABEL, "array param value type is invalid");
142 result_ = ERROR_INVALID_LIST_PARAM_TYPE;
143 std::string errMsg = NapiUtil::CreateErrMsg("param value", PARAM_VALUE_TYPE);
144 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, errMsg, isV9_);
145 break;
146 }
147 }
148 }
149
AddParam2EventPack(napi_env env,const std::string & key,const napi_value value)150 void NapiHiAppEventBuilder::AddParam2EventPack(napi_env env, const std::string &key,
151 const napi_value value)
152 {
153 napi_valuetype type = NapiUtil::GetType(env, value);
154 switch (type) {
155 case napi_boolean:
156 appEventPack_->AddParam(key, NapiUtil::GetBoolean(env, value));
157 break;
158 case napi_number:
159 appEventPack_->AddParam(key, NapiUtil::GetDouble(env, value));
160 break;
161 case napi_string:
162 appEventPack_->AddParam(key, NapiUtil::GetString(env, value, MAX_STRING_LEN));
163 break;
164 case napi_object:
165 if (NapiUtil::IsArray(env, value)) {
166 AddArrayParam2EventPack(env, key, value);
167 break;
168 }
169 [[fallthrough]];
170 default:
171 HiLog::Error(LABEL, "param value type is invalid");
172 result_ = ERROR_INVALID_PARAM_VALUE_TYPE;
173 std::string errMsg = NapiUtil::CreateErrMsg("param value", PARAM_VALUE_TYPE);
174 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, errMsg, isV9_);
175 break;
176 }
177 }
178
AddParams2EventPack(napi_env env,const napi_value paramObj)179 void NapiHiAppEventBuilder::AddParams2EventPack(napi_env env, const napi_value paramObj)
180 {
181 std::vector<std::string> keys;
182 NapiUtil::GetPropertyNames(env, paramObj, keys);
183 for (auto key : keys) {
184 if (key.length() > MAX_LENGTH_OF_PARAM_NAME) {
185 result_ = ERROR_INVALID_PARAM_NAME;
186 HiLog::Info(LABEL, "the length=%{public}zu of the param key is invalid", key.length());
187 continue;
188 }
189 napi_value value = NapiUtil::GetProperty(env, paramObj, key);
190 if (value == nullptr) {
191 result_ = ERROR_INVALID_PARAM_VALUE_TYPE;
192 std::string errMsg = NapiUtil::CreateErrMsg("param value", PARAM_VALUE_TYPE);
193 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, errMsg, isV9_);
194 continue;
195 }
196 AddParam2EventPack(env, key, value);
197 }
198 }
199
BuildEventPack(napi_env env,const napi_value params[])200 void NapiHiAppEventBuilder::BuildEventPack(napi_env env, const napi_value params[])
201 {
202 int index = 0;
203 std::string name = NapiUtil::GetString(env, params[index++]);
204 int32_t type = NapiUtil::GetInt32(env, params[index++]);
205 appEventPack_ = std::make_shared<AppEventPack>(name, type);
206 AddParams2EventPack(env, params[index]);
207 }
208
BuildEventPack(napi_env env,const napi_value eventInfo)209 void NapiHiAppEventBuilder::BuildEventPack(napi_env env, const napi_value eventInfo)
210 {
211 std::string domain = NapiUtil::GetString(env, NapiUtil::GetProperty(env, eventInfo, DOMAIN_PROPERTY));
212 std::string name = NapiUtil::GetString(env, NapiUtil::GetProperty(env, eventInfo, NAME_PROPERTY));
213 int32_t type = NapiUtil::GetInt32(env, NapiUtil::GetProperty(env, eventInfo, TYPE_PROPERTY));
214 appEventPack_ = std::make_shared<AppEventPack>(domain, name, type);
215 napi_value param = NapiUtil::GetProperty(env, eventInfo, PARAM_PROPERTY);
216 AddParams2EventPack(env, param);
217 }
218
BuildCallback(const napi_env env,const napi_value callback)219 void NapiHiAppEventBuilder::BuildCallback(const napi_env env, const napi_value callback)
220 {
221 if (NapiUtil::IsFunction(env, callback)) {
222 callback_ = NapiUtil::CreateReference(env, callback);
223 }
224 }
225
Build(const napi_env env,const napi_value params[],size_t len)226 std::shared_ptr<AppEventPack> NapiHiAppEventBuilder::Build(const napi_env env, const napi_value params[], size_t len)
227 {
228 if (len < 3) { // the min number of params for write is 3
229 result_ = ERROR_INVALID_PARAM_NUM_JS;
230 return nullptr;
231 }
232
233 // 1. build AppEventPack
234 if (IsOldWriteParams(env, params, len)) {
235 BuildEventPack(env, params);
236 } else {
237 result_ = ERROR_INVALID_PARAM_TYPE_JS;
238 }
239
240 // 2. build callback if any
241 BuildCallback(env, params[len - 1]); // (len - 1) means the last param
242 return appEventPack_;
243 }
244
BuildV9(const napi_env env,const napi_value params[],size_t len)245 std::shared_ptr<AppEventPack> NapiHiAppEventBuilder::BuildV9(const napi_env env, const napi_value params[], size_t len)
246 {
247 isV9_ = true;
248 if (len < 1) { // the min number of params for writeV9 is 1
249 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("info"), isV9_);
250 return nullptr;
251 }
252 if (!IsNewWriteParams(env, params, len)) {
253 return nullptr;
254 }
255 BuildEventPack(env, params[0]);
256 BuildCallback(env, params[len - 1]); // (len - 1) means the last param
257 return appEventPack_;
258 }
259
GetResult() const260 int NapiHiAppEventBuilder::GetResult() const
261 {
262 return result_;
263 }
264
GetCallback() const265 napi_ref NapiHiAppEventBuilder::GetCallback() const
266 {
267 return callback_;
268 }
269 } // namespace HiviewDFX
270 } // namespace OHOS
271