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 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, MAX_STRING_LEN);
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, MAX_STRING_LEN));
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 napi_value value = NapiUtil::GetProperty(env, paramObj, key);
184 if (value == nullptr) {
185 result_ = ERROR_INVALID_PARAM_VALUE_TYPE;
186 std::string errMsg = NapiUtil::CreateErrMsg("param value", PARAM_VALUE_TYPE);
187 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, errMsg, isV9_);
188 continue;
189 }
190 AddParam2EventPack(env, key, value);
191 }
192 }
193
BuildEventPack(napi_env env,const napi_value params[])194 void NapiHiAppEventBuilder::BuildEventPack(napi_env env, const napi_value params[])
195 {
196 int index = 0;
197 std::string name = NapiUtil::GetString(env, params[index++]);
198 int32_t type = NapiUtil::GetInt32(env, params[index++]);
199 appEventPack_ = std::make_shared<AppEventPack>(name, type);
200 AddParams2EventPack(env, params[index]);
201 }
202
BuildEventPack(napi_env env,const napi_value eventInfo)203 void NapiHiAppEventBuilder::BuildEventPack(napi_env env, const napi_value eventInfo)
204 {
205 std::string domain = NapiUtil::GetString(env, NapiUtil::GetProperty(env, eventInfo, DOMAIN_PROPERTY));
206 std::string name = NapiUtil::GetString(env, NapiUtil::GetProperty(env, eventInfo, NAME_PROPERTY));
207 int32_t type = NapiUtil::GetInt32(env, NapiUtil::GetProperty(env, eventInfo, TYPE_PROPERTY));
208 appEventPack_ = std::make_shared<AppEventPack>(domain, name, type);
209 napi_value param = NapiUtil::GetProperty(env, eventInfo, PARAM_PROPERTY);
210 AddParams2EventPack(env, param);
211 }
212
BuildCallback(const napi_env env,const napi_value callback)213 void NapiHiAppEventBuilder::BuildCallback(const napi_env env, const napi_value callback)
214 {
215 if (NapiUtil::IsFunction(env, callback)) {
216 callback_ = NapiUtil::CreateReference(env, callback);
217 }
218 }
219
Build(const napi_env env,const napi_value params[],size_t len)220 std::shared_ptr<AppEventPack> NapiHiAppEventBuilder::Build(const napi_env env, const napi_value params[], size_t len)
221 {
222 if (len < 3) { // the min number of params for write is 3
223 result_ = ERROR_INVALID_PARAM_NUM_JS;
224 return nullptr;
225 }
226
227 // 1. build AppEventPack
228 if (IsOldWriteParams(env, params, len)) {
229 BuildEventPack(env, params);
230 } else {
231 result_ = ERROR_INVALID_PARAM_TYPE_JS;
232 }
233
234 // 2. build callback if any
235 BuildCallback(env, params[len - 1]); // (len - 1) means the last param
236 return appEventPack_;
237 }
238
BuildV9(const napi_env env,const napi_value params[],size_t len)239 std::shared_ptr<AppEventPack> NapiHiAppEventBuilder::BuildV9(const napi_env env, const napi_value params[], size_t len)
240 {
241 isV9_ = true;
242 if (len < 1) { // the min number of params for writeV9 is 1
243 NapiUtil::ThrowError(env, NapiError::ERR_PARAM, NapiUtil::CreateErrMsg("info"), isV9_);
244 return nullptr;
245 }
246 if (!IsNewWriteParams(env, params, len)) {
247 return nullptr;
248 }
249 BuildEventPack(env, params[0]);
250 BuildCallback(env, params[len - 1]); // (len - 1) means the last param
251 return appEventPack_;
252 }
253
GetResult() const254 int NapiHiAppEventBuilder::GetResult() const
255 {
256 return result_;
257 }
258
GetCallback() const259 napi_ref NapiHiAppEventBuilder::GetCallback() const
260 {
261 return callback_;
262 }
263 } // namespace HiviewDFX
264 } // namespace OHOS
265