1 /*
2 * Copyright (C) 2024 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 <cstdint>
19 #include <mutex>
20 #include <string>
21
22 #include "base/request/request/common/include/constant.h"
23 #include "js_native_api.h"
24 #include "napi/native_common.h"
25
26 namespace OHOS::Request {
CreateBusinessError(napi_env env,int32_t errorCode,const std::string & errorMessage)27 napi_value CreateBusinessError(napi_env env, int32_t errorCode, const std::string &errorMessage)
28 {
29 napi_value error = nullptr;
30 napi_value msg = nullptr;
31 NAPI_CALL(env, napi_create_string_utf8(env, errorMessage.c_str(), errorMessage.length(), &msg));
32 NAPI_CALL(env, napi_create_error(env, nullptr, msg, &error));
33 napi_value code = nullptr;
34 NAPI_CALL(env, napi_create_uint32(env, static_cast<uint32_t>(errorCode), &code));
35 napi_set_named_property(env, error, "code", code);
36 return error;
37 }
38
ThrowError(napi_env env,int32_t code,const std::string & msg)39 void ThrowError(napi_env env, int32_t code, const std::string &msg)
40 {
41 napi_value error = CreateBusinessError(env, code, msg);
42 napi_throw(env, error);
43 }
44
GetValueType(napi_env env,napi_value value)45 napi_valuetype GetValueType(napi_env env, napi_value value)
46 {
47 if (value == nullptr) {
48 return napi_undefined;
49 }
50 napi_valuetype valueType = napi_undefined;
51 NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined);
52 return valueType;
53 }
54
GetStringLength(napi_env env,napi_value value)55 size_t GetStringLength(napi_env env, napi_value value)
56 {
57 size_t length;
58 NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, value, nullptr, 0, &length), 0);
59 return length;
60 }
61
GetValueString(napi_env env,napi_value value,size_t length)62 std::string GetValueString(napi_env env, napi_value value, size_t length)
63 {
64 char chars[length + 1];
65 NAPI_CALL(env, napi_get_value_string_utf8(env, value, chars, sizeof(chars), &length));
66 return std::string(chars);
67 }
68
GetValueNum(napi_env env,napi_value value)69 int64_t GetValueNum(napi_env env, napi_value value)
70 {
71 int64_t ret;
72 NAPI_CALL_BASE(env, napi_get_value_int64(env, value, &ret), 0);
73 return ret;
74 }
75
GetPropertyNames(napi_env env,napi_value object)76 std::vector<std::string> GetPropertyNames(napi_env env, napi_value object)
77 {
78 std::vector<std::string> ret;
79 napi_value names = nullptr;
80 NAPI_CALL_BASE(env, napi_get_property_names(env, object, &names), ret);
81 uint32_t length = 0;
82 NAPI_CALL_BASE(env, napi_get_array_length(env, names, &length), ret);
83 for (uint32_t index = 0; index < length; ++index) {
84 napi_value name = nullptr;
85 if (napi_get_element(env, names, index, &name) != napi_ok) {
86 continue;
87 }
88 if (GetValueType(env, name) != napi_string) {
89 continue;
90 }
91 size_t propertyLength = GetStringLength(env, name);
92 ret.emplace_back(GetValueString(env, name, propertyLength));
93 }
94 return ret;
95 }
96
HasNamedProperty(napi_env env,napi_value object,const std::string & propertyName)97 bool HasNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
98 {
99 bool hasProperty = false;
100 NAPI_CALL_BASE(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty), false);
101 return hasProperty;
102 }
103
GetNamedProperty(napi_env env,napi_value object,const std::string & propertyName)104 napi_value GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
105 {
106 napi_value value = nullptr;
107 bool hasProperty = false;
108 NAPI_CALL(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty));
109 if (!hasProperty) {
110 return value;
111 }
112 NAPI_CALL(env, napi_get_named_property(env, object, propertyName.c_str(), &value));
113 return value;
114 }
115
GetPropertyValue(napi_env env,napi_value object,const std::string & propertyName)116 std::string GetPropertyValue(napi_env env, napi_value object, const std::string &propertyName)
117 {
118 if (!HasNamedProperty(env, object, propertyName)) {
119 return "";
120 }
121 napi_value value = GetNamedProperty(env, object, propertyName);
122 if (GetValueType(env, value) != napi_string) {
123 return "";
124 }
125 auto length = GetStringLength(env, value);
126 return GetValueString(env, value, length);
127 }
128
setPerformanceField(napi_env env,napi_value performance,double field_value,const char * js_name)129 inline napi_status setPerformanceField(napi_env env, napi_value performance, double field_value, const char *js_name)
130 {
131 napi_value value;
132 napi_status status = napi_create_double(env, field_value, &value);
133 if (status != napi_ok) {
134 return status;
135 }
136
137 return napi_set_named_property(env, performance, js_name, value);
138 }
139
buildInfoResource(napi_env env,const CppDownloadInfo & result,napi_value & jsInfo)140 bool buildInfoResource(napi_env env, const CppDownloadInfo &result, napi_value &jsInfo)
141 {
142 napi_status status;
143 napi_value resource;
144 status = napi_create_object(env, &resource);
145 if (status != napi_ok) {
146 return false;
147 }
148
149 napi_value sizeValue;
150 status = napi_create_int64(env, result.resource_size(), &sizeValue);
151 if (status != napi_ok) {
152 return false;
153 }
154
155 status = napi_set_named_property(env, resource, "size", sizeValue);
156 if (status != napi_ok) {
157 return false;
158 }
159
160 status = napi_set_named_property(env, jsInfo, "resource", resource);
161 if (status != napi_ok) {
162 return false;
163 }
164
165 return true;
166 }
167
buildInfoNetwork(napi_env env,const CppDownloadInfo & result,napi_value & jsInfo)168 bool buildInfoNetwork(napi_env env, const CppDownloadInfo &result, napi_value &jsInfo)
169 {
170 napi_status status;
171 napi_value network;
172 status = napi_create_object(env, &network);
173 if (status != napi_ok) {
174 return false;
175 }
176
177 napi_value ipValue;
178 status = napi_create_string_utf8(env, result.network_ip().c_str(), NAPI_AUTO_LENGTH, &ipValue);
179 if (status != napi_ok) {
180 return false;
181 }
182
183 status = napi_set_named_property(env, network, "ip", ipValue);
184 if (status != napi_ok) {
185 return false;
186 }
187
188 std::vector<std::string> dnsServers = result.dns_servers();
189
190 napi_value dnsArray;
191 status = napi_create_array_with_length(env, dnsServers.size(), &dnsArray);
192 if (status != napi_ok) {
193 return false;
194 }
195 for (size_t i = 0; i < dnsServers.size(); i++) {
196 const std::string &server = dnsServers[i];
197 napi_value dnsItem;
198 status = napi_create_string_utf8(env, server.c_str(), NAPI_AUTO_LENGTH, &dnsItem);
199 if (status != napi_ok) {
200 return false;
201 }
202
203 status = napi_set_element(env, dnsArray, i, dnsItem);
204 if (status != napi_ok) {
205 return false;
206 }
207 }
208 status = napi_set_named_property(env, network, "dnsServers", dnsArray);
209 if (status != napi_ok) {
210 return false;
211 }
212 status = napi_set_named_property(env, jsInfo, "network", network);
213 if (status != napi_ok) {
214 return false;
215 }
216 return true;
217 }
218
buildInfoPerformance(napi_env env,const CppDownloadInfo & result,napi_value & jsInfo)219 bool buildInfoPerformance(napi_env env, const CppDownloadInfo &result, napi_value &jsInfo)
220 {
221 napi_status status;
222 napi_value performance;
223 status = napi_create_object(env, &performance);
224 if (status != napi_ok) {
225 return false;
226 }
227
228 if ((status = setPerformanceField(env, performance, result.dns_time(), "dnsTime")) != napi_ok) {
229 return false;
230 }
231 if ((status = setPerformanceField(env, performance, result.connect_time(), "connectTime")) != napi_ok) {
232 return false;
233 }
234 if ((status = setPerformanceField(env, performance, result.tls_time(), "tlsTime")) != napi_ok) {
235 return false;
236 }
237 if ((status = setPerformanceField(env, performance, result.first_send_time(), "firstSendTime")) != napi_ok) {
238 return false;
239 }
240 if ((status = setPerformanceField(env, performance, result.first_recv_time(), "firstReceiveTime")) != napi_ok) {
241 return false;
242 }
243 if ((status = setPerformanceField(env, performance, result.total_time(), "totalTime")) != napi_ok) {
244 return false;
245 }
246 if ((status = setPerformanceField(env, performance, result.redirect_time(), "redirectTime")) != napi_ok) {
247 return false;
248 }
249
250 status = napi_set_named_property(env, jsInfo, "performance", performance);
251 if (status != napi_ok) {
252 return false;
253 }
254
255 return true;
256 }
257
258 } // namespace OHOS::Request