• 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 
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), &param->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), &param->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