1 /*
2 * Copyright (c) 2023 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_proxy_config.h"
17
18 #include <js_native_api.h>
19 #include <js_native_api_types.h>
20 #include <napi/native_api.h>
21 #include <securec.h>
22
23 #include "business_error.h"
24 #include "nweb_log.h"
25 #include "napi_parse_utils.h"
26 #include "napi/native_node_api.h"
27 #include "web_errors.h"
28
29 #include "proxy_config.h"
30 #include "proxy_rule.h"
31 #include "napi_proxy_rule.h"
32
33 using namespace OHOS::NWebError;
34
35 namespace OHOS {
36 namespace NWeb {
37
JS_InsertBypassRule(napi_env env,napi_callback_info info)38 napi_value NapiProxyConfig::JS_InsertBypassRule(napi_env env, napi_callback_info info)
39 {
40 size_t argc = 1;
41 napi_value argv[1] = {0};
42 napi_value thisVar = nullptr;
43 void *data = nullptr;
44 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
45
46 ProxyConfig *proxyConfig = nullptr;
47 napi_unwrap(env, thisVar, (void **)&proxyConfig);
48
49 if (!proxyConfig) {
50 WVLOG_E("[PROXYCONTROLLER] unwrap ProxyConfig failed.");
51 return nullptr;
52 }
53
54 std::string bypassRule;
55 if (!NapiParseUtils::ParseString(env, argv[0], bypassRule)) {
56 BusinessError::ThrowErrorByErrcode(env, PARAM_CHECK_ERROR,
57 NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "bypassRule", "string"));
58 return nullptr;
59 }
60
61 WVLOG_I("[PROXYCONTROLLER] insert bypass rule %{public}s.", bypassRule.c_str());
62 proxyConfig->InsertBypassRule(bypassRule);
63 return nullptr;
64 }
65
JS_InsertDirectRule(napi_env env,napi_callback_info info)66 napi_value NapiProxyConfig::JS_InsertDirectRule(napi_env env, napi_callback_info info)
67 {
68 size_t argc = 1;
69 napi_value argv[1] = {0};
70 napi_value thisVar = nullptr;
71 void *data = nullptr;
72 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
73
74 ProxyConfig *proxyConfig = nullptr;
75 napi_unwrap(env, thisVar, (void **)&proxyConfig);
76
77 if (!proxyConfig) {
78 WVLOG_E("[PROXYCONTROLLER] unwrap ProxyConfig failed.");
79 return nullptr;
80 }
81
82 if (argc > 0) {
83 int32_t schemeFilter = 0;
84 if (!NapiParseUtils::ParseInt32(env, argv[0], schemeFilter)) {
85 WVLOG_E("[PROXYCONTROLLER] parse int32 failed");
86 BusinessError::ThrowErrorByErrcode(env, PARAM_CHECK_ERROR,
87 "BusinessError 401: Parameter error. The type of 'schemeFilter' must be int.");
88 return nullptr;
89 }
90
91 WVLOG_I("[PROXYCONTROLLER] insert direct rule %{public}d.", schemeFilter);
92 proxyConfig->InsertDirectRule(schemeFilter);
93 } else {
94 WVLOG_I("[PROXYCONTROLLER] insert default direct rule.");
95 proxyConfig->InsertDirectRule();
96 }
97
98 return nullptr;
99 }
100
JS_InsertProxyRule(napi_env env,napi_callback_info info)101 napi_value NapiProxyConfig::JS_InsertProxyRule(napi_env env, napi_callback_info info)
102 {
103 size_t argc = 2;
104 napi_value argv[2] = {0};
105 napi_value thisVar = nullptr;
106 void *data = nullptr;
107 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
108
109 ProxyConfig *proxyConfig = nullptr;
110 napi_unwrap(env, thisVar, (void **)&proxyConfig);
111
112 if (!proxyConfig) {
113 WVLOG_E("[PROXYCONTROLLER] unwrap ProxyConfig failed.");
114 return nullptr;
115 }
116
117 std::string proxyUrl;
118 if (!NapiParseUtils::ParseString(env, argv[0], proxyUrl)) {
119 BusinessError::ThrowErrorByErrcode(env, PARAM_CHECK_ERROR,
120 NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "proxyUrl", "string"));
121 return nullptr;
122 }
123 if (argc > 1) {
124 int32_t schemeFilter = 0;
125 if (!NapiParseUtils::ParseInt32(env, argv[1], schemeFilter)) {
126 WVLOG_E("[PROXYCONTROLLER] parse int32 failed");
127 BusinessError::ThrowErrorByErrcode(env, PARAM_CHECK_ERROR,
128 "BusinessError 401: Parameter error. The type of 'schemeFilter' must be int.");
129 return nullptr;
130 }
131
132 WVLOG_I("[PROXYCONTROLLER] insert proxy rule %{public}s : %{public}d.", proxyUrl.c_str(), schemeFilter);
133 proxyConfig->InsertProxyRule(proxyUrl, schemeFilter);
134 } else {
135 WVLOG_I("[PROXYCONTROLLER] insert proxy rule, the schemeFilter is default.");
136 proxyConfig->InsertProxyRule(proxyUrl);
137 }
138
139 return nullptr;
140 }
141
JS_BypassHostnamesWithoutPeriod(napi_env env,napi_callback_info info)142 napi_value NapiProxyConfig::JS_BypassHostnamesWithoutPeriod(napi_env env, napi_callback_info info)
143 {
144 napi_value thisVar = nullptr;
145 void *data = nullptr;
146 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
147
148 ProxyConfig *proxyConfig = nullptr;
149 napi_unwrap(env, thisVar, (void **)&proxyConfig);
150
151 if (!proxyConfig) {
152 WVLOG_E("[PROXYCONTROLLER] unwrap ProxyConfig failed.");
153 return nullptr;
154 }
155
156 WVLOG_I("[PROXYCONTROLLER] bypass host names without period.");
157 proxyConfig->BypassHostnamesWithoutPeriod();
158 return nullptr;
159 }
160
JS_ClearImplicitRules(napi_env env,napi_callback_info info)161 napi_value NapiProxyConfig::JS_ClearImplicitRules(napi_env env, napi_callback_info info)
162 {
163 napi_value thisVar = nullptr;
164 void *data = nullptr;
165 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
166
167 ProxyConfig *proxyConfig = nullptr;
168 napi_unwrap(env, thisVar, (void **)&proxyConfig);
169
170 if (!proxyConfig) {
171 WVLOG_E("[PROXYCONTROLLER] unwrap ProxyConfig failed.");
172 return nullptr;
173 }
174
175 WVLOG_I("[PROXYCONTROLLER] clear implicit rules.");
176 proxyConfig->ClearImplicitRules();
177 return nullptr;
178 }
179
JS_EnableReverseBypass(napi_env env,napi_callback_info info)180 napi_value NapiProxyConfig::JS_EnableReverseBypass(napi_env env, napi_callback_info info)
181 {
182 size_t argc = 1;
183 napi_value argv[1] = {0};
184 napi_value thisVar = nullptr;
185 void *data = nullptr;
186 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
187
188 ProxyConfig *proxyConfig = nullptr;
189 napi_unwrap(env, thisVar, (void **)&proxyConfig);
190
191 if (!proxyConfig) {
192 WVLOG_E("[PROXYCONTROLLER] unwrap ProxyConfig failed.");
193 return nullptr;
194 }
195
196 bool enableReverseBypass = false;
197 if (!NapiParseUtils::ParseBoolean(env, argv[0], enableReverseBypass)) {
198 WVLOG_E("[PROXYCONTROLLER] parse boolean failed.");
199 BusinessError::ThrowErrorByErrcode(env, PARAM_CHECK_ERROR,
200 NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "enableReverseBypass", "boolean"));
201 return nullptr;
202 }
203
204 WVLOG_I("[PROXYCONTROLLER] enable reverse bypass %{public}d.", enableReverseBypass);
205 proxyConfig->EnableReverseBypass(enableReverseBypass);
206 return nullptr;
207 }
208
JS_GetBypassRules(napi_env env,napi_callback_info info)209 napi_value NapiProxyConfig::JS_GetBypassRules(napi_env env, napi_callback_info info)
210 {
211 size_t argc = 1;
212 napi_value argv[1] = {0};
213 napi_value thisVar = nullptr;
214 void *data = nullptr;
215 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
216
217 ProxyConfig *proxyConfig = nullptr;
218 napi_unwrap(env, thisVar, (void **)&proxyConfig);
219
220 if (!proxyConfig) {
221 WVLOG_E("[PROXYCONTROLLER] unwrap ProxyConfig failed.");
222 return nullptr;
223 }
224
225 napi_value result;
226 napi_create_array(env, &result);
227 std::vector<std::string> bypassRules = proxyConfig->GetBypassRules();
228
229 for (size_t index = 0; index < bypassRules.size(); index++) {
230 WVLOG_I("[PROXYCONTROLLER] get bypass rules %{public}s.", bypassRules[index].c_str());
231 napi_value jsBypassRule = nullptr;
232 napi_status status = napi_create_string_utf8(env, bypassRules[index].c_str(),
233 bypassRules[index].length(), &jsBypassRule);
234 if (status != napi_ok) {
235 WVLOG_I("[PROXYCONTROLLER] create js string error");
236 continue;
237 }
238 NAPI_CALL(env, napi_set_element(env, result, index, jsBypassRule));
239 }
240
241 return result;
242 }
243
JS_GetProxyRules(napi_env env,napi_callback_info info)244 napi_value NapiProxyConfig::JS_GetProxyRules(napi_env env, napi_callback_info info)
245 {
246 size_t argc = 1;
247 napi_value argv[1] = {0};
248 napi_value thisVar = nullptr;
249 void *data = nullptr;
250 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
251
252 ProxyConfig *proxyConfig = nullptr;
253 napi_unwrap(env, thisVar, (void **)&proxyConfig);
254
255 if (!proxyConfig) {
256 WVLOG_E("[PROXYCONTROLLER] unwrap ProxyConfig failed");
257 return nullptr;
258 }
259
260 napi_value result = nullptr;
261 napi_create_array(env, &result);
262 std::vector<ProxyRule> proxyRules = proxyConfig->GetProxyRules();
263 for (size_t index = 0; index < proxyRules.size(); index++) {
264 WVLOG_I("[PROXYCONTROLLER] get proxy rules %{public}s %{public}d",
265 proxyRules[index].GetUrl().c_str(), proxyRules[index].GetSchemeFilter());
266 napi_value jsProxyRule = nullptr;
267 napi_create_object(env, &jsProxyRule);
268 napi_wrap(
269 env, jsProxyRule, new ProxyRule(proxyRules[index].GetUrl().c_str(), proxyRules[index].GetSchemeFilter()),
270 [](napi_env /* env */, void *data, void * /* hint */) {
271 if (data) {
272 ProxyRule *proxyRule = static_cast<ProxyRule *>(data);
273 delete proxyRule;
274 }
275 },
276 nullptr, nullptr);
277 NapiProxyRule::DefineProperties(env, &jsProxyRule);
278 NAPI_CALL(env, napi_set_element(env, result, index, jsProxyRule));
279 }
280
281 return result;
282 }
283
JS_IsReverseBypassEnabled(napi_env env,napi_callback_info info)284 napi_value NapiProxyConfig::JS_IsReverseBypassEnabled(napi_env env, napi_callback_info info)
285 {
286 size_t argc = 1;
287 napi_value argv[1] = {0};
288 napi_value thisVar = nullptr;
289 void *data = nullptr;
290 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
291
292 ProxyConfig *proxyConfig = nullptr;
293 napi_unwrap(env, thisVar, (void **)&proxyConfig);
294
295 if (!proxyConfig) {
296 WVLOG_E("[PROXYCONTROLLER] unwrap ProxyConfig failed");
297 return nullptr;
298 }
299
300 napi_value result = nullptr;
301 bool enabled = proxyConfig->IsReverseBypassEnabled();
302 WVLOG_I("[PROXYCONTROLLER] is reverse bypass enabled %{public}d", enabled);
303 NAPI_CALL(env, napi_get_boolean(env, enabled, &result));
304 return result;
305 }
306
Init(napi_env env,napi_value exports)307 napi_value NapiProxyConfig::Init(napi_env env, napi_value exports)
308 {
309 WVLOG_I("[PROXYCONTROLLER] NapiProxyConfig::Init is called");
310 napi_property_descriptor properties[] = {
311 DECLARE_NAPI_FUNCTION("insertBypassRule", NapiProxyConfig::JS_InsertBypassRule),
312 DECLARE_NAPI_FUNCTION("insertDirectRule", NapiProxyConfig::JS_InsertDirectRule),
313 DECLARE_NAPI_FUNCTION("insertProxyRule", NapiProxyConfig::JS_InsertProxyRule),
314 DECLARE_NAPI_FUNCTION("bypassHostnamesWithoutPeriod", NapiProxyConfig::JS_BypassHostnamesWithoutPeriod),
315 DECLARE_NAPI_FUNCTION("clearImplicitRules", NapiProxyConfig::JS_ClearImplicitRules),
316 DECLARE_NAPI_FUNCTION("enableReverseBypass", NapiProxyConfig::JS_EnableReverseBypass),
317 DECLARE_NAPI_FUNCTION("getBypassRules", NapiProxyConfig::JS_GetBypassRules),
318 DECLARE_NAPI_FUNCTION("getProxyRules", NapiProxyConfig::JS_GetProxyRules),
319 DECLARE_NAPI_FUNCTION("isReverseBypassEnabled", NapiProxyConfig::JS_IsReverseBypassEnabled),
320 };
321
322 napi_value constructor = nullptr;
323 napi_define_class(env, PROXY_CONFIG_CLASS_NAME.c_str(), PROXY_CONFIG_CLASS_NAME.length(),
324 JS_Constructor, nullptr, sizeof(properties) / sizeof(properties[0]), properties, &constructor);
325 NAPI_ASSERT(env, constructor != nullptr, "NapiProxyConfig define js class failed.");
326 napi_status status = napi_set_named_property(env, exports, PROXY_CONFIG_CLASS_NAME.c_str(), constructor);
327 NAPI_ASSERT(env, status == napi_ok, "NapiProxyConfig set property failed.");
328
329 return exports;
330 }
331
JS_Constructor(napi_env env,napi_callback_info info)332 napi_value NapiProxyConfig::JS_Constructor(napi_env env, napi_callback_info info)
333 {
334 WVLOG_I("[PROXYCONTROLLER] NapiProxyConfig::JS_Constructor is called");
335 napi_value thisVar = nullptr;
336 void *data = nullptr;
337 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
338
339 ProxyConfig *nativeProxyConfig = new ProxyConfig();
340
341 napi_wrap(
342 env, thisVar, nativeProxyConfig,
343 [](napi_env /* env */, void *data, void * /* hint */) {
344 ProxyConfig *proxyConfig = (ProxyConfig *)data;
345 delete proxyConfig;
346 },
347 nullptr, nullptr);
348
349 return thisVar;
350 }
351
352 }
353 }