• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_web_cookie_manager.h"
17 
18 #include <cstdint>
19 #include <uv.h>
20 #include <vector>
21 
22 #include "business_error.h"
23 #include "napi/native_common.h"
24 #include "nweb_cookie_manager.h"
25 #include "nweb_helper.h"
26 #include "nweb_log.h"
27 #include "napi_parse_utils.h"
28 #include "web_errors.h"
29 #include "securec.h"
30 
31 namespace OHOS {
32 namespace NWeb {
Init(napi_env env,napi_value exports)33 napi_value NapiWebCookieManager::Init(napi_env env, napi_value exports)
34 {
35     napi_property_descriptor properties[] = {
36         DECLARE_NAPI_STATIC_FUNCTION("getCookie", NapiWebCookieManager::JsGetCookie),
37         DECLARE_NAPI_STATIC_FUNCTION("setCookie", NapiWebCookieManager::JsSetCookie),
38         DECLARE_NAPI_STATIC_FUNCTION("isCookieAllowed", NapiWebCookieManager::JsIsCookieAllowed),
39         DECLARE_NAPI_STATIC_FUNCTION("putAcceptCookieEnabled", NapiWebCookieManager::JsPutAcceptCookieEnabled),
40         DECLARE_NAPI_STATIC_FUNCTION("isThirdPartyCookieAllowed",
41                                      NapiWebCookieManager::JsIsThirdPartyCookieAllowed),
42         DECLARE_NAPI_STATIC_FUNCTION("putAcceptThirdPartyCookieEnabled",
43                                      NapiWebCookieManager::JsPutAcceptThirdPartyCookieEnabled),
44         DECLARE_NAPI_STATIC_FUNCTION("existCookie", NapiWebCookieManager::JsExistCookie),
45         DECLARE_NAPI_STATIC_FUNCTION("deleteEntireCookie", NapiWebCookieManager::JsDeleteEntireCookie),
46         DECLARE_NAPI_STATIC_FUNCTION("deleteSessionCookie", NapiWebCookieManager::JsDeleteSessionCookie),
47         DECLARE_NAPI_STATIC_FUNCTION("saveCookieAsync", NapiWebCookieManager::JsSaveCookieAsync),
48     };
49     napi_value constructor = nullptr;
50 
51     napi_define_class(env, WEB_COOKIE_MANAGER_CLASS_NAME.c_str(), WEB_COOKIE_MANAGER_CLASS_NAME.length(),
52         JsConstructor, nullptr, sizeof(properties) / sizeof(properties[0]), properties, &constructor);
53     NAPI_ASSERT(env, constructor != nullptr, "NapiWebCookieManager define js class failed");
54     napi_status status = napi_set_named_property(env, exports, "WebCookieManager", constructor);
55     NAPI_ASSERT(env, status == napi_ok, "NapiWebCookieManager set property failed");
56     return exports;
57 }
58 
JsConstructor(napi_env env,napi_callback_info info)59 napi_value NapiWebCookieManager::JsConstructor(napi_env env, napi_callback_info info)
60 {
61     napi_value thisVar = nullptr;
62 
63     size_t argc = INTEGER_TWO;
64     napi_value argv[INTEGER_TWO] = { 0 };
65     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
66     return thisVar;
67 }
68 
GetStringPara(napi_env env,napi_value argv,std::string & outValue)69 bool NapiWebCookieManager::GetStringPara(napi_env env, napi_value argv, std::string& outValue)
70 {
71     constexpr int32_t MAX_STRING_LENGTH = 40960;
72     size_t bufferSize = 0;
73     napi_valuetype valueType = napi_null;
74 
75     napi_typeof(env, argv, &valueType);
76     if (valueType != napi_string) {
77         return false;
78     }
79     napi_get_value_string_utf8(env, argv, nullptr, 0, &bufferSize);
80     if (bufferSize > MAX_STRING_LENGTH) {
81         return false;
82     }
83     char stringValue[bufferSize + 1];
84     size_t jsStringLength = 0;
85     napi_get_value_string_utf8(env, argv, stringValue, bufferSize + 1, &jsStringLength);
86     if (jsStringLength != bufferSize) {
87         return false;
88     }
89     outValue = stringValue;
90     return true;
91 }
92 
GetBooleanPara(napi_env env,napi_value argv,bool & outValue)93 bool NapiWebCookieManager::GetBooleanPara(napi_env env, napi_value argv, bool& outValue)
94 {
95     napi_valuetype valueType = napi_null;
96 
97     napi_typeof(env, argv, &valueType);
98     if (valueType != napi_boolean) {
99         return false;
100     }
101 
102     bool boolValue;
103     napi_get_value_bool(env, argv, &boolValue);
104     outValue = boolValue;
105     return true;
106 }
107 
JsGetCookie(napi_env env,napi_callback_info info)108 napi_value NapiWebCookieManager::JsGetCookie(napi_env env, napi_callback_info info)
109 {
110     napi_value retValue = nullptr;
111     size_t argc = INTEGER_ONE;
112     napi_value argv[INTEGER_ONE] = { 0 };
113 
114     napi_get_cb_info(env, info, &argc, argv, &retValue, nullptr);
115     if (argc != INTEGER_ONE) {
116         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
117         return nullptr;
118     }
119 
120     std::string url;
121     if (!GetStringPara(env, argv[INTEGER_ZERO], url)) {
122         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
123         return nullptr;
124     }
125 
126     napi_value result = nullptr;
127     std::string cookieContent = "";
128 
129     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
130     bool is_valid = true;
131     if (cookieManager != nullptr) {
132         cookieContent = cookieManager->ReturnCookie(url, is_valid);
133     }
134 
135     if (cookieContent == "" && !is_valid) {
136         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::INVALID_URL);
137         return nullptr;
138     }
139     napi_create_string_utf8(env, cookieContent.c_str(), cookieContent.length(), &result);
140     return result;
141 }
142 
JsSetCookie(napi_env env,napi_callback_info info)143 napi_value NapiWebCookieManager::JsSetCookie(napi_env env, napi_callback_info info)
144 {
145     napi_value retValue = nullptr;
146     size_t argc = INTEGER_TWO;
147     napi_value argv[INTEGER_TWO] = { 0 };
148 
149     napi_get_cb_info(env, info, &argc, argv, &retValue, nullptr);
150     if (argc != INTEGER_TWO) {
151         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
152         return nullptr;
153     }
154 
155     std::string url;
156     std::string value;
157     if (!GetStringPara(env, argv[INTEGER_ZERO], url)) {
158         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
159         return nullptr;
160     }
161     if (!GetStringPara(env, argv[INTEGER_ONE], value)) {
162         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
163         return nullptr;
164     }
165 
166     napi_value result = nullptr;
167     int isSet = -1;
168 
169     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
170     if (cookieManager != nullptr) {
171         isSet = cookieManager->SetCookie(url, value);
172     }
173     if (isSet == NWebError::INVALID_URL) {
174         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::INVALID_URL);
175         return nullptr;
176     } else if (isSet == NWebError::INVALID_COOKIE_VALUE) {
177         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::INVALID_COOKIE_VALUE);
178         return nullptr;
179     }
180     NAPI_CALL(env, napi_get_undefined(env, &result));
181     return result;
182 }
183 
JsIsCookieAllowed(napi_env env,napi_callback_info info)184 napi_value NapiWebCookieManager::JsIsCookieAllowed(napi_env env, napi_callback_info info)
185 {
186     napi_value result = nullptr;
187     bool accept = true;
188 
189     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
190     if (cookieManager != nullptr) {
191         accept = cookieManager->IsAcceptCookieAllowed();
192     }
193     NAPI_CALL(env, napi_get_boolean(env, accept, &result));
194     return result;
195 }
196 
JsPutAcceptCookieEnabled(napi_env env,napi_callback_info info)197 napi_value NapiWebCookieManager::JsPutAcceptCookieEnabled(napi_env env, napi_callback_info info)
198 {
199     napi_value retValue = nullptr;
200     size_t argc = INTEGER_ONE;
201     napi_value argv[INTEGER_ONE] = { 0 };
202 
203     napi_get_cb_info(env, info, &argc, argv, &retValue, nullptr);
204     if (argc != INTEGER_ONE) {
205         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
206         return nullptr;
207     }
208 
209     bool accept;
210     if (!GetBooleanPara(env, argv[INTEGER_ZERO], accept)) {
211         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
212         return nullptr;
213     }
214 
215     napi_value result = nullptr;
216 
217     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
218     if (cookieManager != nullptr) {
219         cookieManager->PutAcceptCookieEnabled(accept);
220     }
221     NAPI_CALL(env, napi_get_undefined(env, &result));
222     return result;
223 }
224 
JsIsThirdPartyCookieAllowed(napi_env env,napi_callback_info info)225 napi_value NapiWebCookieManager::JsIsThirdPartyCookieAllowed(napi_env env, napi_callback_info info)
226 {
227     napi_value result = nullptr;
228     bool accept = true;
229 
230     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
231     if (cookieManager != nullptr) {
232         accept = cookieManager->IsThirdPartyCookieAllowed();
233     }
234     NAPI_CALL(env, napi_get_boolean(env, accept, &result));
235     return result;
236 }
237 
JsPutAcceptThirdPartyCookieEnabled(napi_env env,napi_callback_info info)238 napi_value NapiWebCookieManager::JsPutAcceptThirdPartyCookieEnabled(napi_env env, napi_callback_info info)
239 {
240     napi_value retValue = nullptr;
241     size_t argc = INTEGER_ONE;
242     napi_value argv[INTEGER_ONE] = { 0 };
243 
244     napi_get_cb_info(env, info, &argc, argv, &retValue, nullptr);
245     if (argc != INTEGER_ONE) {
246         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
247         return nullptr;
248     }
249 
250     bool accept;
251     if (!GetBooleanPara(env, argv[INTEGER_ZERO], accept)) {
252         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
253         return nullptr;
254     }
255 
256     napi_value result = nullptr;
257 
258     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
259     if (cookieManager != nullptr) {
260         cookieManager->PutAcceptThirdPartyCookieEnabled(accept);
261     }
262     NAPI_CALL(env, napi_get_undefined(env, &result));
263     return result;
264 }
265 
JsExistCookie(napi_env env,napi_callback_info info)266 napi_value NapiWebCookieManager::JsExistCookie(napi_env env, napi_callback_info info)
267 {
268     napi_value result = nullptr;
269     bool exist = true;
270 
271     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
272     if (cookieManager != nullptr) {
273         exist = cookieManager->ExistCookies();
274     }
275     NAPI_CALL(env, napi_get_boolean(env, exist, &result));
276     return result;
277 }
278 
JsDeleteEntireCookie(napi_env env,napi_callback_info info)279 napi_value NapiWebCookieManager::JsDeleteEntireCookie(napi_env env, napi_callback_info info)
280 {
281     napi_value result = nullptr;
282 
283     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
284     if (cookieManager != nullptr) {
285         cookieManager->DeleteCookieEntirely(nullptr);
286     }
287     NAPI_CALL(env, napi_get_undefined(env, &result));
288     return result;
289 }
290 
JsDeleteSessionCookie(napi_env env,napi_callback_info info)291 napi_value NapiWebCookieManager::JsDeleteSessionCookie(napi_env env, napi_callback_info info)
292 {
293     napi_value result = nullptr;
294 
295     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
296     if (cookieManager != nullptr) {
297         cookieManager->DeleteSessionCookies(nullptr);
298     }
299     napi_get_undefined(env, &result);
300     return result;
301 }
302 
SaveCookieAsyncCallback(napi_env env,napi_ref jsCallback)303 void SaveCookieAsyncCallback(napi_env env, napi_ref jsCallback)
304 {
305     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
306     if (cookieManager == nullptr) {
307         napi_value jsResult = nullptr;
308         napi_get_null(env, &jsResult);
309         napi_value callback = nullptr;
310         napi_get_reference_value(env, jsCallback, &callback);
311         napi_value callbackResult = nullptr;
312         napi_call_function(env, nullptr, callback, INTEGER_ONE, &jsResult, &callbackResult);
313         napi_delete_reference(env, jsCallback);
314     } else {
315         auto callbackImpl = std::make_shared<OHOS::NWeb::NWebSaveCookieCallbackImpl>(env, jsCallback, nullptr);
316         cookieManager->Store(callbackImpl);
317     }
318 }
319 
SaveCookieAsyncPromise(napi_env env,napi_deferred deferred)320 void SaveCookieAsyncPromise(napi_env env, napi_deferred deferred)
321 {
322     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
323     if (cookieManager == nullptr) {
324         napi_value jsResult = nullptr;
325         napi_get_undefined(env, &jsResult);
326         napi_reject_deferred(env, deferred, jsResult);
327     } else {
328         auto callbackImpl = std::make_shared<OHOS::NWeb::NWebSaveCookieCallbackImpl>(env, nullptr, deferred);
329         cookieManager->Store(callbackImpl);
330     }
331 }
332 
JsSaveCookieAsync(napi_env env,napi_callback_info info)333 napi_value NapiWebCookieManager::JsSaveCookieAsync(napi_env env, napi_callback_info info)
334 {
335     napi_value thisVar = nullptr;
336 
337     size_t argc = INTEGER_ONE;
338     size_t argcPromise = INTEGER_ZERO;
339     size_t argcCallback = INTEGER_ONE;
340     napi_value argv[INTEGER_ONE] = {0};
341 
342     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
343     if (argc != argcPromise && argc != argcCallback) {
344         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
345         return nullptr;
346     }
347 
348     napi_value result = nullptr;
349     napi_get_undefined(env, &result);
350 
351     if (argc == argcCallback) {
352         napi_valuetype valueType = napi_null;
353         napi_typeof(env, argv[argcCallback - 1], &valueType);
354         if (valueType != napi_function) {
355             NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
356             return nullptr;
357         }
358         napi_ref jsCallback = nullptr;
359         napi_create_reference(env, argv[argcCallback - 1], INTEGER_ONE, &jsCallback);
360 
361         if (jsCallback) {
362             SaveCookieAsyncCallback(env, jsCallback);
363         }
364         return result;
365     }
366 
367     napi_deferred deferred = nullptr;
368     napi_value promise = nullptr;
369     napi_create_promise(env, &deferred, &promise);
370     if (promise && deferred) {
371         SaveCookieAsyncPromise(env, deferred);
372     }
373     return promise;
374 }
375 
UvJsCallbackThreadWoker(uv_work_t * work,int status)376 void NWebSaveCookieCallbackImpl::UvJsCallbackThreadWoker(uv_work_t *work, int status)
377 {
378     if (work == nullptr) {
379         WVLOG_E("uv work is null");
380         return;
381     }
382     NapiWebCookieManager::WebCookieManagerParam *data =
383         reinterpret_cast<NapiWebCookieManager::WebCookieManagerParam*>(work->data);
384     if (data == nullptr) {
385         WVLOG_E("WebCookieManagerParam is null");
386         delete work;
387         work = nullptr;
388         return;
389     }
390     napi_handle_scope scope = nullptr;
391     napi_open_handle_scope(data->env_, &scope);
392     if (scope == nullptr) {
393         return;
394     }
395 
396     if (data->callback_) {
397         napi_value result[INTEGER_ONE] = {0};
398         napi_get_null(data->env_, &result[INTEGER_ZERO]);
399 
400         napi_value onSaveCookieFunc = nullptr;
401         napi_get_reference_value(data->env_, data->callback_, &onSaveCookieFunc);
402         napi_value callbackResult = nullptr;
403         napi_call_function(data->env_, nullptr, onSaveCookieFunc,
404             INTEGER_ONE, &result[INTEGER_ZERO], &callbackResult);
405         napi_delete_reference(data->env_, data->callback_);
406     } else if (data->deferred_) {
407         napi_value jsResult = nullptr;
408         napi_get_undefined(data->env_, &jsResult);
409         napi_resolve_deferred(data->env_, data->deferred_, jsResult);
410     }
411 
412     napi_close_handle_scope(data->env_, scope);
413     delete data;
414     data = nullptr;
415     delete work;
416     work = nullptr;
417 }
418 
OnReceiveValue(bool result)419 void NWebSaveCookieCallbackImpl::OnReceiveValue(bool result)
420 {
421     WVLOG_D("save cookie received result, result = %{public}d", result);
422     uv_loop_s *loop = nullptr;
423     uv_work_t *work = nullptr;
424     napi_get_uv_event_loop(env_, &loop);
425     if (loop == nullptr) {
426         WVLOG_E("get uv event loop failed");
427         return;
428     }
429     work = new (std::nothrow) uv_work_t;
430     if (work == nullptr) {
431         WVLOG_E("new uv work failed");
432         return;
433     }
434     NapiWebCookieManager::WebCookieManagerParam *param =
435         new (std::nothrow) NapiWebCookieManager::WebCookieManagerParam();
436     if (param == nullptr) {
437         WVLOG_E("new WebCookieManagerParam failed");
438         delete work;
439         return;
440     }
441     param->env_ = env_;
442     param->callback_ = callback_;
443     param->deferred_ = deferred_;
444 
445     work->data = reinterpret_cast<void*>(param);
446     int ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, UvJsCallbackThreadWoker);
447     if (ret != 0) {
448         if (param != nullptr) {
449             delete param;
450             param = nullptr;
451         }
452         if (work != nullptr) {
453             delete work;
454             work = nullptr;
455         }
456     }
457 }
458 } // namespace NWeb
459 } // namespace OHOS
460