/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "web_scheme_handler_request.h" #include "webview_javascript_execute_callback.h" #include "native_arkweb_utils.h" #include "native_interface_arkweb.h" #include "cj_common_ffi.h" #include "application_context.h" #include "webview_log.h" #include "webview_utils.h" #include "nweb_store_web_archive_callback.h" namespace OHOS::Webview { int WebSchemeHandlerRequestImpl::GetRequestResourceType() { return requestResourceType_; } bool WebSchemeHandlerRequestImpl::HasGesture() { return hasGesture_; } bool WebSchemeHandlerRequestImpl::IsMainFrame() { return isMainFrame_; } bool WebSchemeHandlerRequestImpl::IsRedirect() { return isRedirect_; } std::string WebSchemeHandlerRequestImpl::GetRequestUrl() { return url_; } std::string WebSchemeHandlerRequestImpl::GetMethod() { return method_; } std::string WebSchemeHandlerRequestImpl::GetReferrer() { return referrer_; } std::string WebSchemeHandlerRequestImpl::GetFrameUrl() { return frameUrl_; } const WebHeaderList& WebSchemeHandlerRequestImpl::GetHeader() { return headerList_; } ArkWeb_HttpBodyStream* WebSchemeHandlerRequestImpl::GetHttpBodyStream() { return stream_; } void WebHttpBodyStreamImpl::HttpBodyStreamInitCallback( const ArkWeb_HttpBodyStream* httpBodyStream, ArkWeb_NetError result) { WEBVIEWLOGD("WebHttpBodyStream::HttpBodyStreamInitCallback"); WebHttpBodyStreamImpl* stream = reinterpret_cast( OH_ArkWebHttpBodyStream_GetUserData(httpBodyStream)); if (!stream) { WEBVIEWLOGD("OH_ArkWebHttpBodyStream_GetUserData is nullptr"); return; } } int32_t WebHttpBodyStreamImpl::initialize() { int ret = OH_ArkWebHttpBodyStream_Init(stream_, &WebHttpBodyStreamImpl::HttpBodyStreamInitCallback); if (ret != 0) { WEBVIEWLOGD("OH_ArkWebHttpBodyStream_Init failed"); return NWebError::HTTP_BODY_STREAN_INIT_FAILED; } return NWebError::NO_ERROR; } int32_t WebHttpBodyStreamImpl::Read(int32_t bufLen) { WEBVIEWLOGD("WebHttpBodyStreamImpl::Read"); if (bufLen <= 0) { WEBVIEWLOGE("WebHttpBodyStreamImpl::Read failed: bufLen is illegal"); return NWebError::PARAM_CHECK_ERROR; } uint8_t* buffer = new (std::nothrow) uint8_t[bufLen]; if (buffer == nullptr) { WEBVIEWLOGE("WebHttpBodyStreamImpl::Read failed: buffer is null"); return NWebError::PARAM_CHECK_ERROR; } OH_ArkWebHttpBodyStream_Read(stream_, buffer, bufLen); delete[] buffer; return NWebError::NO_ERROR; } uint64_t WebHttpBodyStreamImpl::GetPostion() { return OH_ArkWebHttpBodyStream_GetPosition(stream_); } uint64_t WebHttpBodyStreamImpl::GetSize() { return OH_ArkWebHttpBodyStream_GetSize(stream_); } bool WebHttpBodyStreamImpl::IsChunked() { return OH_ArkWebHttpBodyStream_IsChunked(stream_); } bool WebHttpBodyStreamImpl::IsEof() { return OH_ArkWebHttpBodyStream_IsEof(stream_); } bool WebHttpBodyStreamImpl::IsInMemory() { return OH_ArkWebHttpBodyStream_IsInMemory(stream_); } int32_t WebResourceHandlerImpl::DidReceiveResponse(const ArkWeb_Response* response) { if (isFinished_) { return ArkWeb_ErrorCode::ARKWEB_ERROR_UNKNOWN; } return OH_ArkWebResourceHandler_DidReceiveResponse(handler_, response); } int32_t WebResourceHandlerImpl::DidReceiveResponseBody(const uint8_t* buffer, int64_t buflen) { if (isFinished_) { return ArkWeb_ErrorCode::ARKWEB_ERROR_UNKNOWN; } return OH_ArkWebResourceHandler_DidReceiveData(handler_, buffer, buflen); } int32_t WebResourceHandlerImpl::DidFinish() { if (isFinished_) { return ArkWeb_ErrorCode::ARKWEB_ERROR_UNKNOWN; } int32_t ret = OH_ArkWebResourceHandler_DidFinish(handler_); if (ret == 0) { isFinished_ = true; } return ret; } int32_t WebResourceHandlerImpl::DidFailWithError(ArkWeb_NetError errorCode) { if (isFinished_) { return ArkWeb_ErrorCode::ARKWEB_ERROR_UNKNOWN; } int32_t ret = OH_ArkWebResourceHandler_DidFailWithError(handler_, errorCode); if (ret == 0) { isFinished_ = true; } return ret; } void WebResourceHandlerImpl::DestroyArkWebResourceHandler() { if (handler_) { OH_ArkWebResourceHandler_Destroy(handler_); handler_ = nullptr; } } void OnRequestStart( const ArkWeb_SchemeHandler* schemeHandler, ArkWeb_ResourceRequest* resourceRequest, const ArkWeb_ResourceHandler* resourceHandler, bool* intercept) { WEBVIEWLOGD("SchemeHandler OnRequestStart"); if (!schemeHandler) { WEBVIEWLOGD("OnRequestStart schemeHandler is nullptr"); return; } WebSchemeHandlerImpl* handler = WebSchemeHandlerImpl::GetWebSchemeHandler(schemeHandler); if (!handler) { WEBVIEWLOGD("GetWebSchemeHandler failed"); return; } handler->RequestStart(resourceRequest, resourceHandler, intercept); } void OnRequestStop( const ArkWeb_SchemeHandler* schemeHandler, const ArkWeb_ResourceRequest* resourceRequest) { WEBVIEWLOGD("SchemeHandler OnRequestStop"); if (!schemeHandler) { WEBVIEWLOGD("OnRequestStop schemeHandler is nullptr"); return; } WebSchemeHandlerImpl* handler = WebSchemeHandlerImpl::GetWebSchemeHandler(schemeHandler); if (!handler) { WEBVIEWLOGD("GetWebSchemeHandler failed"); return; } handler->RequestStop(resourceRequest); } std::unordered_map WebSchemeHandlerImpl::webSchemeHandlerMap_; std::unordered_map WebSchemeHandlerImpl::arkWebSchemeHandlerMap_; const ArkWeb_SchemeHandler* WebSchemeHandlerImpl::GetArkWebSchemeHandler( WebSchemeHandlerImpl* handler) { return WebSchemeHandlerImpl::webSchemeHandlerMap_.find(handler) != WebSchemeHandlerImpl::webSchemeHandlerMap_.end() ? WebSchemeHandlerImpl::webSchemeHandlerMap_[handler] : nullptr; } WebSchemeHandlerImpl* WebSchemeHandlerImpl::GetWebSchemeHandler(const ArkWeb_SchemeHandler* handler) { return WebSchemeHandlerImpl::arkWebSchemeHandlerMap_.find(handler) != WebSchemeHandlerImpl::arkWebSchemeHandlerMap_.end() ? WebSchemeHandlerImpl::arkWebSchemeHandlerMap_[handler] : nullptr; } WebSchemeHandlerImpl::WebSchemeHandlerImpl() { ArkWeb_SchemeHandler* handler; OH_ArkWeb_CreateSchemeHandler(&handler); if (!handler) { WEBVIEWLOGD("create WebSchemeHandler failed"); return; } onRequestStart_ = &OnRequestStart; onRequestStop_ = &OnRequestStop; OH_ArkWebSchemeHandler_SetOnRequestStart(handler, onRequestStart_); OH_ArkWebSchemeHandler_SetOnRequestStop(handler, onRequestStop_); OH_ArkWebSchemeHandler_SetFromEts(handler, true); webSchemeHandlerMap_.insert(std::make_pair(this, handler)); arkWebSchemeHandlerMap_.insert(std::make_pair(handler, this)); } WebSchemeHandlerImpl::~WebSchemeHandlerImpl() { WEBVIEWLOGD("WebSchemeHandler::~WebSchemeHandler"); ArkWeb_SchemeHandler* handler = const_cast(GetArkWebSchemeHandler(this)); if (!handler) { WEBVIEWLOGD("~WebSchemeHandler not found ArkWeb_SchemeHandler"); return; } webSchemeHandlerMap_.erase(this); arkWebSchemeHandlerMap_.erase(handler); OH_ArkWeb_DestroySchemeHandler(handler); } void WebSchemeHandlerImpl::RequestStart( ArkWeb_ResourceRequest* request, const ArkWeb_ResourceHandler* ArkWeb_ResourceHandler, bool* intercept) { WEBVIEWLOGI("[SchemeHandler] WebSchemeHandlerImpl::RequestStart"); if (!request_start_callback_) { WEBVIEWLOGE("[SchemeHandler] :RequestStart not exists."); return; } sptr schemeHandlerRequest = FFIData::Create(request); if (schemeHandlerRequest == nullptr) { WEBVIEWLOGD("RequestStart, new schemeHandlerRequest failed"); return; } sptr resourceHandler = FFIData::Create(ArkWeb_ResourceHandler); if (resourceHandler == nullptr) { WEBVIEWLOGD("RequestStart, new resourceHandler failed"); return; } if (OH_ArkWebResourceRequest_SetUserData(request, resourceHandler) != 0) { WEBVIEWLOGD("OH_ArkWebResourceRequest_SetUserData failed"); } else { resourceHandler->IncStrongRef(nullptr); } *intercept = request_start_callback_(schemeHandlerRequest->GetID(), resourceHandler->GetID()); if (!*intercept) { resourceHandler->SetFinishFlag(); resourceHandler->DecStrongRef(nullptr); } } void WebSchemeHandlerImpl::RequestStopAfterWorkCb(RequestStopParam* param) { WEBVIEWLOGI("[SchemeHandler] WebSchemeHandlerImpl::RequestStopAfterWorkCb"); if (!param->callbackRef_) { WEBVIEWLOGI("scheme handler onRequestStop not exists"); delete param; return; } param->callbackRef_(param->request_->GetID()); WebResourceHandlerImpl* resourceHandler = reinterpret_cast( OH_ArkWebResourceRequest_GetUserData(param->arkWebRequest_)); if (resourceHandler) { resourceHandler->SetFinishFlag(); } delete param; param = nullptr; } void WebSchemeHandlerImpl::RequestStop(const ArkWeb_ResourceRequest* resourceRequest) { WEBVIEWLOGI("[SchemeHandler] WebSchemeHandlerImpl::RequestStop"); RequestStopParam *param = new (std::nothrow) RequestStopParam(); if (param == nullptr) { return; } param->callbackRef_ = request_stop_callback_; param->request_ = FFIData::Create(resourceRequest); if (param->request_ == nullptr) { delete param; return; } param->arkWebRequest_ = resourceRequest; std::thread([param]() { RequestStopAfterWorkCb(param); }).detach(); } void WebSchemeHandlerImpl::PutRequestStart(std::function callback) { WEBVIEWLOGI("[SchemeHandler] WebSchemeHandlerImpl::PutRequestStart"); request_start_callback_ = callback; } void WebSchemeHandlerImpl::PutRequestStop(std::function callback) { WEBVIEWLOGI("WebSchemeHandlerImpl::PutRequestStop"); request_stop_callback_ = callback; } }