a975a0ae创建于 2025年8月1日历史提交
/*

 * 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 <cstdint>

#include <thread>

#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<WebHttpBodyStreamImpl*>(

            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*, const ArkWeb_SchemeHandler*>

        WebSchemeHandlerImpl::webSchemeHandlerMap_;

    std::unordered_map<const ArkWeb_SchemeHandler*, WebSchemeHandlerImpl*>

        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<ArkWeb_SchemeHandler*>(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<WebSchemeHandlerRequestImpl> schemeHandlerRequest = FFIData::Create<WebSchemeHandlerRequestImpl>(request);

        if (schemeHandlerRequest == nullptr) {

            WEBVIEWLOGD("RequestStart, new schemeHandlerRequest failed");

            return;

        }

        sptr<WebResourceHandlerImpl> resourceHandler = FFIData::Create<WebResourceHandlerImpl>(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<WebResourceHandlerImpl*>(

                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<WebSchemeHandlerRequestImpl>(resourceRequest);

        if (param->request_ == nullptr) {

            delete param;

            return;

        }

        param->arkWebRequest_ = resourceRequest;

        std::thread([param]() {

            RequestStopAfterWorkCb(param);

        }).detach();

    }



    void WebSchemeHandlerImpl::PutRequestStart(std::function<bool(int64_t, int64_t)> callback)

    {

        WEBVIEWLOGI("[SchemeHandler] WebSchemeHandlerImpl::PutRequestStart");

        request_start_callback_ = callback;

    }



    void WebSchemeHandlerImpl::PutRequestStop(std::function<void(int64_t)> callback)

    {

        WEBVIEWLOGI("WebSchemeHandlerImpl::PutRequestStop");

        request_stop_callback_ = callback;

    }

}