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