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 "web_scheme_handler_request.h"
17
18 #include <securec.h>
19 #include <mutex>
20
21 #include "napi_web_scheme_handler_request.h"
22 #include "napi_parse_utils.h"
23 #include "nweb_napi_scope.h"
24 #include "nweb_log.h"
25 #include "business_error.h"
26 #include "web_errors.h"
27
28 namespace OHOS::NWeb {
29 namespace {
30
31 std::unordered_map<WebSchemeHandler*, const ArkWeb_SchemeHandler*>
32 g_web_scheme_handler_map;
33 std::unordered_map<const ArkWeb_SchemeHandler*, WebSchemeHandler*>
34 g_ark_web_scheme_handler_map;
35 std::mutex g_mutex_for_handler_map;
36
OnRequestStart(const ArkWeb_SchemeHandler * schemeHandler,ArkWeb_ResourceRequest * resourceRequest,const ArkWeb_ResourceHandler * resourceHandler,bool * intercept)37 void OnRequestStart(const ArkWeb_SchemeHandler* schemeHandler,
38 ArkWeb_ResourceRequest* resourceRequest,
39 const ArkWeb_ResourceHandler* resourceHandler,
40 bool* intercept)
41 {
42 WVLOG_D("SchemeHandler OnRequestStart");
43 if (!schemeHandler) {
44 WVLOG_E("OnRequestStart schemeHandler is nullptr");
45 return;
46 }
47 WebSchemeHandler* handler =
48 WebSchemeHandler::GetWebSchemeHandler(schemeHandler);
49 if (!handler) {
50 WVLOG_E("GetWebSchemeHandler failed");
51 return;
52 }
53 handler->RequestStart(resourceRequest, resourceHandler,
54 intercept);
55 }
56
OnRequestStop(const ArkWeb_SchemeHandler * schemeHandler,const ArkWeb_ResourceRequest * resourceRequest)57 void OnRequestStop(const ArkWeb_SchemeHandler* schemeHandler,
58 const ArkWeb_ResourceRequest* resourceRequest)
59 {
60 WVLOG_D("SchemeHandler OnRequestStop");
61 if (!schemeHandler) {
62 WVLOG_E("OnRequestStop schemeHandler is nullptr");
63 return;
64 }
65 WebSchemeHandler* handler =
66 WebSchemeHandler::GetWebSchemeHandler(schemeHandler);
67 if (!handler) {
68 WVLOG_E("GetWebSchemeHandler failed");
69 return;
70 }
71 handler->RequestStop(resourceRequest);
72 }
73 }
74
WebSchemeHandlerRequest(napi_env env)75 WebSchemeHandlerRequest::WebSchemeHandlerRequest(napi_env env)
76 : env_(env)
77 {
78 WVLOG_D("WebSchemeHandlerRequest::WebSchemeHandlerRequest");
79 }
80
WebSchemeHandlerRequest(napi_env env,const ArkWeb_ResourceRequest * request)81 WebSchemeHandlerRequest::WebSchemeHandlerRequest(napi_env env,
82 const ArkWeb_ResourceRequest* request)
83 {
84 env_ = env;
85 OH_ArkWebResourceRequest_GetUrl(request, &url_);
86 OH_ArkWebResourceRequest_GetMethod(request, &method_);
87 OH_ArkWebResourceRequest_GetReferrer(request, &referrer_);
88 isRedirect_ = OH_ArkWebResourceRequest_IsRedirect(request);
89 isMainFrame_ = OH_ArkWebResourceRequest_IsMainFrame(request);
90 hasGesture_ = OH_ArkWebResourceRequest_HasGesture(request);
91 OH_ArkWebResourceRequest_GetHttpBodyStream(request, &stream_);
92 requestResourceType_ = OH_ArkWebResourceRequest_GetResourceType(request);
93 OH_ArkWebResourceRequest_GetFrameUrl(request, &frameUrl_);
94
95 ArkWeb_RequestHeaderList* arkWebHeaderlist = nullptr;
96 OH_ArkWebResourceRequest_GetRequestHeaders(request, &arkWebHeaderlist);
97 if (!arkWebHeaderlist) {
98 WVLOG_E("OH_ArkWebRequestHeaderList_Create failed");
99 return;
100 }
101 int32_t size = OH_ArkWebRequestHeaderList_GetSize(arkWebHeaderlist);
102 if (size <= 0) {
103 WVLOG_E("OH_ArkWebRequestHeaderList_GetSize:%{public}d", size);
104 return;
105 }
106 for (int32_t index = 0; index < size; index++) {
107 char* key;
108 char* value;
109 OH_ArkWebRequestHeaderList_GetHeader(arkWebHeaderlist, index, &key, &value);
110 if (!key || !value) {
111 continue;
112 }
113 std::string strKey(key);
114 std::string strValue(value);
115 headerList_.emplace_back(std::make_pair(strKey, strValue));
116 OH_ArkWeb_ReleaseString(key);
117 OH_ArkWeb_ReleaseString(value);
118 }
119 OH_ArkWebRequestHeaderList_Destroy(arkWebHeaderlist);
120 }
121
~WebSchemeHandlerRequest()122 WebSchemeHandlerRequest::~WebSchemeHandlerRequest()
123 {
124 WVLOG_D("WebSchemeHandlerRequest::~WebSchemeHandlerRequest");
125 OH_ArkWeb_ReleaseString(url_);
126 OH_ArkWeb_ReleaseString(method_);
127 OH_ArkWeb_ReleaseString(referrer_);
128 }
129
GetRequestUrl()130 char* WebSchemeHandlerRequest::GetRequestUrl()
131 {
132 return url_;
133 }
134
GetMethod()135 char* WebSchemeHandlerRequest::GetMethod()
136 {
137 return method_;
138 }
139
GetReferrer()140 char* WebSchemeHandlerRequest::GetReferrer()
141 {
142 return referrer_;
143 }
144
IsRedirect()145 bool WebSchemeHandlerRequest::IsRedirect()
146 {
147 return isRedirect_;
148 }
149
IsMainFrame()150 bool WebSchemeHandlerRequest::IsMainFrame()
151 {
152 return isMainFrame_;
153 }
154
HasGesture()155 bool WebSchemeHandlerRequest::HasGesture()
156 {
157 return hasGesture_;
158 }
159
GetHeader()160 const WebHeaderList& WebSchemeHandlerRequest::GetHeader()
161 {
162 return headerList_;
163 }
164
GetHttpBodyStream()165 ArkWeb_HttpBodyStream* WebSchemeHandlerRequest::GetHttpBodyStream()
166 {
167 return stream_;
168 }
169
GetRequestResourceType()170 int32_t WebSchemeHandlerRequest::GetRequestResourceType()
171 {
172 return requestResourceType_;
173 }
174
GetFrameUrl()175 char* WebSchemeHandlerRequest::GetFrameUrl()
176 {
177 return frameUrl_;
178 }
179
WebSchemeHandlerResponse(napi_env env)180 WebSchemeHandlerResponse::WebSchemeHandlerResponse(napi_env env)
181 : env_(env)
182 {
183 WVLOG_D("WebSchemeHandlerResponse::WebSchemeHandlerResponse");
184 OH_ArkWeb_CreateResponse(&response_);
185 }
186
WebSchemeHandlerResponse(napi_env env,ArkWeb_Response * response)187 WebSchemeHandlerResponse::WebSchemeHandlerResponse(napi_env env,
188 ArkWeb_Response* response)
189 : env_(env), response_(response)
190 {
191 WVLOG_D("WebSchemeHandlerResponse::WebSchemeHandlerResponse");
192 }
193
~WebSchemeHandlerResponse()194 WebSchemeHandlerResponse::~WebSchemeHandlerResponse()
195 {
196 WVLOG_I("WebSchemeHandlerResponse::~WebSchemeHandlerResponse");
197 (void)env_;
198 (void)response_;
199 OH_ArkWeb_DestroyResponse(response_);
200 }
201
GetUrl()202 char* WebSchemeHandlerResponse::GetUrl()
203 {
204 if (!response_) {
205 WVLOG_E("WebSchemeHandlerResponse is nullptr");
206 return nullptr;
207 }
208 char* url;
209 OH_ArkWebResponse_GetUrl(response_, &url);
210 return url;
211 }
212
SetUrl(const char * url)213 int32_t WebSchemeHandlerResponse::SetUrl(const char* url)
214 {
215 return OH_ArkWebResponse_SetUrl(response_, url);
216 }
217
GetStatus() const218 int32_t WebSchemeHandlerResponse::GetStatus() const
219 {
220 return OH_ArkWebResponse_GetStatus(response_);
221 }
222
SetStatus(int32_t status)223 int32_t WebSchemeHandlerResponse::SetStatus(int32_t status)
224 {
225 return OH_ArkWebResponse_SetStatus(response_, status);
226 }
227
GetStatusText()228 char* WebSchemeHandlerResponse::GetStatusText()
229 {
230 if (!response_) {
231 WVLOG_E("WebSchemeHandlerResponse is nullptr");
232 return nullptr;
233 }
234 char *statusText;
235 OH_ArkWebResponse_GetStatusText(response_, &statusText);
236 return statusText;
237 }
238
SetStatusText(const char * statusText)239 int32_t WebSchemeHandlerResponse::SetStatusText(const char* statusText)
240 {
241 return OH_ArkWebResponse_SetStatusText(response_, statusText);
242 }
243
GetMimeType()244 char* WebSchemeHandlerResponse::GetMimeType()
245 {
246 if (!response_) {
247 WVLOG_E("WebSchemeHandlerResponse is nullptr");
248 return nullptr;
249 }
250 char *mimeType;
251 OH_ArkWebResponse_GetMimeType(response_, &mimeType);
252 return mimeType;
253 }
254
SetMimeType(const char * mimeType)255 int32_t WebSchemeHandlerResponse::SetMimeType(const char* mimeType)
256 {
257 return OH_ArkWebResponse_SetMimeType(response_, mimeType);
258 }
259
GetEncoding() const260 char* WebSchemeHandlerResponse::GetEncoding() const
261 {
262 if (!response_) {
263 WVLOG_E("WebSchemeHandlerResponse is nullptr");
264 return nullptr;
265 }
266 char *encoding;
267 OH_ArkWebResponse_GetCharset(response_, &encoding);
268 return encoding;
269 }
270
SetEncoding(const char * encoding)271 int32_t WebSchemeHandlerResponse::SetEncoding(const char* encoding)
272 {
273 return OH_ArkWebResponse_SetCharset(response_, encoding);
274 }
275
GetHeaderByName(const char * name)276 char* WebSchemeHandlerResponse::GetHeaderByName(const char* name)
277 {
278 if (!response_) {
279 WVLOG_E("WebSchemeHandlerResponse is nullptr");
280 return nullptr;
281 }
282 char *value;
283 OH_ArkWebResponse_GetHeaderByName(response_, name, &value);
284 return value;
285 }
286
SetHeaderByName(const char * name,const char * value,bool overwrite)287 int32_t WebSchemeHandlerResponse::SetHeaderByName(
288 const char* name, const char* value, bool overwrite)
289 {
290 return OH_ArkWebResponse_SetHeaderByName(response_, name, value, overwrite);
291 }
292
GetErrorCode()293 int32_t WebSchemeHandlerResponse::GetErrorCode()
294 {
295 return static_cast<int32_t>(OH_ArkWebResponse_GetError(response_));
296 }
297
SetErrorCode(int32_t code)298 int32_t WebSchemeHandlerResponse::SetErrorCode(int32_t code)
299 {
300 return OH_ArkWebResponse_SetError(response_, static_cast<ArkWeb_NetError>(code));
301 }
302
GetArkWebSchemeHandler(WebSchemeHandler * handler)303 const ArkWeb_SchemeHandler* WebSchemeHandler::GetArkWebSchemeHandler(
304 WebSchemeHandler* handler)
305 {
306 std::lock_guard<std::mutex> auto_lock(g_mutex_for_handler_map);
307 auto iter = g_web_scheme_handler_map.find(handler);
308 if (iter == g_web_scheme_handler_map.end()) {
309 return nullptr;
310 }
311 return iter->second;
312 }
313
GetWebSchemeHandler(const ArkWeb_SchemeHandler * handler)314 WebSchemeHandler* WebSchemeHandler::GetWebSchemeHandler(const ArkWeb_SchemeHandler* handler)
315 {
316 std::lock_guard<std::mutex> auto_lock(g_mutex_for_handler_map);
317 auto iter = g_ark_web_scheme_handler_map.find(handler);
318 if (iter == g_ark_web_scheme_handler_map.end()) {
319 return nullptr;
320 }
321 return iter->second;
322 }
323
WebSchemeHandler(napi_env env)324 WebSchemeHandler::WebSchemeHandler(napi_env env)
325 : env_(env),
326 thread_id_(gettid())
327 {
328 ArkWeb_SchemeHandler* handler;
329 OH_ArkWeb_CreateSchemeHandler(&handler);
330 if (!handler) {
331 WVLOG_E("create WebSchemeHandler failed");
332 return;
333 }
334 onRequestStart_ = &OnRequestStart;
335 onRequestStop_ = &OnRequestStop;
336 OH_ArkWebSchemeHandler_SetOnRequestStart(handler, onRequestStart_);
337 OH_ArkWebSchemeHandler_SetOnRequestStop(handler, onRequestStop_);
338 OH_ArkWebSchemeHandler_SetFromEts(handler, true);
339
340 {
341 std::lock_guard<std::mutex> auto_lock(g_mutex_for_handler_map);
342 g_web_scheme_handler_map.insert(std::make_pair(this, handler));
343 g_ark_web_scheme_handler_map.insert(std::make_pair(handler, this));
344 }
345 }
346
~WebSchemeHandler()347 WebSchemeHandler::~WebSchemeHandler()
348 {
349 WVLOG_D("WebSchemeHandler::~WebSchemeHandler");
350 pid_t current_tid = gettid();
351 if (current_tid != thread_id_) {
352 WVLOG_E("~WebSchemeHandler is in wrong thread! %{public}d != %{public}d",
353 current_tid, thread_id_);
354 }
355 napi_delete_reference(env_, request_start_callback_);
356 napi_delete_reference(env_, request_stop_callback_);
357 ArkWeb_SchemeHandler* handler =
358 const_cast<ArkWeb_SchemeHandler*>(GetArkWebSchemeHandler(this));
359 if (!handler) {
360 WVLOG_E("~WebSchemeHandler not found ArkWeb_SchemeHandler");
361 return;
362 }
363 {
364 std::lock_guard<std::mutex> auto_lock(g_mutex_for_handler_map);
365 g_web_scheme_handler_map.erase(this);
366 g_ark_web_scheme_handler_map.erase(handler);
367 }
368 OH_ArkWeb_DestroySchemeHandler(handler);
369 }
370
RequestStart(ArkWeb_ResourceRequest * request,const ArkWeb_ResourceHandler * ArkWeb_ResourceHandler,bool * intercept)371 void WebSchemeHandler::RequestStart(ArkWeb_ResourceRequest* request,
372 const ArkWeb_ResourceHandler* ArkWeb_ResourceHandler,
373 bool* intercept)
374 {
375 NApiScope scope(env_);
376 if (!scope.IsVaild()) {
377 WVLOG_E("scheme handler RequestStart scope is nullptr");
378 return;
379 }
380
381 WVLOG_D("WebSchemeHandler::RequestStart");
382 size_t paramCount = 2;
383 napi_value callbackFunc = nullptr;
384 napi_status status;
385 if (!request_start_callback_) {
386 WVLOG_E("scheme handler onRequestStart nil env");
387 return;
388 }
389 status = napi_get_reference_value(env_, request_start_callback_, &callbackFunc);
390 if (status != napi_ok || callbackFunc == nullptr) {
391 WVLOG_E("scheme handler get onRequestStart func failed.");
392 return;
393 }
394
395 napi_value requestValue[2] = {0};
396 napi_create_object(env_, &requestValue[0]);
397 napi_create_object(env_, &requestValue[1]);
398 WebSchemeHandlerRequest* schemeHandlerRequest = new (std::nothrow) WebSchemeHandlerRequest(env_, request);
399 if (schemeHandlerRequest == nullptr) {
400 WVLOG_E("RequestStart, new schemeHandlerRequest failed");
401 return;
402 }
403 sptr<WebResourceHandler> resourceHandler = new (std::nothrow) WebResourceHandler(env_, ArkWeb_ResourceHandler);
404 if (resourceHandler == nullptr) {
405 WVLOG_E("RequestStart, new resourceHandler failed");
406 delete schemeHandlerRequest;
407 return;
408 }
409 if (OH_ArkWebResourceRequest_SetUserData(request, resourceHandler.GetRefPtr()) != 0) {
410 WVLOG_W("OH_ArkWebResourceRequest_SetUserData failed");
411 } else {
412 resourceHandler->IncStrongRef(nullptr);
413 }
414 napi_wrap(
415 env_, requestValue[0], schemeHandlerRequest,
416 [](napi_env /* env */, void *data, void * /* hint */) {
417 WebSchemeHandlerRequest *request = (WebSchemeHandlerRequest *)data;
418 delete request;
419 }, nullptr, nullptr);
420 NapiWebSchemeHandlerRequest::DefineProperties(env_, &requestValue[0]);
421 napi_wrap(
422 env_, requestValue[1], resourceHandler.GetRefPtr(),
423 [](napi_env /* env */, void *data, void * /* hint */) {
424 static_cast<WebResourceHandler*>(data)->DecStrongRef(data);
425 }, nullptr, nullptr);
426 NapiWebResourceHandler::DefineProperties(env_, &requestValue[1]);
427 resourceHandler->IncStrongRef(nullptr);
428 napi_value result = nullptr;
429 status = napi_call_function(
430 env_, nullptr, callbackFunc, paramCount, requestValue, &result);
431 if (status != napi_status::napi_ok) {
432 WVLOG_W("scheme handler call onRequestStart failed.");
433 }
434 if (!NapiParseUtils::ParseBoolean(env_, result, *intercept)) {
435 WVLOG_E("scheme handler onRequestStart intercept parse failed");
436 *intercept = false;
437 }
438 if (!*intercept) {
439 resourceHandler->SetFinishFlag();
440 resourceHandler->DecStrongRef(resourceHandler);
441 }
442 }
443
RequestStopAfterWorkCb(uv_work_t * work,int status)444 void WebSchemeHandler::RequestStopAfterWorkCb(uv_work_t* work, int status)
445 {
446 WVLOG_D("WebSchemeHandler::RequestStopAfterWorkCb");
447 if (!work) {
448 return;
449 }
450 RequestStopParam *param =
451 reinterpret_cast<struct RequestStopParam*>(work->data);
452 if (!param) {
453 delete work;
454 work = nullptr;
455 return;
456 }
457 NApiScope scope(param->env_);
458 if (!scope.IsVaild()) {
459 delete param;
460 delete work;
461 return;
462 }
463 napi_value callbackFunc = nullptr;
464 napi_status napiStatus;
465 if (!param->callbackRef_) {
466 WVLOG_E("scheme handler onRequestStop nil env");
467 delete param;
468 delete work;
469 return;
470 }
471 napiStatus = napi_get_reference_value(param->env_, param->callbackRef_, &callbackFunc);
472 if (napiStatus != napi_ok || callbackFunc == nullptr) {
473 WVLOG_E("scheme handler get onRequestStop func failed.");
474 delete param;
475 delete work;
476 return;
477 }
478 napi_value requestValue;
479 napi_create_object(param->env_, &requestValue);
480 napi_wrap(
481 param->env_, requestValue, param->request_,
482 [](napi_env /* env */, void *data, void * /* hint */) {
483 WebSchemeHandlerRequest *request = (WebSchemeHandlerRequest *)data;
484 delete request;
485 },
486 nullptr, nullptr);
487 NapiWebSchemeHandlerRequest::DefineProperties(param->env_, &requestValue);
488 napi_value result = nullptr;
489 napiStatus = napi_call_function(
490 param->env_, nullptr, callbackFunc, 1, &requestValue, &result);
491 if (napiStatus != napi_status::napi_ok) {
492 WVLOG_E("scheme handler call onRequestStop failed.");
493 }
494 WebResourceHandler* resourceHandler =
495 reinterpret_cast<WebResourceHandler*>(
496 OH_ArkWebResourceRequest_GetUserData(param->arkWebRequest_));
497 if (resourceHandler) {
498 resourceHandler->SetFinishFlag();
499 resourceHandler->DecStrongRef(resourceHandler);
500 }
501 delete param;
502 param = nullptr;
503 delete work;
504 work = nullptr;
505 }
506
RequestStop(const ArkWeb_ResourceRequest * resourceRequest)507 void WebSchemeHandler::RequestStop(const ArkWeb_ResourceRequest* resourceRequest)
508 {
509 WVLOG_D("WebSchemeHandler::RequestStop");
510 uv_loop_s *loop = nullptr;
511 uv_work_t *work = nullptr;
512 napi_get_uv_event_loop(env_, &loop);
513 if (loop == nullptr) {
514 return;
515 }
516 work = new (std::nothrow) uv_work_t;
517 if (work == nullptr) {
518 return;
519 }
520 RequestStopParam *param = new (std::nothrow) RequestStopParam();
521 if (param == nullptr) {
522 delete work;
523 return;
524 }
525 param->env_ = env_;
526 param->callbackRef_ = request_stop_callback_;
527 param->request_ = new (std::nothrow) WebSchemeHandlerRequest(param->env_, resourceRequest);
528 if (param->request_ == nullptr) {
529 delete work;
530 delete param;
531 return;
532 }
533 param->arkWebRequest_ = resourceRequest;
534 work->data = reinterpret_cast<void*>(param);
535 int ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {},
536 RequestStopAfterWorkCb, uv_qos_user_initiated);
537 if (ret != 0) {
538 if (param != nullptr) {
539 delete param;
540 param = nullptr;
541 }
542 if (work != nullptr) {
543 delete work;
544 work = nullptr;
545 }
546 }
547 }
548
PutRequestStart(napi_env,napi_value callback)549 void WebSchemeHandler::PutRequestStart(napi_env, napi_value callback)
550 {
551 WVLOG_D("WebSchemeHandler::PutRequestStart");
552 napi_status status = napi_create_reference(env_, callback, 1, &request_start_callback_);
553 if (status != napi_status::napi_ok) {
554 WVLOG_E("PutRequestStart create reference failed.");
555 }
556 }
PutRequestStop(napi_env,napi_value callback)557 void WebSchemeHandler::PutRequestStop(napi_env, napi_value callback)
558 {
559 WVLOG_D("WebSchemeHandler::PutRequestStop");
560 napi_status status = napi_create_reference(env_, callback, 1, &request_stop_callback_);
561 if (status != napi_status::napi_ok) {
562 WVLOG_E("PutRequestStop create reference failed.");
563 }
564 }
565
DeleteReference(WebSchemeHandler * schemehandler)566 void WebSchemeHandler::DeleteReference(WebSchemeHandler* schemehandler)
567 {
568 ArkWeb_SchemeHandler* handler =
569 const_cast<ArkWeb_SchemeHandler*>(GetArkWebSchemeHandler(schemehandler));
570 if (handler && schemehandler->delegate_) {
571 napi_delete_reference(schemehandler->env_, schemehandler->delegate_);
572 schemehandler->delegate_ = nullptr;
573 }
574 }
575
WebResourceHandler(napi_env env)576 WebResourceHandler::WebResourceHandler(napi_env env)
577 : env_(env)
578 {
579 WVLOG_D("create WebResourceHandler");
580 }
581
WebResourceHandler(napi_env env,const ArkWeb_ResourceHandler * handler)582 WebResourceHandler::WebResourceHandler(napi_env env, const ArkWeb_ResourceHandler* handler)
583 : handler_(const_cast<ArkWeb_ResourceHandler*>(handler))
584 {
585 WVLOG_D("create WebResourceHandler");
586 env_ = env;
587 }
588
~WebResourceHandler()589 WebResourceHandler::~WebResourceHandler()
590 {
591 WVLOG_D("~WebResourceHandler");
592 }
593
DidReceiveResponse(const ArkWeb_Response * response)594 int32_t WebResourceHandler::DidReceiveResponse(const ArkWeb_Response* response)
595 {
596 if (isFinished_) {
597 return ArkWeb_ErrorCode::ARKWEB_ERROR_UNKNOWN;
598 }
599 return OH_ArkWebResourceHandler_DidReceiveResponse(handler_, response);
600 }
601
DidReceiveResponseBody(const uint8_t * buffer,int64_t buflen)602 int32_t WebResourceHandler::DidReceiveResponseBody(const uint8_t* buffer, int64_t buflen)
603 {
604 if (isFinished_) {
605 return ArkWeb_ErrorCode::ARKWEB_ERROR_UNKNOWN;
606 }
607 return OH_ArkWebResourceHandler_DidReceiveData(handler_, buffer, buflen);
608 }
609
DidFinish()610 int32_t WebResourceHandler::DidFinish()
611 {
612 if (isFinished_) {
613 return ArkWeb_ErrorCode::ARKWEB_ERROR_UNKNOWN;
614 }
615 int32_t ret = OH_ArkWebResourceHandler_DidFinish(handler_);
616 if (ret == 0) {
617 isFinished_ = true;
618 }
619 return ret;
620 }
621
DidFailWithError(ArkWeb_NetError errorCode,bool completeIfNoResponse)622 int32_t WebResourceHandler::DidFailWithError(ArkWeb_NetError errorCode, bool completeIfNoResponse)
623 {
624 if (isFinished_) {
625 return ArkWeb_ErrorCode::ARKWEB_ERROR_UNKNOWN;
626 }
627 int32_t ret = OH_ArkWebResourceHandler_DidFailWithErrorV2(handler_, errorCode, completeIfNoResponse);
628 if (ret == 0) {
629 isFinished_ = true;
630 }
631 return ret;
632 }
633
DestroyArkWebResourceHandler()634 void WebResourceHandler::DestroyArkWebResourceHandler()
635 {
636 if (handler_) {
637 OH_ArkWebResourceHandler_Destroy(handler_);
638 handler_ = nullptr;
639 }
640 }
641
WebHttpBodyStream(napi_env env)642 WebHttpBodyStream::WebHttpBodyStream(napi_env env)
643 {
644 WVLOG_D("WebHttpBodyStream::WebHttpBodyStream");
645 env_ = env;
646 }
647
WebHttpBodyStream(napi_env env,ArkWeb_HttpBodyStream * stream)648 WebHttpBodyStream::WebHttpBodyStream(napi_env env,
649 ArkWeb_HttpBodyStream* stream)
650 {
651 WVLOG_D("WebHttpBodyStream::WebHttpBodyStream");
652 env_ = env;
653 stream_ = stream;
654 if (OH_ArkWebHttpBodyStream_SetUserData(stream_, this) != 0) {
655 WVLOG_E("OH_ArkWebHttpBodyStream_SetUserData failed");
656 return;
657 }
658 if (OH_ArkWebHttpBodyStream_SetReadCallback(stream_,
659 &WebHttpBodyStream::HttpBodyStreamReadCallback) != 0) {
660 WVLOG_E("OH_ArkWebHttpBodyStream_SetReadCallback failed");
661 return;
662 }
663 }
664
~WebHttpBodyStream()665 WebHttpBodyStream::~WebHttpBodyStream()
666 {
667 WVLOG_D("WebHttpBodyStream::~WebHttpBodyStream");
668 if (!stream_) {
669 OH_ArkWebResourceRequest_DestroyHttpBodyStream(stream_);
670 stream_ = nullptr;
671 }
672 }
673
HttpBodyStreamReadCallback(const ArkWeb_HttpBodyStream * httpBodyStream,uint8_t * buffer,int bytesRead)674 void WebHttpBodyStream::HttpBodyStreamReadCallback(
675 const ArkWeb_HttpBodyStream* httpBodyStream, uint8_t* buffer, int bytesRead)
676 {
677 WVLOG_D("WebHttpBodyStream::HttpBodyStreamReadCallback");
678 WebHttpBodyStream* stream = reinterpret_cast<WebHttpBodyStream*>(
679 OH_ArkWebHttpBodyStream_GetUserData(httpBodyStream));
680 if (!stream) {
681 WVLOG_E("OH_ArkWebHttpBodyStream_GetUserData is nullptr");
682 return;
683 }
684 stream->ExecuteRead(buffer, bytesRead);
685 }
686
HttpBodyStreamInitCallback(const ArkWeb_HttpBodyStream * httpBodyStream,ArkWeb_NetError result)687 void WebHttpBodyStream::HttpBodyStreamInitCallback(
688 const ArkWeb_HttpBodyStream* httpBodyStream, ArkWeb_NetError result)
689 {
690 WVLOG_D("WebHttpBodyStream::HttpBodyStreamInitCallback");
691 WebHttpBodyStream* stream = reinterpret_cast<WebHttpBodyStream*>(
692 OH_ArkWebHttpBodyStream_GetUserData(httpBodyStream));
693 if (!stream) {
694 WVLOG_E("OH_ArkWebHttpBodyStream_GetUserData is nullptr");
695 return;
696 }
697 stream->ExecuteInit(result);
698 }
699
Init(napi_ref jsCallback,napi_deferred deferred)700 void WebHttpBodyStream::Init(napi_ref jsCallback, napi_deferred deferred)
701 {
702 if (!jsCallback && !deferred) {
703 WVLOG_E("WebHttpBodyStream::InitCallback callback is nullptr");
704 return;
705 }
706 if (jsCallback) {
707 initJsCallback_ = std::move(jsCallback);
708 }
709 if (deferred) {
710 initDeferred_ = std::move(deferred);
711 }
712 int ret = OH_ArkWebHttpBodyStream_Init(stream_,
713 &WebHttpBodyStream::HttpBodyStreamInitCallback);
714 if (ret != 0) {
715 WVLOG_E("OH_ArkWebHttpBodyStream_Init failed");
716 return;
717 }
718 }
719
Read(int bufLen,napi_ref jsCallback,napi_deferred deferred)720 void WebHttpBodyStream::Read(int bufLen, napi_ref jsCallback, napi_deferred deferred)
721 {
722 WVLOG_D("WebHttpBodyStream::Read");
723 if (!jsCallback && !deferred) {
724 WVLOG_E("WebHttpBodyStream::Read callback is nullptr");
725 return;
726 }
727 if (bufLen <= 0) {
728 return;
729 }
730 if (jsCallback) {
731 readJsCallback_ = std::move(jsCallback);
732 }
733 if (deferred) {
734 readDeferred_ = std::move(deferred);
735 }
736 uint8_t* buffer = new (std::nothrow) uint8_t[bufLen];
737 if (buffer == nullptr) {
738 return;
739 }
740 if (!stream_) {
741 delete[] buffer;
742 buffer = nullptr;
743 return;
744 }
745 OH_ArkWebHttpBodyStream_Read(stream_, buffer, bufLen);
746 }
747
DeleteInitJsCallbackRef()748 void WebHttpBodyStream::DeleteInitJsCallbackRef()
749 {
750 if (!env_) {
751 return;
752 }
753 if (initJsCallback_) {
754 napi_delete_reference(env_, initJsCallback_);
755 initJsCallback_ = nullptr;
756 }
757 }
758
ExecuteInit(ArkWeb_NetError result)759 void WebHttpBodyStream::ExecuteInit(ArkWeb_NetError result)
760 {
761 WVLOG_D("WebHttpBodyStream::ExecuteInit");
762 if (!env_) {
763 return ;
764 }
765 InitParam *param = new (std::nothrow) InitParam {
766 .env = env_,
767 .asyncWork = nullptr,
768 .deferred = initDeferred_,
769 .callbackRef = initJsCallback_,
770 .result = result,
771 };
772 if (param == nullptr) {
773 return;
774 }
775 napi_value resourceName = nullptr;
776 if (napi_create_string_utf8(env_, __func__, NAPI_AUTO_LENGTH, &resourceName) != napi_status::napi_ok) {
777 DeleteInitJsCallbackRef();
778 delete param;
779 return;
780 }
781 if (napi_create_async_work(env_, nullptr, resourceName,
782 [](napi_env env, void *data) {},
783 ExecuteInitComplete, static_cast<void *>(param), ¶m->asyncWork) != napi_status::napi_ok) {
784 DeleteInitJsCallbackRef();
785 delete param;
786 return;
787 }
788 if (napi_queue_async_work_with_qos(env_, param->asyncWork, napi_qos_user_initiated) != napi_status::napi_ok) {
789 napi_delete_async_work(env_, param->asyncWork);
790 DeleteInitJsCallbackRef();
791 delete param;
792 }
793 }
794
ExecuteInitComplete(napi_env env,napi_status status,void * data)795 void WebHttpBodyStream::ExecuteInitComplete(napi_env env, napi_status status, void* data)
796 {
797 WVLOG_D("WebHttpBodyStream::ExecuteInitComplete");
798 InitParam* param = static_cast<InitParam*>(data);
799 if (!param) {
800 return;
801 }
802 NApiScope scope(env);
803 if (!scope.IsVaild()) {
804 delete param;
805 return;
806 }
807 napi_value result[INTEGER_ONE] = {0};
808 if (param->result != 0) {
809 result[INTEGER_ZERO] = NWebError::BusinessError::CreateError(
810 env, NWebError::HTTP_BODY_STREAN_INIT_FAILED);
811 } else {
812 napi_get_null(env, &result[INTEGER_ZERO]);
813 }
814 if (param->callbackRef) {
815 napi_value callback = nullptr;
816 napi_get_reference_value(env, param->callbackRef, &callback);
817 napi_call_function(env, nullptr, callback, INTEGER_ONE, &result[INTEGER_ZERO], nullptr);
818 napi_delete_reference(env, param->callbackRef);
819 } else if (param->deferred) {
820 if (param->result != 0) {
821 napi_reject_deferred(env, param->deferred, result[INTEGER_ZERO]);
822 } else {
823 napi_resolve_deferred(env, param->deferred, result[INTEGER_ZERO]);
824 }
825 }
826 napi_delete_async_work(env, param->asyncWork);
827 delete param;
828 }
829
ExecuteReadComplete(napi_env env,napi_status status,void * data)830 void WebHttpBodyStream::ExecuteReadComplete(napi_env env, napi_status status, void* data)
831 {
832 WVLOG_D("WebHttpBodyStream::ExecuteReadComplete");
833 ReadParam* param = static_cast<ReadParam*>(data);
834 if (!param) {
835 return;
836 }
837 NApiScope scope(env);
838 if (!scope.IsVaild()) {
839 if (param->buffer) {
840 delete param->buffer;
841 }
842 delete param;
843 return;
844 }
845 napi_value result[INTEGER_ONE] = {0};
846 void *bufferData = nullptr;
847 napi_create_arraybuffer(env, param->bytesRead, &bufferData, &result[INTEGER_ZERO]);
848 if (memcpy_s(bufferData, param->bytesRead, param->buffer, param->bytesRead) != 0 &&
849 param->bytesRead > 0) {
850 WVLOG_W("WebHttpBodyStream::ExecuteRead memcpy failed");
851 }
852 if (param->buffer) {
853 delete param->buffer;
854 }
855 if (param->callbackRef) {
856 napi_value callback = nullptr;
857 napi_get_reference_value(env, param->callbackRef, &callback);
858 napi_call_function(env, nullptr, callback, INTEGER_ONE, &result[INTEGER_ZERO], nullptr);
859 napi_delete_reference(env, param->callbackRef);
860 } else if (param->deferred) {
861 napi_resolve_deferred(env, param->deferred, result[INTEGER_ZERO]);
862 }
863 napi_delete_async_work(env, param->asyncWork);
864 delete param;
865 }
866
DeleteReadJsCallbackRef()867 void WebHttpBodyStream::DeleteReadJsCallbackRef()
868 {
869 if (!env_) {
870 return;
871 }
872 if (readJsCallback_) {
873 napi_delete_reference(env_, readJsCallback_);
874 readJsCallback_ = nullptr;
875 }
876 }
877
ExecuteRead(uint8_t * buffer,int bytesRead)878 void WebHttpBodyStream::ExecuteRead(uint8_t* buffer, int bytesRead)
879 {
880 if (!env_) {
881 return;
882 }
883 ReadParam *param = new (std::nothrow) ReadParam {
884 .env = env_,
885 .asyncWork = nullptr,
886 .deferred = readDeferred_,
887 .callbackRef = readJsCallback_,
888 .buffer = buffer,
889 .bytesRead = bytesRead,
890 };
891 if (param == nullptr) {
892 return;
893 }
894 napi_value resourceName = nullptr;
895 if (napi_create_string_utf8(env_, __func__, NAPI_AUTO_LENGTH, &resourceName) != napi_status::napi_ok) {
896 DeleteReadJsCallbackRef();
897 delete param;
898 return;
899 }
900 if (napi_create_async_work(env_, nullptr, resourceName,
901 [](napi_env env, void *data) {},
902 ExecuteReadComplete, static_cast<void *>(param), ¶m->asyncWork) != napi_status::napi_ok) {
903 DeleteReadJsCallbackRef();
904 delete param;
905 return;
906 }
907 if (napi_queue_async_work_with_qos(env_, param->asyncWork, napi_qos_user_initiated) != napi_status::napi_ok) {
908 napi_delete_async_work(env_, param->asyncWork);
909 DeleteReadJsCallbackRef();
910 delete param;
911 }
912 }
913
914
GetPostion() const915 uint64_t WebHttpBodyStream::GetPostion() const
916 {
917 return OH_ArkWebHttpBodyStream_GetPosition(stream_);
918 }
919
GetSize() const920 uint64_t WebHttpBodyStream::GetSize() const
921 {
922 return OH_ArkWebHttpBodyStream_GetSize(stream_);
923 }
924
IsChunked() const925 bool WebHttpBodyStream::IsChunked() const
926 {
927 return OH_ArkWebHttpBodyStream_IsChunked(stream_);
928 }
929
IsEof()930 bool WebHttpBodyStream::IsEof()
931 {
932 return OH_ArkWebHttpBodyStream_IsEof(stream_);
933 }
934
IsInMemory()935 bool WebHttpBodyStream::IsInMemory()
936 {
937 return OH_ArkWebHttpBodyStream_IsInMemory(stream_);
938 }
939 }
940