• 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     if (cookieManager != nullptr) {
131         cookieContent = cookieManager->ReturnCookie(url);
132     }
133 
134     if (cookieContent == "") {
135         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::INVALID_URL);
136         return nullptr;
137     }
138     napi_create_string_utf8(env, cookieContent.c_str(), cookieContent.length(), &result);
139     return result;
140 }
141 
JsSetCookie(napi_env env,napi_callback_info info)142 napi_value NapiWebCookieManager::JsSetCookie(napi_env env, napi_callback_info info)
143 {
144     napi_value retValue = nullptr;
145     size_t argc = INTEGER_TWO;
146     napi_value argv[INTEGER_TWO] = { 0 };
147 
148     napi_get_cb_info(env, info, &argc, argv, &retValue, nullptr);
149     if (argc != INTEGER_TWO) {
150         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
151         return nullptr;
152     }
153 
154     std::string url;
155     std::string value;
156     if (!GetStringPara(env, argv[INTEGER_ZERO], url)) {
157         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
158         return nullptr;
159     }
160     if (!GetStringPara(env, argv[INTEGER_ONE], value)) {
161         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
162         return nullptr;
163     }
164 
165     napi_value result = nullptr;
166     int isSet = -1;
167 
168     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
169     if (cookieManager != nullptr) {
170         isSet = cookieManager->SetCookie(url, value);
171     }
172     if (isSet == NWebError::INVALID_URL) {
173         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::INVALID_URL);
174         return nullptr;
175     } else if (isSet == NWebError::INVALID_COOKIE_VALUE) {
176         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::INVALID_COOKIE_VALUE);
177         return nullptr;
178     }
179     NAPI_CALL(env, napi_get_undefined(env, &result));
180     return result;
181 }
182 
JsIsCookieAllowed(napi_env env,napi_callback_info info)183 napi_value NapiWebCookieManager::JsIsCookieAllowed(napi_env env, napi_callback_info info)
184 {
185     napi_value result = nullptr;
186     bool accept = true;
187 
188     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
189     if (cookieManager != nullptr) {
190         accept = cookieManager->IsAcceptCookieAllowed();
191     }
192     NAPI_CALL(env, napi_get_boolean(env, accept, &result));
193     return result;
194 }
195 
JsPutAcceptCookieEnabled(napi_env env,napi_callback_info info)196 napi_value NapiWebCookieManager::JsPutAcceptCookieEnabled(napi_env env, napi_callback_info info)
197 {
198     napi_value retValue = nullptr;
199     size_t argc = INTEGER_ONE;
200     napi_value argv[INTEGER_ONE] = { 0 };
201 
202     napi_get_cb_info(env, info, &argc, argv, &retValue, nullptr);
203     if (argc != INTEGER_ONE) {
204         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
205         return nullptr;
206     }
207 
208     bool accept;
209     if (!GetBooleanPara(env, argv[INTEGER_ZERO], accept)) {
210         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
211         return nullptr;
212     }
213 
214     napi_value result = nullptr;
215 
216     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
217     if (cookieManager != nullptr) {
218         cookieManager->PutAcceptCookieEnabled(accept);
219     }
220     NAPI_CALL(env, napi_get_undefined(env, &result));
221     return result;
222 }
223 
JsIsThirdPartyCookieAllowed(napi_env env,napi_callback_info info)224 napi_value NapiWebCookieManager::JsIsThirdPartyCookieAllowed(napi_env env, napi_callback_info info)
225 {
226     napi_value result = nullptr;
227     bool accept = true;
228 
229     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
230     if (cookieManager != nullptr) {
231         accept = cookieManager->IsThirdPartyCookieAllowed();
232     }
233     NAPI_CALL(env, napi_get_boolean(env, accept, &result));
234     return result;
235 }
236 
JsPutAcceptThirdPartyCookieEnabled(napi_env env,napi_callback_info info)237 napi_value NapiWebCookieManager::JsPutAcceptThirdPartyCookieEnabled(napi_env env, napi_callback_info info)
238 {
239     napi_value retValue = nullptr;
240     size_t argc = INTEGER_ONE;
241     napi_value argv[INTEGER_ONE] = { 0 };
242 
243     napi_get_cb_info(env, info, &argc, argv, &retValue, nullptr);
244     if (argc != INTEGER_ONE) {
245         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
246         return nullptr;
247     }
248 
249     bool accept;
250     if (!GetBooleanPara(env, argv[INTEGER_ZERO], accept)) {
251         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
252         return nullptr;
253     }
254 
255     napi_value result = nullptr;
256 
257     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
258     if (cookieManager != nullptr) {
259         cookieManager->PutAcceptThirdPartyCookieEnabled(accept);
260     }
261     NAPI_CALL(env, napi_get_undefined(env, &result));
262     return result;
263 }
264 
JsExistCookie(napi_env env,napi_callback_info info)265 napi_value NapiWebCookieManager::JsExistCookie(napi_env env, napi_callback_info info)
266 {
267     napi_value result = nullptr;
268     bool exist = true;
269 
270     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
271     if (cookieManager != nullptr) {
272         exist = cookieManager->ExistCookies();
273     }
274     NAPI_CALL(env, napi_get_boolean(env, exist, &result));
275     return result;
276 }
277 
JsDeleteEntireCookie(napi_env env,napi_callback_info info)278 napi_value NapiWebCookieManager::JsDeleteEntireCookie(napi_env env, napi_callback_info info)
279 {
280     napi_value result = nullptr;
281 
282     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
283     if (cookieManager != nullptr) {
284         cookieManager->DeleteCookieEntirely(nullptr);
285     }
286     NAPI_CALL(env, napi_get_undefined(env, &result));
287     return result;
288 }
289 
JsDeleteSessionCookie(napi_env env,napi_callback_info info)290 napi_value NapiWebCookieManager::JsDeleteSessionCookie(napi_env env, napi_callback_info info)
291 {
292     napi_value result = nullptr;
293 
294     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
295     if (cookieManager != nullptr) {
296         cookieManager->DeleteSessionCookies(nullptr);
297     }
298     napi_get_undefined(env, &result);
299     return result;
300 }
301 
SaveCookieAsyncCallback(napi_env env,napi_ref jsCallback)302 void SaveCookieAsyncCallback(napi_env env, napi_ref jsCallback)
303 {
304     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
305     if (cookieManager == nullptr) {
306         napi_value jsResult = nullptr;
307         napi_get_null(env, &jsResult);
308         napi_value callback = nullptr;
309         napi_get_reference_value(env, jsCallback, &callback);
310         napi_value callbackResult = nullptr;
311         napi_call_function(env, nullptr, callback, INTEGER_ONE, &jsResult, &callbackResult);
312         napi_delete_reference(env, jsCallback);
313     } else {
314         auto callbackImpl = std::make_shared<OHOS::NWeb::NWebSaveCookieCallbackImpl>(env, jsCallback, nullptr);
315         cookieManager->Store(callbackImpl);
316     }
317 }
318 
SaveCookieAsyncPromise(napi_env env,napi_deferred deferred)319 void SaveCookieAsyncPromise(napi_env env, napi_deferred deferred)
320 {
321     OHOS::NWeb::NWebCookieManager* cookieManager = OHOS::NWeb::NWebHelper::Instance().GetCookieManager();
322     if (cookieManager == nullptr) {
323         napi_value jsResult = nullptr;
324         napi_get_undefined(env, &jsResult);
325         napi_reject_deferred(env, deferred, jsResult);
326     } else {
327         auto callbackImpl = std::make_shared<OHOS::NWeb::NWebSaveCookieCallbackImpl>(env, nullptr, deferred);
328         cookieManager->Store(callbackImpl);
329     }
330 }
331 
JsSaveCookieAsync(napi_env env,napi_callback_info info)332 napi_value NapiWebCookieManager::JsSaveCookieAsync(napi_env env, napi_callback_info info)
333 {
334     napi_value thisVar = nullptr;
335 
336     size_t argc = INTEGER_ONE;
337     size_t argcPromise = INTEGER_ZERO;
338     size_t argcCallback = INTEGER_ONE;
339     napi_value argv[INTEGER_ONE] = {0};
340 
341     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
342     if (argc != argcPromise && argc != argcCallback) {
343         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
344         return nullptr;
345     }
346 
347     napi_value result = nullptr;
348     napi_get_undefined(env, &result);
349 
350     if (argc == argcCallback) {
351         napi_valuetype valueType = napi_null;
352         napi_typeof(env, argv[argcCallback - 1], &valueType);
353         if (valueType != napi_function) {
354             NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR);
355             return nullptr;
356         }
357         napi_ref jsCallback = nullptr;
358         napi_create_reference(env, argv[argcCallback - 1], INTEGER_ONE, &jsCallback);
359 
360         if (jsCallback) {
361             SaveCookieAsyncCallback(env, jsCallback);
362         }
363         return result;
364     }
365 
366     napi_deferred deferred = nullptr;
367     napi_value promise = nullptr;
368     napi_create_promise(env, &deferred, &promise);
369     if (promise && deferred) {
370         SaveCookieAsyncPromise(env, deferred);
371     }
372     return promise;
373 }
374 
UvJsCallbackThreadWoker(uv_work_t * work,int status)375 void NWebSaveCookieCallbackImpl::UvJsCallbackThreadWoker(uv_work_t *work, int status)
376 {
377     if (work == nullptr) {
378         WVLOG_E("uv work is null");
379         return;
380     }
381     NapiWebCookieManager::WebCookieManagerParam *data =
382         reinterpret_cast<NapiWebCookieManager::WebCookieManagerParam*>(work->data);
383     if (data == nullptr) {
384         WVLOG_E("WebCookieManagerParam is null");
385         delete work;
386         work = nullptr;
387         return;
388     }
389     napi_handle_scope scope = nullptr;
390     napi_open_handle_scope(data->env_, &scope);
391     if (scope == nullptr) {
392         return;
393     }
394 
395     if (data->callback_) {
396         napi_value result[INTEGER_ONE] = {0};
397         napi_get_null(data->env_, &result[INTEGER_ZERO]);
398 
399         napi_value onSaveCookieFunc = nullptr;
400         napi_get_reference_value(data->env_, data->callback_, &onSaveCookieFunc);
401         napi_value callbackResult = nullptr;
402         napi_call_function(data->env_, nullptr, onSaveCookieFunc,
403             INTEGER_ONE, &result[INTEGER_ZERO], &callbackResult);
404         napi_delete_reference(data->env_, data->callback_);
405     } else if (data->deferred_) {
406         napi_value jsResult = nullptr;
407         napi_get_undefined(data->env_, &jsResult);
408         napi_resolve_deferred(data->env_, data->deferred_, jsResult);
409     }
410 
411     napi_close_handle_scope(data->env_, scope);
412     delete data;
413     data = nullptr;
414     delete work;
415     work = nullptr;
416 }
417 
OnReceiveValue(bool result)418 void NWebSaveCookieCallbackImpl::OnReceiveValue(bool result)
419 {
420     WVLOG_D("save cookie received result, result = %{public}d", result);
421     uv_loop_s *loop = nullptr;
422     uv_work_t *work = nullptr;
423     napi_get_uv_event_loop(env_, &loop);
424     if (loop == nullptr) {
425         WVLOG_E("get uv event loop failed");
426         return;
427     }
428     work = new (std::nothrow) uv_work_t;
429     if (work == nullptr) {
430         WVLOG_E("new uv work failed");
431         return;
432     }
433     NapiWebCookieManager::WebCookieManagerParam *param =
434         new (std::nothrow) NapiWebCookieManager::WebCookieManagerParam();
435     if (param == nullptr) {
436         WVLOG_E("new WebCookieManagerParam failed");
437         delete work;
438         return;
439     }
440     param->env_ = env_;
441     param->callback_ = callback_;
442     param->deferred_ = deferred_;
443 
444     work->data = reinterpret_cast<void*>(param);
445     int ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, UvJsCallbackThreadWoker);
446     if (ret != 0) {
447         if (param != nullptr) {
448             delete param;
449             param = nullptr;
450         }
451         if (work != nullptr) {
452             delete work;
453             work = nullptr;
454         }
455     }
456 }
457 } // namespace NWeb
458 } // namespace OHOS