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
16 #include "napi_utils.h"
17
18 #include <cstring>
19 #include <initializer_list>
20 #include <memory>
21 #include "log.h"
22 #include "securec.h"
23 #include "download_manager.h"
24
25 namespace OHOS::Request::Download::NapiUtils {
26 static constexpr const int MAX_STRING_LENGTH = 65536;
27
GetValueType(napi_env env,napi_value value)28 napi_valuetype GetValueType(napi_env env, napi_value value)
29 {
30 if (value == nullptr) {
31 return napi_undefined;
32 }
33
34 napi_valuetype valueType = napi_undefined;
35 NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined);
36 return valueType;
37 }
38
39 /* named property */
HasNamedProperty(napi_env env,napi_value object,const std::string & propertyName)40 bool HasNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
41 {
42 bool hasProperty = false;
43 NAPI_CALL_BASE(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty), false);
44 return hasProperty;
45 }
46
GetNamedProperty(napi_env env,napi_value object,const std::string & propertyName)47 napi_value GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
48 {
49 napi_value value = nullptr;
50 bool hasProperty = false;
51 NAPI_CALL(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty));
52 if (!hasProperty) {
53 return value;
54 }
55 NAPI_CALL(env, napi_get_named_property(env, object, propertyName.c_str(), &value));
56 return value;
57 }
58
GetPropertyNames(napi_env env,napi_value object)59 std::vector<std::string> GetPropertyNames(napi_env env, napi_value object)
60 {
61 std::vector<std::string> ret;
62 napi_value names = nullptr;
63 NAPI_CALL_BASE(env, napi_get_property_names(env, object, &names), ret);
64 uint32_t length = 0;
65 NAPI_CALL_BASE(env, napi_get_array_length(env, names, &length), ret);
66 for (uint32_t index = 0; index < length; ++index) {
67 napi_value name = nullptr;
68 if (napi_get_element(env, names, index, &name) != napi_ok) {
69 continue;
70 }
71 if (GetValueType(env, name) != napi_string) {
72 continue;
73 }
74 ret.emplace_back(GetStringFromValueUtf8(env, name));
75 }
76 return ret;
77 }
78
79 /* UINT32 */
CreateUint32(napi_env env,uint32_t code)80 napi_value CreateUint32(napi_env env, uint32_t code)
81 {
82 napi_value value = nullptr;
83 if (napi_create_uint32(env, code, &value) != napi_ok) {
84 return nullptr;
85 }
86 return value;
87 }
88
GetUint32FromValue(napi_env env,napi_value value)89 uint32_t GetUint32FromValue(napi_env env, napi_value value)
90 {
91 uint32_t ret = 0;
92 NAPI_CALL_BASE(env, napi_get_value_uint32(env, value, &ret), 0);
93 return ret;
94 }
95
GetUint32Property(napi_env env,napi_value object,const std::string & propertyName)96 uint32_t GetUint32Property(napi_env env, napi_value object, const std::string &propertyName)
97 {
98 if (!HasNamedProperty(env, object, propertyName)) {
99 return 0;
100 }
101 napi_value value = GetNamedProperty(env, object, propertyName);
102 return GetUint32FromValue(env, value);
103 }
104
SetUint32Property(napi_env env,napi_value object,const std::string & name,uint32_t value)105 void SetUint32Property(napi_env env, napi_value object, const std::string &name, uint32_t value)
106 {
107 napi_value jsValue = CreateUint32(env, value);
108 if (GetValueType(env, jsValue) != napi_number) {
109 return;
110 }
111
112 napi_set_named_property(env, object, name.c_str(), jsValue);
113 }
114
115 /* INT32 */
CreateInt32(napi_env env,int32_t code)116 napi_value CreateInt32(napi_env env, int32_t code)
117 {
118 napi_value value = nullptr;
119 if (napi_create_int32(env, code, &value) != napi_ok) {
120 return nullptr;
121 }
122 return value;
123 }
124
GetInt32FromValue(napi_env env,napi_value value)125 int32_t GetInt32FromValue(napi_env env, napi_value value)
126 {
127 int32_t ret = 0;
128 NAPI_CALL_BASE(env, napi_get_value_int32(env, value, &ret), 0);
129 return ret;
130 }
131
132 /* String UTF8 */
CreateStringUtf8(napi_env env,const std::string & str)133 napi_value CreateStringUtf8(napi_env env, const std::string &str)
134 {
135 napi_value value = nullptr;
136 if (napi_create_string_utf8(env, str.c_str(), strlen(str.c_str()), &value) != napi_ok) {
137 return nullptr;
138 }
139 return value;
140 }
141
GetStringFromValueUtf8(napi_env env,napi_value value)142 std::string GetStringFromValueUtf8(napi_env env, napi_value value)
143 {
144 std::string result;
145 std::vector<char> str(MAX_STRING_LENGTH + 1, '\0');
146 size_t length = 0;
147 NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, value, &str[0], MAX_STRING_LENGTH, &length), result);
148 if (length > 0) {
149 return result.append(&str[0], length);
150 }
151 return result;
152 }
153
GetStringPropertyUtf8(napi_env env,napi_value object,const std::string & propertyName)154 std::string GetStringPropertyUtf8(napi_env env, napi_value object, const std::string &propertyName)
155 {
156 if (!HasNamedProperty(env, object, propertyName)) {
157 return "";
158 }
159 napi_value value = GetNamedProperty(env, object, propertyName);
160 return GetStringFromValueUtf8(env, value);
161 }
162
SetStringPropertyUtf8(napi_env env,napi_value object,const std::string & name,const std::string & value)163 void SetStringPropertyUtf8(napi_env env, napi_value object, const std::string &name, const std::string &value)
164 {
165 napi_value jsValue = CreateStringUtf8(env, value);
166 if (GetValueType(env, jsValue) != napi_string) {
167 return;
168 }
169 napi_set_named_property(env, object, name.c_str(), jsValue);
170 }
171
172 /* object */
CreateObject(napi_env env)173 napi_value CreateObject(napi_env env)
174 {
175 napi_value object = nullptr;
176 NAPI_CALL(env, napi_create_object(env, &object));
177 return object;
178 }
179
180 /* undefined */
GetUndefined(napi_env env)181 napi_value GetUndefined(napi_env env)
182 {
183 napi_value undefined = nullptr;
184 NAPI_CALL(env, napi_get_undefined(env, &undefined));
185 return undefined;
186 }
187
188 /* function */
CallFunction(napi_env env,napi_value recv,napi_value func,size_t argc,const napi_value * argv)189 napi_value CallFunction(napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv)
190 {
191 napi_value res = nullptr;
192 NAPI_CALL(env, napi_call_function(env, recv, func, argc, argv, &res));
193 return res;
194 }
195
196 /* boolean */
GetBooleanProperty(napi_env env,napi_value object,const std::string & propertyName)197 bool GetBooleanProperty(napi_env env, napi_value object, const std::string &propertyName)
198 {
199 if (!HasNamedProperty(env, object, propertyName)) {
200 return false;
201 }
202 napi_value value = GetNamedProperty(env, object, propertyName);
203 bool ret = false;
204 NAPI_CALL_BASE(env, napi_get_value_bool(env, value, &ret), false);
205 return ret;
206 }
207
ToLower(const std::string & s)208 std::string ToLower(const std::string &s)
209 {
210 std::string res = s;
211 std::transform(res.begin(), res.end(), res.begin(), tolower);
212 return res;
213 }
214
GetParameterNumber(napi_env env,napi_callback_info info,napi_value * argv,napi_value * this_arg)215 int32_t GetParameterNumber(napi_env env, napi_callback_info info, napi_value *argv, napi_value *this_arg)
216 {
217 size_t argc = NapiUtils::MAX_ARGC;
218 void *data = nullptr;
219 napi_status status = napi_get_cb_info(env, info, &argc, argv, this_arg, &data);
220 if (status != napi_ok) {
221 return -1;
222 }
223 return static_cast<int32_t>(argc);
224 }
225
ThrowError(napi_env env,const ExceptionErrorCode & code,const std::string & msg)226 void ThrowError(napi_env env, const ExceptionErrorCode &code, const std::string &msg)
227 {
228 napi_value error = CreateBusinessError(env, code, msg);
229 napi_throw(env, error);
230 }
231
CreateBusinessError(napi_env env,const ExceptionErrorCode & errorCode,const std::string & errorMessage)232 napi_value CreateBusinessError(napi_env env, const ExceptionErrorCode &errorCode, const std::string &errorMessage)
233 {
234 napi_value error = nullptr;
235 napi_value code = nullptr;
236 napi_value msg = nullptr;
237 auto iter = ErrorCodeToMsg.find(errorCode);
238 std::string strMsg = (iter != ErrorCodeToMsg.end() ? iter->second : "") + " "+ errorMessage;
239 NAPI_CALL(env, napi_create_string_utf8(env, strMsg.c_str(), strMsg.length(), &msg));
240 NAPI_CALL(env, napi_create_uint32(env, errorCode, &code));
241 NAPI_CALL(env, napi_create_error(env, nullptr, msg, &error));
242 napi_set_named_property(env, error, "code", code);
243 return error;
244 }
245
CheckParameterCorrect(napi_env env,napi_callback_info info,const std::string & type,ExceptionError & err)246 bool CheckParameterCorrect(napi_env env, napi_callback_info info, const std::string &type, ExceptionError &err)
247 {
248 if (!DownloadManager::GetInstance()->CheckPermission()) {
249 err.code = EXCEPTION_PERMISSION;
250 err.errInfo = "Permission denied.An attempt was made to forbidden by permission:INTERNET";
251 return false;
252 }
253 std::string errInfo;
254 napi_value argv[NapiUtils::MAX_ARGC] = {nullptr};
255 int32_t num = NapiUtils::GetParameterNumber(env, info, argv, nullptr);
256 if (num < 0) {
257 err.code = EXCEPTION_PARAMETER_CHECK;
258 err.errInfo = "function ${" + type + "} Wrong number of arguments";
259 return false;
260 }
261 if (num == NapiUtils::ONE_ARG) {
262 if (NapiUtils::GetValueType(env, argv[NapiUtils::FIRST_ARGV]) != napi_function) {
263 err.code = EXCEPTION_PARAMETER_CHECK;
264 err.errInfo = "function ${" + type + "} the first parameter must be function";
265 return false;
266 }
267 }
268 return true;
269 }
270 } // namespace OHOS::Request::Download::NapiUtils