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
WebResourceHandler(napi_env env)566 WebResourceHandler::WebResourceHandler(napi_env env)
567 : env_(env)
568 {
569 WVLOG_D("create WebResourceHandler");
570 }
571
WebResourceHandler(napi_env env,const ArkWeb_ResourceHandler * handler)572 WebResourceHandler::WebResourceHandler(napi_env env, const ArkWeb_ResourceHandler* handler)
573 : handler_(const_cast<ArkWeb_ResourceHandler*>(handler))
574 {
575 WVLOG_D("create WebResourceHandler");
576 env_ = env;
577 }
578
~WebResourceHandler()579 WebResourceHandler::~WebResourceHandler()
580 {
581 WVLOG_D("~WebResourceHandler");
582 }
583
DidReceiveResponse(const ArkWeb_Response * response)584 int32_t WebResourceHandler::DidReceiveResponse(const ArkWeb_Response* response)
585 {
586 if (isFinished_) {
587 return ArkWeb_ErrorCode::ARKWEB_ERROR_UNKNOWN;
588 }
589 return OH_ArkWebResourceHandler_DidReceiveResponse(handler_, response);
590 }
591
DidReceiveResponseBody(const uint8_t * buffer,int64_t buflen)592 int32_t WebResourceHandler::DidReceiveResponseBody(const uint8_t* buffer, int64_t buflen)
593 {
594 if (isFinished_) {
595 return ArkWeb_ErrorCode::ARKWEB_ERROR_UNKNOWN;
596 }
597 return OH_ArkWebResourceHandler_DidReceiveData(handler_, buffer, buflen);
598 }
599
DidFinish()600 int32_t WebResourceHandler::DidFinish()
601 {
602 if (isFinished_) {
603 return ArkWeb_ErrorCode::ARKWEB_ERROR_UNKNOWN;
604 }
605 int32_t ret = OH_ArkWebResourceHandler_DidFinish(handler_);
606 if (ret == 0) {
607 isFinished_ = true;
608 }
609 return ret;
610 }
611
DidFailWithError(ArkWeb_NetError errorCode)612 int32_t WebResourceHandler::DidFailWithError(ArkWeb_NetError errorCode)
613 {
614 if (isFinished_) {
615 return ArkWeb_ErrorCode::ARKWEB_ERROR_UNKNOWN;
616 }
617 int32_t ret = OH_ArkWebResourceHandler_DidFailWithError(handler_, errorCode);
618 if (ret == 0) {
619 isFinished_ = true;
620 }
621 return ret;
622 }
623
DestoryArkWebResourceHandler()624 void WebResourceHandler::DestoryArkWebResourceHandler()
625 {
626 if (handler_) {
627 OH_ArkWebResourceHandler_Destroy(handler_);
628 handler_ = nullptr;
629 }
630 }
631
WebHttpBodyStream(napi_env env)632 WebHttpBodyStream::WebHttpBodyStream(napi_env env)
633 {
634 WVLOG_D("WebHttpBodyStream::WebHttpBodyStream");
635 env_ = env;
636 }
637
WebHttpBodyStream(napi_env env,ArkWeb_HttpBodyStream * stream)638 WebHttpBodyStream::WebHttpBodyStream(napi_env env,
639 ArkWeb_HttpBodyStream* stream)
640 {
641 WVLOG_D("WebHttpBodyStream::WebHttpBodyStream");
642 env_ = env;
643 stream_ = stream;
644 if (OH_ArkWebHttpBodyStream_SetUserData(stream_, this) != 0) {
645 WVLOG_E("OH_ArkWebHttpBodyStream_SetUserData failed");
646 return;
647 }
648 if (OH_ArkWebHttpBodyStream_SetReadCallback(stream_,
649 &WebHttpBodyStream::HttpBodyStreamReadCallback) != 0) {
650 WVLOG_E("OH_ArkWebHttpBodyStream_SetReadCallback failed");
651 return;
652 }
653 }
654
~WebHttpBodyStream()655 WebHttpBodyStream::~WebHttpBodyStream()
656 {
657 WVLOG_D("WebHttpBodyStream::~WebHttpBodyStream");
658 if (!stream_) {
659 OH_ArkWebResourceRequest_DestroyHttpBodyStream(stream_);
660 stream_ = nullptr;
661 }
662 }
663
HttpBodyStreamReadCallback(const ArkWeb_HttpBodyStream * httpBodyStream,uint8_t * buffer,int bytesRead)664 void WebHttpBodyStream::HttpBodyStreamReadCallback(
665 const ArkWeb_HttpBodyStream* httpBodyStream, uint8_t* buffer, int bytesRead)
666 {
667 WVLOG_D("WebHttpBodyStream::HttpBodyStreamReadCallback");
668 WebHttpBodyStream* stream = reinterpret_cast<WebHttpBodyStream*>(
669 OH_ArkWebHttpBodyStream_GetUserData(httpBodyStream));
670 if (!stream) {
671 WVLOG_E("OH_ArkWebHttpBodyStream_GetUserData is nullptr");
672 return;
673 }
674 stream->ExecuteRead(buffer, bytesRead);
675 }
676
HttpBodyStreamInitCallback(const ArkWeb_HttpBodyStream * httpBodyStream,ArkWeb_NetError result)677 void WebHttpBodyStream::HttpBodyStreamInitCallback(
678 const ArkWeb_HttpBodyStream* httpBodyStream, ArkWeb_NetError result)
679 {
680 WVLOG_D("WebHttpBodyStream::HttpBodyStreamInitCallback");
681 WebHttpBodyStream* stream = reinterpret_cast<WebHttpBodyStream*>(
682 OH_ArkWebHttpBodyStream_GetUserData(httpBodyStream));
683 if (!stream) {
684 WVLOG_E("OH_ArkWebHttpBodyStream_GetUserData is nullptr");
685 return;
686 }
687 stream->ExecuteInit(result);
688 }
689
Init(napi_ref jsCallback,napi_deferred deferred)690 void WebHttpBodyStream::Init(napi_ref jsCallback, napi_deferred deferred)
691 {
692 if (!jsCallback && !deferred) {
693 WVLOG_E("WebHttpBodyStream::InitCallback callback is nullptr");
694 return;
695 }
696 if (jsCallback) {
697 initJsCallback_ = std::move(jsCallback);
698 }
699 if (deferred) {
700 initDeferred_ = std::move(deferred);
701 }
702 int ret = OH_ArkWebHttpBodyStream_Init(stream_,
703 &WebHttpBodyStream::HttpBodyStreamInitCallback);
704 if (ret != 0) {
705 WVLOG_E("OH_ArkWebHttpBodyStream_Init failed");
706 return;
707 }
708 }
709
Read(int bufLen,napi_ref jsCallback,napi_deferred deferred)710 void WebHttpBodyStream::Read(int bufLen, napi_ref jsCallback, napi_deferred deferred)
711 {
712 WVLOG_D("WebHttpBodyStream::Read");
713 if (!jsCallback && !deferred) {
714 WVLOG_E("WebHttpBodyStream::Read callback is nullptr");
715 return;
716 }
717 if (bufLen <= 0) {
718 return;
719 }
720 if (jsCallback) {
721 readJsCallback_ = std::move(jsCallback);
722 }
723 if (deferred) {
724 readDeferred_ = std::move(deferred);
725 }
726 uint8_t* buffer = new (std::nothrow) uint8_t[bufLen];
727 if (buffer == nullptr) {
728 return;
729 }
730 OH_ArkWebHttpBodyStream_Read(stream_, buffer, bufLen);
731 }
732
ExecuteInit(ArkWeb_NetError result)733 void WebHttpBodyStream::ExecuteInit(ArkWeb_NetError result)
734 {
735 WVLOG_D("WebHttpBodyStream::ExecuteInit");
736 if (!env_) {
737 return ;
738 }
739 InitParam *param = new (std::nothrow) InitParam {
740 .env = env_,
741 .asyncWork = nullptr,
742 .deferred = initDeferred_,
743 .callbackRef = initJsCallback_,
744 .result = result,
745 };
746 if (param == nullptr) {
747 return;
748 }
749 napi_value resourceName = nullptr;
750 NAPI_CALL_RETURN_VOID(env_, napi_create_string_utf8(env_, __func__, NAPI_AUTO_LENGTH, &resourceName));
751 NAPI_CALL_RETURN_VOID(env_, napi_create_async_work(env_, nullptr, resourceName,
752 [](napi_env env, void *data) {},
753 ExecuteInitComplete, static_cast<void *>(param), ¶m->asyncWork));
754 NAPI_CALL_RETURN_VOID(env_, napi_queue_async_work_with_qos(env_, param->asyncWork, napi_qos_user_initiated));
755 }
756
ExecuteInitComplete(napi_env env,napi_status status,void * data)757 void WebHttpBodyStream::ExecuteInitComplete(napi_env env, napi_status status, void* data)
758 {
759 WVLOG_D("WebHttpBodyStream::ExecuteInitComplete");
760 InitParam* param = static_cast<InitParam*>(data);
761 if (!param) {
762 return;
763 }
764 NApiScope scope(env);
765 if (!scope.IsVaild()) {
766 delete param;
767 return;
768 }
769 napi_value result[INTEGER_ONE] = {0};
770 if (param->result != 0) {
771 result[INTEGER_ZERO] = NWebError::BusinessError::CreateError(
772 env, NWebError::HTTP_BODY_STREAN_INIT_FAILED);
773 } else {
774 napi_get_null(env, &result[INTEGER_ZERO]);
775 }
776 if (param->callbackRef) {
777 napi_value callback = nullptr;
778 napi_get_reference_value(env, param->callbackRef, &callback);
779 napi_call_function(env, nullptr, callback, INTEGER_ONE, &result[INTEGER_ZERO], nullptr);
780 napi_delete_reference(env, param->callbackRef);
781 } else if (param->deferred) {
782 if (param->result != 0) {
783 napi_reject_deferred(env, param->deferred, result[INTEGER_ZERO]);
784 } else {
785 napi_resolve_deferred(env, param->deferred, result[INTEGER_ZERO]);
786 }
787 }
788 napi_delete_async_work(env, param->asyncWork);
789 delete param;
790 }
791
ExecuteReadComplete(napi_env env,napi_status status,void * data)792 void WebHttpBodyStream::ExecuteReadComplete(napi_env env, napi_status status, void* data)
793 {
794 WVLOG_D("WebHttpBodyStream::ExecuteReadComplete");
795 ReadParam* param = static_cast<ReadParam*>(data);
796 if (!param) {
797 return;
798 }
799 NApiScope scope(env);
800 if (!scope.IsVaild()) {
801 if (param->buffer) {
802 delete param->buffer;
803 }
804 delete param;
805 return;
806 }
807 napi_value result[INTEGER_ONE] = {0};
808 void *bufferData = nullptr;
809 napi_create_arraybuffer(env, param->bytesRead, &bufferData, &result[INTEGER_ZERO]);
810 if (memcpy_s(bufferData, param->bytesRead, param->buffer, param->bytesRead) != 0 &&
811 param->bytesRead > 0) {
812 WVLOG_W("WebHttpBodyStream::ExecuteRead memcpy failed");
813 }
814 if (param->buffer) {
815 delete param->buffer;
816 }
817 if (param->callbackRef) {
818 napi_value callback = nullptr;
819 napi_get_reference_value(env, param->callbackRef, &callback);
820 napi_call_function(env, nullptr, callback, INTEGER_ONE, &result[INTEGER_ZERO], nullptr);
821 napi_delete_reference(env, param->callbackRef);
822 } else if (param->deferred) {
823 napi_resolve_deferred(env, param->deferred, result[INTEGER_ZERO]);
824 }
825 napi_delete_async_work(env, param->asyncWork);
826 delete param;
827 }
828
ExecuteRead(uint8_t * buffer,int bytesRead)829 void WebHttpBodyStream::ExecuteRead(uint8_t* buffer, int bytesRead)
830 {
831 if (!env_) {
832 return;
833 }
834 ReadParam *param = new (std::nothrow) ReadParam {
835 .env = env_,
836 .asyncWork = nullptr,
837 .deferred = readDeferred_,
838 .callbackRef = readJsCallback_,
839 .buffer = buffer,
840 .bytesRead = bytesRead,
841 };
842 if (param == nullptr) {
843 return;
844 }
845 napi_value resourceName = nullptr;
846 NAPI_CALL_RETURN_VOID(env_, napi_create_string_utf8(env_, __func__, NAPI_AUTO_LENGTH, &resourceName));
847 NAPI_CALL_RETURN_VOID(env_, napi_create_async_work(env_, nullptr, resourceName,
848 [](napi_env env, void *data) {},
849 ExecuteReadComplete, static_cast<void *>(param), ¶m->asyncWork));
850 NAPI_CALL_RETURN_VOID(env_,
851 napi_queue_async_work_with_qos(env_, param->asyncWork, napi_qos_user_initiated));
852 }
853
GetPostion() const854 uint64_t WebHttpBodyStream::GetPostion() const
855 {
856 return OH_ArkWebHttpBodyStream_GetPosition(stream_);
857 }
858
GetSize() const859 uint64_t WebHttpBodyStream::GetSize() const
860 {
861 return OH_ArkWebHttpBodyStream_GetSize(stream_);
862 }
863
IsChunked() const864 bool WebHttpBodyStream::IsChunked() const
865 {
866 return OH_ArkWebHttpBodyStream_IsChunked(stream_);
867 }
868
IsEof()869 bool WebHttpBodyStream::IsEof()
870 {
871 return OH_ArkWebHttpBodyStream_IsEof(stream_);
872 }
873
IsInMemory()874 bool WebHttpBodyStream::IsInMemory()
875 {
876 return OH_ArkWebHttpBodyStream_IsInMemory(stream_);
877 }
878 }
879