• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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), &param->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), &param->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