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_controller.h"
17
18 #include <js_native_api.h>
19 #include <js_native_api_types.h>
20 #include <napi/native_api.h>
21 #include <cstring>
22 #include "napi_parse_utils.h"
23
24 #include "nweb_helper.h"
25 #include "nweb_log.h"
26 #include "business_error.h"
27 #include "web_errors.h"
28
29 #include "proxy_config.h"
30 #include "proxy_rule.h"
31
32
33 namespace OHOS {
34 namespace NWeb {
35
JS_Constructor(napi_env env,napi_callback_info info)36 napi_value NapiProxyController::JS_Constructor(napi_env env, napi_callback_info info)
37 {
38 WVLOG_I("[PROXYCONTROLLER] NapiProxyController::JS_Constructor");
39 size_t argc = 1;
40 napi_value argv[1] = {0};
41 napi_value thisVar = nullptr;
42 void *data = nullptr;
43 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
44
45 return thisVar;
46 }
47
Init(napi_env env,napi_value exports)48 napi_value NapiProxyController::Init(napi_env env, napi_value exports)
49 {
50 napi_property_descriptor properties[] = {
51 DECLARE_NAPI_STATIC_FUNCTION("applyProxyOverride", NapiProxyController::JS_ApplyProxyOverride),
52 DECLARE_NAPI_STATIC_FUNCTION("removeProxyOverride", NapiProxyController::JS_RemoveProxyOverride),
53 };
54
55 napi_value proxyController = nullptr;
56 napi_define_class(env, PROXY_CONTROLLER_CLASS_NAME.c_str(), PROXY_CONTROLLER_CLASS_NAME.length(),
57 JS_Constructor, nullptr, sizeof(properties) / sizeof(properties[0]), properties, &proxyController);
58 napi_status status = napi_set_named_property(env, exports, "ProxyController", proxyController);
59 NAPI_ASSERT(env, status == napi_ok, "NapiProxyController set property failed.");
60
61 return exports;
62 }
63
InnerApplyProxyOverride(ProxyConfig * proxyConfig,napi_env env,napi_ref jsCallback)64 void NapiProxyController::InnerApplyProxyOverride(ProxyConfig *proxyConfig, napi_env env, napi_ref jsCallback)
65 {
66 std::vector<std::string> proxyUrls;
67 std::vector<std::string> proxySchemeFilters;
68 std::vector<std::string> bypassRules;
69 bool reverseBypass;
70 for (auto proxyRule : proxyConfig->GetProxyRules()) {
71 WVLOG_I("[PROXYCONTROLLER] add proxy rule %{public}s : %{public}d",
72 proxyRule.GetUrl().c_str(), proxyRule.GetSchemeFilter());
73 proxyUrls.push_back(proxyRule.GetUrl());
74 std::string proxySchemeFilter = "*";
75 switch (proxyRule.GetSchemeFilter()) {
76 case static_cast<int32_t>(ProxySchemeFilter::MATCH_ALL_SCHEMES):
77 break;
78 case static_cast<int32_t>(ProxySchemeFilter::MATCH_HTTP):
79 proxySchemeFilter = "http";
80 break;
81 case static_cast<int32_t>(ProxySchemeFilter::MATCH_HTTPS):
82 proxySchemeFilter = "https";
83 break;
84 }
85 proxySchemeFilters.push_back(proxySchemeFilter);
86 }
87 reverseBypass = proxyConfig->IsReverseBypassEnabled();
88 WVLOG_I("[PROXYCONTROLLER] reverse bypass %{public}d", reverseBypass);
89 for (auto bypassRule :proxyConfig->GetBypassRules()) {
90 WVLOG_I("[PROXYCONTROLLER] add bypass rule %{public}s", bypassRule.c_str());
91 bypassRules.push_back(bypassRule);
92 }
93
94 auto resultCallback = std::make_shared<ProxyChangedCallbackImpl>(env, jsCallback);
95 NWebHelper::Instance().SetProxyOverride(proxyUrls, proxySchemeFilters, bypassRules,
96 reverseBypass, resultCallback);
97 }
98
OnChanged()99 void ProxyChangedCallbackImpl::OnChanged()
100 {
101 napi_value callback = nullptr;
102 napi_get_reference_value(env_, callback_, &callback);
103
104 napi_call_function(env_, nullptr, callback, INTEGER_ZERO, nullptr, nullptr);
105 napi_delete_reference(env_, callback_);
106 }
107
JS_ApplyProxyOverride(napi_env env,napi_callback_info info)108 napi_value NapiProxyController::JS_ApplyProxyOverride(napi_env env, napi_callback_info info)
109 {
110 napi_value thisVar = nullptr;
111 size_t argc = INTEGER_TWO;
112 size_t argcCallback = INTEGER_TWO;
113 napi_value argv[INTEGER_TWO] = {0};
114
115 WVLOG_I("[PROXYCONTROLLER] apply proxy override.");
116 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
117 if (argc != INTEGER_TWO) {
118 WVLOG_E("[PROXYCONTROLLER] param check error.");
119 NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
120 return nullptr;
121 }
122
123 napi_valuetype valueType = napi_null;
124 napi_typeof(env, argv[argcCallback - 1], &valueType);
125 if (valueType != napi_function) {
126 WVLOG_E("[PROXYCONTROLLER] last arg is not function %{public}d.", valueType);
127 NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
128 NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "callback", "function"));
129 return nullptr;
130 }
131
132 napi_ref jsCallback = nullptr;
133 napi_create_reference(env, argv[argcCallback - 1], INTEGER_ONE, &jsCallback);
134 if (!jsCallback) {
135 WVLOG_E("[PROXYCONTROLLER] generate reference for callback failed.");
136 NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
137 NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "callback", "function"));
138 return nullptr;
139 }
140
141 ProxyConfig *proxyConfig = nullptr;
142 napi_unwrap(env, argv[0], (void **)&proxyConfig);
143
144 if (!proxyConfig) {
145 WVLOG_E("[PROXYCONTROLLER] unwrap ProxyConfig failed.");
146 napi_delete_reference(env, jsCallback);
147 return nullptr;
148 }
149
150 InnerApplyProxyOverride(proxyConfig, env, jsCallback);
151
152 return nullptr;
153 }
154
JS_RemoveProxyOverride(napi_env env,napi_callback_info info)155 napi_value NapiProxyController::JS_RemoveProxyOverride(napi_env env, napi_callback_info info)
156 {
157 napi_value thisVar = nullptr;
158 size_t argc = INTEGER_ONE;
159 size_t argcCallback = INTEGER_ONE;
160 napi_value argv[INTEGER_ONE] = {0};
161
162 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
163 if (argc != INTEGER_ONE) {
164 NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
165 return nullptr;
166 }
167
168 napi_valuetype valueType = napi_null;
169 napi_typeof(env, argv[argcCallback - 1], &valueType);
170 if (valueType != napi_function) {
171 NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
172 NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "callback", "function"));
173 return nullptr;
174 }
175
176 napi_ref jsCallback = nullptr;
177 napi_create_reference(env, argv[argcCallback - 1], INTEGER_ONE, &jsCallback);
178 if (!jsCallback) {
179 NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
180 NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "callback", "function"));
181 return nullptr;
182 }
183
184 auto resultCallback = std::make_shared<ProxyChangedCallbackImpl>(env, jsCallback);
185 NWebHelper::Instance().RemoveProxyOverride(resultCallback);
186
187 return nullptr;
188 }
189 } // namespace NWeb
190 } // namespace OHOS