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