diff --git a/interfaces/kits/ani/webview/BUILD.gn b/interfaces/kits/ani/webview/BUILD.gn index 26532b9112d66a0b56998aed6f7a101a6099a7e5..6ce9c4a81eeccfca796dc0b883ec6fb96c297d4e 100644 --- a/interfaces/kits/ani/webview/BUILD.gn +++ b/interfaces/kits/ani/webview/BUILD.gn @@ -50,8 +50,8 @@ ohos_shared_library("webview_native") { #"native/webviewcontroller/web_download_item.cpp", #"native/webviewcontroller/web_download_item.h", #"native/webviewcontroller/web_download_manager.cpp", - #"native/webviewcontroller/web_download_manager.h", - #"native/webviewcontroller/web_scheme_handler_request.cpp", + "native/webviewcontroller/web_download_manager.h", + "native/webviewcontroller/web_scheme_handler_request.cpp", #"native/webviewcontroller/web_scheme_handler_request.h", "native/webviewcontroller/webview_controller.cpp", "native/webviewcontroller/webview_hasimage_callback.cpp", @@ -108,6 +108,7 @@ ohos_shared_library("webview_ani") { sources = [ "./src/common/ani_business_error.cpp", + "./src/common/ani_parse_utils.h", "./src/common/ani_parse_utils.cpp", "./src/webstorage/ani_web_storage.cpp", "./src/webadsblockmanager/ani_web_adsblock_manager.h", @@ -115,9 +116,17 @@ ohos_shared_library("webview_ani") { "./src/webdatabase/ani_web_data_base.cpp", "./src/webdatabase/ani_geolocation_permission.cpp", "./src/webviewcontroller/ani_webview_controller.cpp", + "./src/webviewcontroller/ani_webview_controller.h", "./src/webviewcontroller/web_scheme_handler_response.cpp", "./src/webviewcontroller/web_scheme_handler_response.h", + "./src/webviewcontroller/ani_web_scheme_handler_request.cpp", + "./src/webviewcontroller/ani_web_scheme_handler_request.h", + "./src/webviewcontroller/ani_web_scheme_handler_resource.cpp", + "./src/webviewcontroller/ani_web_scheme_handler_resource.h", + "./src/webviewcontroller/ani_web_scheme_handler.cpp", + "./src/webviewcontroller/ani_web_scheme_handler.h", "./src/webviewcontroller/ani_web_scheme_handler_response.cpp", + "./src/webviewcontroller/ani_web_scheme_handler_response.h", "./src/webviewcontroller/ani_web_download_delegate.cpp", "./src/webviewcontroller/ani_web_download_item.cpp", "./src/webviewcontroller/ani_web_download_manager.cpp", @@ -159,7 +168,7 @@ ohos_shared_library("webview_ani") { "image_framework:image", "image_framework:image_native", "image_framework:image_ani", - #"image_framework:image_taihe", + "image_framework:image_taihe", "init:libbegetutil", "ipc:ipc_core", "napi:ace_napi", diff --git a/interfaces/kits/ani/webview/ets/@ohos.web.webview.ets b/interfaces/kits/ani/webview/ets/@ohos.web.webview.ets index 7df5e2f89d2fcca5cc403af98ef4f33a450706c8..a0e37d5da799ef9e2e691edcd2c8f4aa1accebae 100644 --- a/interfaces/kits/ani/webview/ets/@ohos.web.webview.ets +++ b/interfaces/kits/ani/webview/ets/@ohos.web.webview.ets @@ -152,6 +152,29 @@ export default namespace webview { DECODE_ERROR = 3 } + export enum WebResourceType{ + MAIN_FRAME = 0, + SUB_FRAME = 1, + STYLE_SHEET = 2, + SCRIPT = 3, + IMAGE = 4, + FONT_RESOURCE = 5, + SUB_RESOURCE = 6, + OBJECT = 7, + MEDIA = 8, + WORKER = 9, + SHARED_WORKER = 10, + PREFETCH = 11, + FAVICON = 12, + XHR = 13, + PING = 14, + SERVICE_WORKER = 15, + CSP_REPORT = 16, + PLUGIN_RESOURCE = 17, + NAVIGATION_PRELOAD_MAIN_FRAME = 19, + NAVIGATION_PRELOAD_SUB_FRAME = 20, + } + export enum MediaType { VIDEO = 0, AUDIO = 1 @@ -203,6 +226,11 @@ export default namespace webview { headerValue: string; } + export class GetHeaderWebHeader implements WebHeader { + headerKey: string; + headerValue: string; + } + export interface ScrollOffset { x: double; y: double; @@ -660,8 +688,96 @@ export default namespace webview { * @since 20 */ native getUrl(): string; + native setMimeType(type: string): void; + native getMimeType(): string; + native setEncoding(encoding: string): void; + native getEncoding(): string; + native setStatusText(text: string): void; + native getStatusText(): string; + native setStatus(code: number): void; + native getStatus(): number; + native setHeaderByName(name: string, value: string, overwrite: boolean): void; + native getHeaderByName(name: string): string; + } + + export class WebSchemeHandler { + private nativePtr: long = 0; + private cleaner?: Cleaner; + + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr, "WebSchemeHandler") + destroyRegister.register(this, this.cleaner!, unregisterToken); + } + unregisterCleaner(): void { + destroyRegister.unregister(unregisterToken); + } + + bindNativePtr(ptr: long): void { + if (this.nativePtr == 0) { + this.nativePtr = ptr; + this.registerCleaner(this.nativePtr) + } + } + + native constructor(); + native onRequestStart(callback: (request: WebSchemeHandlerRequest, handler: WebResourceHandler) => boolean): void; } + export class WebSchemeHandlerRequest { + private nativePtr: long = 0; + private cleaner?: Cleaner; + + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr, "WebSchemeHandlerRequest") + destroyRegister.register(this, this.cleaner!, unregisterToken); + } + unregisterCleaner(): void { + destroyRegister.unregister(unregisterToken); + } + + bindNativePtr(ptr: long): void { + if (this.nativePtr == 0) { + this.nativePtr = ptr; + this.registerCleaner(this.nativePtr) + } + } + + native constructor(); + native hasGesture(): boolean; + native getReferrer(): string; + native getFrameUrl(): string; + native getHeader(): Array; + native getRequestResourceType(): WebResourceType; + native getRequestUrl(): string; + native isMainFrame(): boolean; + native getRequestMethod(): string; + } + + export class WebResourceHandler { + private nativePtr: long = 0; + private cleaner?: Cleaner; + + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr, "WebResourceHandler") + destroyRegister.register(this, this.cleaner!, unregisterToken); + } + unregisterCleaner(): void { + destroyRegister.unregister(unregisterToken); + } + + bindNativePtr(ptr: long): void { + if (this.nativePtr == 0) { + this.nativePtr = ptr; + this.registerCleaner(this.nativePtr) + } + } + native constructor(); + + native didReceiveResponse(response: WebSchemeHandlerResponse): void; + native didFinish(): void; + } + + export class WebDownloadItem { static { loadLibrary("webview_ani.z"); @@ -1189,14 +1305,14 @@ export default namespace webview { export interface WebStorageOrigin { origin: string; - usage: number; - quota: number; + usage: double; + quota: double; } export class WebStorageOriginInner implements WebStorageOrigin { origin: string = ""; - usage: number = 0; - quota: number = 0; + usage: double = 0; + quota: double = 0; } export class WebStorage { @@ -1204,8 +1320,8 @@ export default namespace webview { loadLibrary("webview_ani.z"); } native static getOriginsSync(): Array; - native static getOriginQuotaSync(origin: string): number; - native static getOriginUsageSync(origin: string): number; + native static getOriginQuotaSync(origin: string): double; + native static getOriginUsageSync(origin: string): double; native static deleteAllData(incognito?: boolean): void; native static deleteOrigin(origin: string): void; static getOrigins(): Promise> { @@ -1235,24 +1351,24 @@ export default namespace webview { }); } - static getOriginQuota(origin: string): Promise { - let p = new Promise((resolve: (v: number) => void, + static getOriginQuota(origin: string): Promise { + let p = new Promise((resolve: (v: double) => void, reject: (error: Error) => void) => { let p1 = taskpool.execute(WebStorage.getOriginQuotaSync, origin); p1.then((e : NullishType) => { - let r = e as number; + let r = e as double; resolve(r); - }).catch((error: Error): number => { + }).catch((error: Error): double => { reject(error); }); }); return p; } - static getOriginQuota(origin: string, callback: AsyncCallback): void { + static getOriginQuota(origin: string, callback: AsyncCallback): void { let p = taskpool.execute(WebStorage.getOriginQuotaSync, origin); p.then((e : NullishType) => { - let r = e as number; + let r = e as double; let err : BusinessError = new BusinessError(); callback(err, r); }).catch((error: Error) => { @@ -1261,24 +1377,24 @@ export default namespace webview { }); } - static getOriginUsage(origin: string): Promise { - let p = new Promise((resolve: (v: number) => void, + static getOriginUsage(origin: string): Promise { + let p = new Promise((resolve: (v: double) => void, reject: (error: Error) => void) => { let p1 = taskpool.execute(WebStorage.getOriginUsageSync, origin); p1.then((e : NullishType) => { - let r = e as number; + let r = e as double; resolve(r); - }).catch((error: Error): number => { + }).catch((error: Error): double => { reject(error); }); }); return p; } - static getOriginUsage(origin: string, callback: AsyncCallback): void { + static getOriginUsage(origin: string, callback: AsyncCallback): void { let p = taskpool.execute(WebStorage.getOriginUsageSync, origin); p.then((e : NullishType) => { - let r = e as number; + let r = e as double; let err : BusinessError = new BusinessError(); callback(err, r); }).catch((error: Error) => { diff --git a/interfaces/kits/ani/webview/native/webviewcontroller/web_scheme_handler_request.cpp b/interfaces/kits/ani/webview/native/webviewcontroller/web_scheme_handler_request.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f17cdee611cb2c7bb227a0452bd0ac54aeb08916 --- /dev/null +++ b/interfaces/kits/ani/webview/native/webviewcontroller/web_scheme_handler_request.cpp @@ -0,0 +1,518 @@ +/* + * 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 "web_scheme_handler_request.h" + +#include +#include +#include + +#include "business_error.h" +#include "nweb_log.h" +#include "web_errors.h" + +namespace OHOS::NWeb { +namespace { + +bool Wrap(ani_env* env, const ani_object& object, const char* className, const ani_long& thisVar) +{ + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return false; + } + ani_status status; + ani_class cls; + if ((status = env->FindClass(className, &cls)) != ANI_OK) { + WVLOG_E("AniUtils_Wrap FindClass status: %{public}d", status); + return false; + } + ani_method innerWrapMethod; + if ((status = env->Class_FindMethod(cls, "bindNativePtr", "J:V", &innerWrapMethod)) != ANI_OK) { + WVLOG_E("AniUtils_Wrap Class_FindMethod status: %{public}d", status); + return false; + } + if ((status = env->Object_CallMethod_Void(object, innerWrapMethod, thisVar)) != ANI_OK) { + WVLOG_E("AniUtils_Wrap Object_CallMethod_Void status: %{public}d", status); + return false; + } + return true; +} + +bool CreateObjectVoid(ani_env* env, const char* className, ani_object& object) +{ + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return false; + } + + ani_boolean errorExists; + WVLOG_E("xuwen class failed"); + env->ExistUnhandledError(&errorExists); + + ani_class cls; + ani_status status = env->FindClass(className, &cls); + + std::ostringstream buffer; + std::streambuf* oldStderr = std::cerr.rdbuf(buffer.rdbuf()); + ani_status statusError = env->DescribeError(); + std::cerr.rdbuf(oldStderr); + std::string output = buffer.str(); + std::vector vec(output.begin(), output.end()); + vec.push_back('\0'); + env->ExistUnhandledError(&errorExists); + char* charPtr = vec.data(); + WVLOG_E("xuwen Arkts %{public}s class failed status: %{public}d", charPtr, statusError); + + if (status != ANI_OK) { + WVLOG_E("find %{public}s class failed, status: %{public}d", className, status); + return false; + } + ani_method ctor; + if ((status = env->Class_FindMethod(cls, "", nullptr, &ctor)) != ANI_OK) { + WVLOG_E("get %{public}s ctor method failed, status: %{public}d", className, status); + return false; + } + if ((status = env->Object_New(cls, ctor, &object)) != ANI_OK) { + WVLOG_E("new %{public}s failed, status: %{public}d", className, status); + return false; + } + return true; +} + +bool ParseBoolean(ani_env* env, ani_ref ref, bool& outValue) +{ + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return false; + } + ani_class booleanClass; + ani_status status; + status = env->FindClass("Lstd/core/Boolean;", &booleanClass); + if (status != ANI_OK) { + WVLOG_E("ParseBoolean FindClass status: %{public}d", status); + return false; + } + + ani_boolean isBoolean; + if (env->Object_InstanceOf(static_cast(ref), booleanClass, &isBoolean) != ANI_OK || + isBoolean != ANI_TRUE) { + WVLOG_E("ParseBoolean failed - invalid boolean type"); + return false; + } + + ani_boolean boolValue; + env->Object_CallMethodByName_Boolean(static_cast(ref), "unboxed", ":Z", &boolValue); + outValue = static_cast(boolValue); + return true; +} + +void OnRequestStart(const ArkWeb_SchemeHandler* schemeHandler, ArkWeb_ResourceRequest* resourceRequest, + const ArkWeb_ResourceHandler* resourceHandler, bool* intercept) +{ + WVLOG_E("xuwen SchemeHandler OnRequestStart"); + if (!schemeHandler) { + WVLOG_E("OnRequestStart schemeHandler is nullptr"); + return; + } + WebSchemeHandler* handler = WebSchemeHandler::GetWebSchemeHandler(schemeHandler); + if (!handler) { + WVLOG_E("GetWebSchemeHandler failed"); + return; + } + WVLOG_E("xuwen SchemeHandler OnRequestStart"); + handler->RequestStart(resourceRequest, resourceHandler, intercept); +} + +void OnRequestStop(const ArkWeb_SchemeHandler* schemeHandler, const ArkWeb_ResourceRequest* resourceRequest) +{ + WVLOG_I("SchemeHandler OnRequestStop"); + if (!schemeHandler) { + WVLOG_E("OnRequestStop schemeHandler is nullptr"); + return; + } + WebSchemeHandler* handler = WebSchemeHandler::GetWebSchemeHandler(schemeHandler); + if (!handler) { + WVLOG_E("GetWebSchemeHandler failed"); + return; + } + handler->RequestStop(resourceRequest); +} +} // namespace + +WebSchemeHandlerRequest::WebSchemeHandlerRequest(ani_env* env) : env_(env) +{ + if (env_->GetVM(&vm_) != ANI_OK) { + WVLOG_E("Failed to get VM from env"); + return; + } + WVLOG_I("WebSchemeHandlerRequest::WebSchemeHandlerRequest"); +} + +WebSchemeHandlerRequest::WebSchemeHandlerRequest(ani_env* env, const ArkWeb_ResourceRequest* request) : env_(env) +{ + WVLOG_I("WebSchemeHandlerRequest::WebSchemeHandlerRequest"); + OH_ArkWebResourceRequest_GetUrl(request, &url_); + OH_ArkWebResourceRequest_GetMethod(request, &method_); + OH_ArkWebResourceRequest_GetReferrer(request, &referrer_); + isRedirect_ = OH_ArkWebResourceRequest_IsRedirect(request); + isMainFrame_ = OH_ArkWebResourceRequest_IsMainFrame(request); + hasGesture_ = OH_ArkWebResourceRequest_HasGesture(request); + OH_ArkWebResourceRequest_GetHttpBodyStream(request, &stream_); + requestResourceType_ = OH_ArkWebResourceRequest_GetResourceType(request); + OH_ArkWebResourceRequest_GetFrameUrl(request, &frameUrl_); + + ArkWeb_RequestHeaderList* arkWebHeaderlist = nullptr; + OH_ArkWebResourceRequest_GetRequestHeaders(request, &arkWebHeaderlist); + if (!arkWebHeaderlist) { + WVLOG_E("OH_ArkWebRequestHeaderList_Create failed"); + return; + } + int32_t size = OH_ArkWebRequestHeaderList_GetSize(arkWebHeaderlist); + if (size <= 0) { + WVLOG_E("OH_ArkWebRequestHeaderList_GetSize:%{public}d", size); + return; + } + for (int32_t index = 0; index < size; index++) { + char* key; + char* value; + OH_ArkWebRequestHeaderList_GetHeader(arkWebHeaderlist, index, &key, &value); + if (!key || !value) { + continue; + } + std::string strKey(key); + std::string strValue(value); + headerList_.emplace_back(std::make_pair(strKey, strValue)); + OH_ArkWeb_ReleaseString(key); + OH_ArkWeb_ReleaseString(value); + } + OH_ArkWebRequestHeaderList_Destroy(arkWebHeaderlist); +} + +WebSchemeHandlerRequest::~WebSchemeHandlerRequest() +{ + WVLOG_I("WebSchemeHandlerRequest::~WebSchemeHandlerRequest"); + OH_ArkWeb_ReleaseString(url_); + OH_ArkWeb_ReleaseString(method_); + OH_ArkWeb_ReleaseString(referrer_); +} + +char* WebSchemeHandlerRequest::GetRequestUrl() +{ + return url_; +} + +char* WebSchemeHandlerRequest::GetMethod() +{ + return method_; +} + +char* WebSchemeHandlerRequest::GetReferrer() +{ + return referrer_; +} + +bool WebSchemeHandlerRequest::IsRedirect() +{ + return isRedirect_; +} + +bool WebSchemeHandlerRequest::IsMainFrame() +{ + return isMainFrame_; +} + +bool WebSchemeHandlerRequest::HasGesture() +{ + return hasGesture_; +} + +const WebHeaderList& WebSchemeHandlerRequest::GetHeader() +{ + return headerList_; +} + +ArkWeb_HttpBodyStream* WebSchemeHandlerRequest::GetHttpBodyStream() +{ + return stream_; +} + +int32_t WebSchemeHandlerRequest::GetRequestResourceType() +{ + return requestResourceType_; +} + +char* WebSchemeHandlerRequest::GetFrameUrl() +{ + return frameUrl_; +} + +std::unordered_map WebSchemeHandler::webSchemeHandlerMap_; +std::unordered_map WebSchemeHandler::arkWebSchemeHandlerMap_; + +const ArkWeb_SchemeHandler* WebSchemeHandler::GetArkWebSchemeHandler(WebSchemeHandler* handler) +{ + return WebSchemeHandler::webSchemeHandlerMap_.find(handler) != WebSchemeHandler::webSchemeHandlerMap_.end() + ? WebSchemeHandler::webSchemeHandlerMap_[handler] + : nullptr; +} + +WebSchemeHandler* WebSchemeHandler::GetWebSchemeHandler(const ArkWeb_SchemeHandler* handler) +{ + return WebSchemeHandler::arkWebSchemeHandlerMap_.find(handler) != WebSchemeHandler::arkWebSchemeHandlerMap_.end() + ? WebSchemeHandler::arkWebSchemeHandlerMap_[handler] + : nullptr; +} + +WebSchemeHandler::WebSchemeHandler(ani_env* env) : vm_(nullptr) +{ + WVLOG_E("create WebSchemeHandler"); + if (!env) { + WVLOG_E("create WebSchemeHandler env null"); + return; + } + env_ = env; + + WVLOG_E("create WebSchemeHandler"); + ArkWeb_SchemeHandler* handler; + OH_ArkWeb_CreateSchemeHandler(&handler); + if (!handler) { + WVLOG_E("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)); +} + +WebSchemeHandler::~WebSchemeHandler() +{ + WVLOG_I("WebSchemeHandler::~WebSchemeHandler"); + GetEnv()->GlobalReference_Delete(request_start_callback_); + GetEnv()->GlobalReference_Delete(request_stop_callback_); + + ArkWeb_SchemeHandler* handler = const_cast(GetArkWebSchemeHandler(this)); + if (!handler) { + WVLOG_E("~WebSchemeHandler not found ArkWeb_SchemeHandler"); + return; + } + webSchemeHandlerMap_.erase(this); + arkWebSchemeHandlerMap_.erase(handler); + OH_ArkWeb_DestroySchemeHandler(handler); +} + +void WebSchemeHandler::RequestStart( + ArkWeb_ResourceRequest* request, const ArkWeb_ResourceHandler* ArkWeb_ResourceHandler, bool* intercept) +{ + WVLOG_E("xuwen SchemeHandler OnRequestStart"); + if (vm_ == nullptr) { + WVLOG_E("WebSchemeHandler::RequestStart nil vm"); + return; + } + + ani_env* env = GetEnv(); + if (!request_start_callback_ || !request) { + WVLOG_E("WebSchemeHandler request_start_callback_ or request is null."); + return; + } + if (!env_ || !env) { + WVLOG_E("WebSchemeHandler env is null."); + return; + } + ani_size nr_refs = REFERENCES_MAX_NUMBER; + env->CreateLocalScope(nr_refs); + WVLOG_E("xuwen SchemeHandler OnRequestStart"); + + WVLOG_E("xuwen SchemeHandler OnRequestStart"); + WebSchemeHandlerRequest* schemeHandlerRequest = new (std::nothrow) WebSchemeHandlerRequest(env, request); + if (schemeHandlerRequest == nullptr) { + WVLOG_E("RequestStart, new schemeHandlerRequest failed"); + env->DestroyLocalScope(); + return; + } + sptr resourceHandler = new (std::nothrow) WebResourceHandler(env, ArkWeb_ResourceHandler); + if (resourceHandler == nullptr) { + WVLOG_E("RequestStart, new resourceHandler failed"); + delete schemeHandlerRequest; + resourceHandler->DecStrongRef(resourceHandler); + env->DestroyLocalScope(); + return; + } + WVLOG_E("xuwen SchemeHandler OnRequestStart"); + + ani_object requestObject = {}; + if (!CreateObjectVoid(env, WEB_WEBSCHEME_HANDLER_REQUEST_CLASS_NAME, requestObject)) { + WVLOG_E("[SchemeHandler] CreaterequestObject failed"); + delete schemeHandlerRequest; + resourceHandler->DecStrongRef(resourceHandler); + env->DestroyLocalScope(); + return; + } + + ani_object resourceObject = {}; + if (!CreateObjectVoid(env, WEB_RESOURCE_HANDLER_CLASS_NAME, resourceObject)) { + WVLOG_E("[SchemeHandler] CreateresourceObject Failed"); + delete schemeHandlerRequest; + resourceHandler->DecStrongRef(resourceHandler); + env->DestroyLocalScope(); + return; + } + WVLOG_E("[SchemeHandler] xuwen"); + if (OH_ArkWebResourceRequest_SetUserData(request, resourceHandler.GetRefPtr()) != 0) { + WVLOG_W("OH_ArkWebResourceRequest_SetUserData failed"); + WVLOG_E("[SchemeHandler] xuwen1"); + } else { + resourceHandler->IncStrongRef(nullptr); + WVLOG_E("[SchemeHandler] xuwen2"); + } + WVLOG_E("xuwen SchemeHandler OnRequestStart"); + if (!Wrap(env, requestObject, WEB_WEBSCHEME_HANDLER_REQUEST_CLASS_NAME, + reinterpret_cast(schemeHandlerRequest))) { + WVLOG_E("[SchemeHandler] WebSchemeHandlerRequest wrap failed"); + delete schemeHandlerRequest; + schemeHandlerRequest = nullptr; + env->DestroyLocalScope(); + return; + } + + if (!Wrap(env, resourceObject, WEB_RESOURCE_HANDLER_CLASS_NAME, + reinterpret_cast(resourceHandler.GetRefPtr()))) { + WVLOG_E("[SchemeHandler] WebResourceHandler wrap failed"); + resourceHandler->DecStrongRef(resourceHandler); + resourceHandler = nullptr; + env->DestroyLocalScope(); + return; + } + WVLOG_E("xuwen SchemeHandler OnRequestStart"); + + if (requestObject == nullptr || resourceObject == nullptr) { + WVLOG_E("requestObject or resourceRequest is null"); + env->DestroyLocalScope(); + return; + } + WVLOG_E("xuwen SchemeHandler OnRequestStart"); + resourceHandler->IncStrongRef(nullptr); + std::vector vec; + vec.push_back(static_cast(requestObject)); + vec.push_back(static_cast(resourceObject)); + ani_ref fnReturnVal; + ani_status status; + status = env->FunctionalObject_Call( + reinterpret_cast(request_start_callback_), vec.size(), vec.data(), &fnReturnVal); + if (status != ANI_OK) { + WVLOG_E("scheme handler call onRequestStart failed."); + } + + if (!ParseBoolean(env, fnReturnVal, *intercept)) { + WVLOG_E("scheme handler onRequestStart intercept parse failed"); + *intercept = false; + } + WVLOG_E("xuwen SchemeHandler OnRequestStart"); + env->DestroyLocalScope(); + if (!*intercept) { + resourceHandler->SetFinishFlag(); + resourceHandler->DecStrongRef(resourceHandler); + } +} + +void WebSchemeHandler::PutRequestStart(ani_env* env, ani_vm* vm, ani_fn_object callback) +{ + WVLOG_I("xuwen WebSchemeHandler::PutRequestStart"); + if (!vm) { + WVLOG_E("PutRequestStart vm null"); + return; + } + vm_ = vm; + ani_status status = env->GlobalReference_Create(reinterpret_cast(callback), &request_start_callback_); + if (status != ANI_OK) { + WVLOG_E("xuwen PutRequestStart create reference failed."); + } +} + +WebResourceHandler::WebResourceHandler(ani_env* env) +{ + WVLOG_I("create WebResourceHandler"); + if (env->GetVM(&vm_) != ANI_OK) { + WVLOG_E("Failed to get VM from env"); + return; + } +} + +WebResourceHandler::WebResourceHandler(ani_env* env, const ArkWeb_ResourceHandler* handler) + : handler_(const_cast(handler)) +{ + WVLOG_E("create WebResourceHandler"); + if (env->GetVM(&vm_) != ANI_OK) { + WVLOG_E("Failed to get VM from env"); + return; + } +} + +WebResourceHandler::~WebResourceHandler() +{ + WVLOG_E("~WebResourceHandler"); +} + +int32_t WebResourceHandler::DidReceiveResponse(const ArkWeb_Response* response) +{ + if (isFinished_) { + return ArkWeb_ErrorCode::ARKWEB_ERROR_UNKNOWN; + } + return OH_ArkWebResourceHandler_DidReceiveResponse(handler_, response); +} + +int32_t WebResourceHandler::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 WebResourceHandler::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 WebResourceHandler::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 WebResourceHandler::DestoryArkWebResourceHandler() +{ + if (handler_) { + OH_ArkWebResourceHandler_Destroy(handler_); + handler_ = nullptr; + } +} +} // namespace OHOS::NWeb diff --git a/interfaces/kits/ani/webview/native/webviewcontroller/web_scheme_handler_request.h b/interfaces/kits/ani/webview/native/webviewcontroller/web_scheme_handler_request.h new file mode 100644 index 0000000000000000000000000000000000000000..94533911057a644ed0e689d2818a04e46836cae4 --- /dev/null +++ b/interfaces/kits/ani/webview/native/webviewcontroller/web_scheme_handler_request.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2025 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. + */ + +#ifndef OHOS_NWEB_SCHEME_HANDLER_REQUEST_H +#define OHOS_NWEB_SCHEME_HANDLER_REQUEST_H + +#include +#include +#include + +#include "arkweb_scheme_handler.h" +#include "refbase.h" + +namespace OHOS { +namespace NWeb { +namespace { +const char* WEB_WEBSCHEME_HANDLER_CLASS_NAME = "L@ohos/web/webview/webview/WebSchemeHandler;"; +const char* WEB_WEBSCHEME_HANDLER_REQUEST_CLASS_NAME = "L@ohos/web/webview/webview/WebSchemeHandlerRequest;"; +const char* WEB_RESOURCE_HANDLER_CLASS_NAME = "L@ohos/web/webview/webview/WebResourceHandler;"; +constexpr ani_size REFERENCES_MAX_NUMBER = 16; + +} // namespace +using WebHeaderList = std::vector>; +class WebSchemeHandlerRequest { +public: + explicit WebSchemeHandlerRequest(ani_env* env); + WebSchemeHandlerRequest(ani_env* env, const ArkWeb_ResourceRequest* request); + ~WebSchemeHandlerRequest(); + + char* GetRequestUrl(); + char* GetMethod(); + char* GetReferrer(); + bool IsRedirect(); + bool IsMainFrame(); + bool HasGesture(); + const WebHeaderList& GetHeader(); + ArkWeb_HttpBodyStream* GetHttpBodyStream(); + int32_t GetRequestResourceType(); + char* GetFrameUrl(); + +private: + ani_vm* vm_ = nullptr; + ani_env* env_; + char* url_ = nullptr; + char* method_ = nullptr; + char* referrer_ = nullptr; + bool isRedirect_ = false; + bool isMainFrame_ = false; + bool hasGesture_ = false; + WebHeaderList headerList_; + ArkWeb_HttpBodyStream* stream_ = nullptr; + int32_t requestResourceType_ = -1; + char* frameUrl_ = nullptr; +}; + +class WebResourceHandler : public RefBase { +public: + explicit WebResourceHandler(ani_env* env); + WebResourceHandler(ani_env* env, const ArkWeb_ResourceHandler* handler); + ~WebResourceHandler(); + int32_t DidReceiveResponse(const ArkWeb_Response* response); + int32_t DidReceiveResponseBody(const uint8_t* buffer, int64_t buflen); + int32_t DidFinish(); + int32_t DidFailWithError(ArkWeb_NetError errorCode); + void DestoryArkWebResourceHandler(); + void SetFinishFlag() + { + isFinished_ = true; + } + +private: + ani_vm* vm_ = nullptr; + bool isFinished_ = false; + ArkWeb_ResourceHandler* handler_ = nullptr; +}; + +class WebSchemeHandler { +public: + explicit WebSchemeHandler(ani_env* env); + ~WebSchemeHandler(); + + static const ArkWeb_SchemeHandler* GetArkWebSchemeHandler(WebSchemeHandler* handler); + static WebSchemeHandler* GetWebSchemeHandler(const ArkWeb_SchemeHandler* handler); + + void RequestStart( + ArkWeb_ResourceRequest* request, const ArkWeb_ResourceHandler* ArkWeb_ResourceHandler, bool* intercept); + + void PutRequestStart(ani_env *env, ani_vm* vm, ani_fn_object callback); + + ani_ref delegate_ = nullptr; + static std::unordered_map webSchemeHandlerMap_; + static std::unordered_map arkWebSchemeHandlerMap_; + ani_env* GetEnv() { + ani_env* env = nullptr; + if (vm_) { + vm_->GetEnv(ANI_VERSION_1, &env); + } + return env; + } + +private: + ani_env* env_ = nullptr; + ani_vm* vm_ = nullptr; + ArkWeb_OnRequestStart onRequestStart_ = nullptr; + ani_ref request_start_callback_ = nullptr; +}; +} // namespace NWeb +} // namespace OHOS +#endif // OHOS_NWEB_ANI_SCHEME_HANDLER_REQUEST_H \ No newline at end of file diff --git a/interfaces/kits/ani/webview/native/webviewcontroller/webview_controller.cpp b/interfaces/kits/ani/webview/native/webviewcontroller/webview_controller.cpp index fecd1e0f9d7b38e4544d1a541ea9b38a8f03d73d..04c69a89e15b7d580746b36906f38e0bea37ca44 100644 --- a/interfaces/kits/ani/webview/native/webviewcontroller/webview_controller.cpp +++ b/interfaces/kits/ani/webview/native/webviewcontroller/webview_controller.cpp @@ -1474,6 +1474,35 @@ void WebPrintWriteResultCallbackAdapter::WriteResultCallback(std::string jobId, cb_(jobId, code); } +bool WebviewController::SetWebSchemeHandler(const char* scheme, WebSchemeHandler* handler) const + +{ + if (!handler || !scheme) { + WVLOG_E("WebviewController::SetWebSchemeHandler handler or scheme is nullptr"); + return false; + } + + auto schemeHandler_ptr = WebSchemeHandler::GetArkWebSchemeHandler(handler); + if (!schemeHandler_ptr) { + WVLOG_E("WebviewController::SetWebSchemeHandler ArkWebSchemeHandler is nullptr"); + return false; + } + + ArkWeb_SchemeHandler* schemeHandler = const_cast(schemeHandler_ptr); + return OH_ArkWeb_SetSchemeHandler(scheme, webTag_.c_str(), schemeHandler); +} + +bool WebviewController::SetWebServiveWorkerSchemeHandler(const char* scheme, WebSchemeHandler* handler) +{ + auto schemeHandler_ptr = WebSchemeHandler::GetArkWebSchemeHandler(handler); + if (!schemeHandler_ptr) { + WVLOG_E("WebviewController::SetWebServiveWorkerSchemeHandler ArkWebSchemeHandler is nullptr"); + return false; + } + ArkWeb_SchemeHandler* schemeHandler = const_cast(schemeHandler_ptr); + return OH_ArkWebServiceWorker_SetSchemeHandler(scheme, schemeHandler); +} + int32_t WebviewController::ClearWebSchemeHandler() { return OH_ArkWeb_ClearSchemeHandlers(webTag_.c_str()); diff --git a/interfaces/kits/ani/webview/native/webviewcontroller/webview_controller.h b/interfaces/kits/ani/webview/native/webviewcontroller/webview_controller.h index 9afdaa4b751f5a01d639deaee2f9f94f25deca34..9a96071013bce2ea5be490bd138c6fe024cbeee5 100644 --- a/interfaces/kits/ani/webview/native/webviewcontroller/webview_controller.h +++ b/interfaces/kits/ani/webview/native/webviewcontroller/webview_controller.h @@ -32,6 +32,7 @@ #include "webview_javascript_result_callback.h" #include "print_manager_adapter.h" #include "arkweb_scheme_handler.h" +#include "web_scheme_handler_request.h" namespace OHOS { namespace NWeb { @@ -314,6 +315,10 @@ public: bool IsIntelligentTrackingPreventionEnabled() const; + bool SetWebSchemeHandler(const char* scheme, WebSchemeHandler* handler) const; + + static bool SetWebServiveWorkerSchemeHandler(const char* scheme, WebSchemeHandler* handler); + int32_t ClearWebSchemeHandler(); ErrCode StartCamera(); diff --git a/interfaces/kits/ani/webview/src/common/ani_class_name.h b/interfaces/kits/ani/webview/src/common/ani_class_name.h index de256cd85d0da5fa8b2644778592d29b46cdd5a4..13f5ab1839da5005157169128cba134e2e19915f 100644 --- a/interfaces/kits/ani/webview/src/common/ani_class_name.h +++ b/interfaces/kits/ani/webview/src/common/ani_class_name.h @@ -37,6 +37,7 @@ const char* ANI_WEB_MESSAGE_PORT_INNER_CLASS_NAME = "L@ohos/web/webview/webview/ const char* ANI_ENUM_MEDIA_PLAY_BACK_STATE = "L@ohos/web/webview/webview/MediaPlaybackState;"; const char* ANI_SNAPSHOT_RESULT_CLASS_NAME = "L@ohos/web/webview/webview/SnapshotResultClass;"; const char* ANI_PDF_DATA_CLASS_NAME = "L@ohos/web/webview/webview/PdfData;"; +const char* ANI_CLASS_WEB_RESOURCETYPE = "L@ohos/web/webview/webview/WebResourceType;"; } // namespace NWeb } // namespace OHOS diff --git a/interfaces/kits/ani/webview/src/common/ani_parse_utils.cpp b/interfaces/kits/ani/webview/src/common/ani_parse_utils.cpp index b6fd9475f97bf517bd7d97fc52d57b70106086c0..87e39cdb749060ac96f435b33afb009dee6c9cb7 100644 --- a/interfaces/kits/ani/webview/src/common/ani_parse_utils.cpp +++ b/interfaces/kits/ani/webview/src/common/ani_parse_utils.cpp @@ -574,7 +574,7 @@ ani_object AniParseUtils::CreateInt(ani_env *env, ani_int val) return obj; } -ani_string StringToAniStr(ani_env* env, const std::string& str) +ani_string AniParseUtils::StringToAniStr(ani_env* env, const std::string& str) { ani_string result {}; if (ANI_OK != env->String_NewUTF8(str.c_str(), str.size(), &result)) { @@ -607,7 +607,7 @@ ani_ref AniParseUtils::CreateAniStringArray(ani_env* env, const std::vectorArray_Set_Ref(array, i, item)) { return nullptr; } @@ -652,7 +652,7 @@ bool AniParseUtils::ParseInt64(ani_env* env, ani_ref ref, int64_t& outValue) } ani_boolean isLong; if (env->Object_InstanceOf(static_cast(ref), longClass, &isLong) != ANI_OK || isLong != ANI_TRUE) { - WVLOG_E("ParseInt64 failed - invalid double type"); + WVLOG_E("ParseInt64 failed - invalid long type"); return false; } diff --git a/interfaces/kits/ani/webview/src/common/ani_parse_utils.h b/interfaces/kits/ani/webview/src/common/ani_parse_utils.h index 93d0d0c27fec5bfc2ef994d112ef9c9de01aefe4..435c38f43812322de41688407bcd26233f0b3caa 100644 --- a/interfaces/kits/ani/webview/src/common/ani_parse_utils.h +++ b/interfaces/kits/ani/webview/src/common/ani_parse_utils.h @@ -54,6 +54,7 @@ public: static bool CreateBoolean(ani_env *env, bool src, ani_object& aniObj); static ani_object CreateDouble(ani_env *env, ani_double val); static ani_object CreateInt(ani_env *env, ani_int val); + static ani_string StringToAniStr(ani_env* env, const std::string& str); static ani_ref CreateAniStringArray(ani_env *env, const std::vector &paths); static bool ParseBoolean(ani_env* env, ani_ref ref, bool& outValue); static bool ParseInt64(ani_env* env, ani_ref ref, int64_t& outValue); diff --git a/interfaces/kits/ani/webview/src/sts_web_webview.cpp b/interfaces/kits/ani/webview/src/sts_web_webview.cpp index 5f7d847a473d2be04ab97dc5728d883d2f8bf408..5ad20ea896e590196f05b372815ccfc509df46f1 100644 --- a/interfaces/kits/ani/webview/src/sts_web_webview.cpp +++ b/interfaces/kits/ani/webview/src/sts_web_webview.cpp @@ -28,7 +28,9 @@ #include "nweb_log.h" #include "ani_geolocation_permission.h" #include "ani_web_adsblock_manager.h" - +#include "ani_web_scheme_handler.h" +#include "ani_web_scheme_handler_resource.h" +#include "ani_web_scheme_handler_request.h" namespace OHOS { namespace NWeb { @@ -60,6 +62,9 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) StsWebDataBaseInit(env); StsPdfDataInit(env); StsGeolocationPermissionInit(env); + StsWebSchemeHandlerResourceInit(env); + StsWebSchemeHandlerRequestInit(env); + StsWebSchemeHandlerInit(env); *result = ANI_VERSION_1; return ANI_OK; } diff --git a/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler.cpp b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b8ed103305c589130d6f74600bc872995a84ce86 --- /dev/null +++ b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2025 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 + +#include "ani_business_error.h" +#include "ani_native_media_player_handler.h" +#include "ani_parse_utils.h" +#include "ani_webview_controller.h" +#include "native_media_player_impl.h" +#include "nweb_helper.h" +#include "nweb_log.h" +#include "securec.h" +#include "web_errors.h" +#include "web_scheme_handler_request.h" + +namespace OHOS { +namespace NWeb { + +using namespace NWebError; +using NWebError::NO_ERROR; + +static void OnRequestStart(ani_env* env, ani_object object, ani_fn_object callback) +{ + WVLOG_I("SchemeHandler OnRequestStart"); + if (env == nullptr) { + WVLOG_E("[WebSchemeHandler] env is nullptr"); + return; + } + + auto* webSchemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!webSchemeHandler) { + WVLOG_E("[WebSchemeHandler] webSchemeHandler is null"); + return; + } + ani_vm* vm = nullptr; + env->GetVM(&vm); + webSchemeHandler->PutRequestStart(env, vm, callback); +} + +static void Constructor(ani_env* env, ani_object object) +{ + WVLOG_I("WebSchemeHandler native Constructor"); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return; + } + + WebSchemeHandler* webSchemeHandler = new (std::nothrow) WebSchemeHandler(env); + if (webSchemeHandler == nullptr) { + WVLOG_E("new WebSchemeHandler failed"); + return; + } + if (!AniParseUtils::Wrap( + env, object, WEB_WEBSCHEME_HANDLER_CLASS_NAME, reinterpret_cast(webSchemeHandler))) { + WVLOG_E("WebDownloadDelegate wrap failed"); + delete webSchemeHandler; + webSchemeHandler = nullptr; + } +} + +ani_status StsWebSchemeHandlerInit(ani_env* env) +{ + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return ANI_ERROR; + } + + ani_class WebSchemeHandlerCls = nullptr; + ani_status status = env->FindClass(WEB_WEBSCHEME_HANDLER_CLASS_NAME, &WebSchemeHandlerCls); + if (status != ANI_OK || !WebSchemeHandlerCls) { + WVLOG_E("find %{public}s class failed, status: %{public}d", WEB_WEBSCHEME_HANDLER_CLASS_NAME, status); + return ANI_ERROR; + } + std::array allMethods = { + ani_native_function { "", nullptr, reinterpret_cast(Constructor) }, + ani_native_function { "onRequestStart", "Lstd/core/Function2;:V", reinterpret_cast(OnRequestStart) }, + }; + + status = env->Class_BindNativeMethods(WebSchemeHandlerCls, allMethods.data(), allMethods.size()); + if (status != ANI_OK) { + WVLOG_E("Class_BindNativeMethods failed status: %{public}d", status); + } + return ANI_OK; +} + +} // namespace NWeb +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler.h b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..dc08e3e9865fb00e742a814fc859a0c8a9db7c11 --- /dev/null +++ b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 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. + */ +#ifndef OHOS_NWEB_ANI_WEB_SCHEME_HANDLER_H +#define OHOS_NWEB_ANI_WEB_SCHEME_HANDLER_H + +#include +extern ani_vm* g_vm; +namespace OHOS { +namespace NWeb { +ani_status StsWebSchemeHandlerInit(ani_env* env); +} // namespace NWeb +} // namespace OHOS +#endif // OHOS_NWEB_ANI_WEB_SCHEME_HANDLER_H \ No newline at end of file diff --git a/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_request.cpp b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_request.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a4ed86eec030fb2e83f37a328ab8fcc2b0cf7a41 --- /dev/null +++ b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_request.cpp @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2025 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 + +#include "ani_business_error.h" +#include "ani_native_media_player_handler.h" +#include "ani_parse_utils.h" +#include "ani_webview_controller.h" +#include "native_media_player_impl.h" +#include "nweb_helper.h" +#include "nweb_log.h" +#include "securec.h" +#include "web_errors.h" +#include "web_scheme_handler_request.h" + +namespace OHOS { +namespace NWeb { + +using namespace NWebError; +using NWebError::NO_ERROR; +namespace { +const char* ANI_CLASS_WEB_RESOURCETYPE = "L@ohos/web/webview/webview/WebResourceType;"; +} // namespace + +static ani_boolean JSHasGesture(ani_env* env, ani_object object) +{ + WVLOG_I("jSHasGesture start"); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return ANI_FALSE; + } + auto* stream = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!stream) { + WVLOG_E("stream is null"); + return ANI_FALSE; + } + return stream->HasGesture() ? ANI_TRUE : ANI_FALSE; +} + +static ani_string GetRequestMethod(ani_env* env, ani_object object) +{ + WVLOG_I("getRequestMethod start"); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return nullptr; + } + auto* request = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!request) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return nullptr; + } + char* referrer = request->GetMethod(); + if (referrer == nullptr) { + WVLOG_E("getRequestMethod: referrer is nullptr"); + return nullptr; + } + ani_string value; + if (env->String_NewUTF8(referrer, strlen(referrer), &value) != ANI_OK) { + WVLOG_E("getRequestMethod: failed to create ani_string value"); + return nullptr; + } + return value; +} + +static ani_boolean IsMainFrame(ani_env* env, ani_object object) +{ + WVLOG_I("isMainFrame start"); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return ANI_TRUE; + } + auto* request = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!request) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return ANI_TRUE; + } + ani_boolean value = (request->IsMainFrame() ? 1 : 0); + return value; +} + +static ani_string GetReferrer(ani_env* env, ani_object object) +{ + WVLOG_I("getReferrer start"); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return nullptr; + } + auto* request = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!request) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return nullptr; + } + char* referrer = request->GetReferrer(); + if (referrer == nullptr) { + WVLOG_E("GetReferrer: referrer is nullptr"); + return nullptr; + } + ani_string value; + if (env->String_NewUTF8(referrer, strlen(referrer), &value) != ANI_OK) { + WVLOG_E("GetReferrer: failed to create ani_string value"); + return nullptr; + } + return value; +} + +static ani_string GetFrameUrl(ani_env* env, ani_object object) +{ + WVLOG_I("GetFrameUrl start"); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return nullptr; + } + auto* request = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!request) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return nullptr; + } + ani_string url = nullptr; + char* result = request->GetFrameUrl(); + env->String_NewUTF8(result, strlen(result), &url); + OH_ArkWeb_ReleaseString(result); + return url; +} + +static ani_object GetRequestResourceType(ani_env* env, ani_object object) +{ + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return nullptr; + } + ani_int resourceType = 0; + ani_enum enumType; + env->FindEnum(ANI_CLASS_WEB_RESOURCETYPE, &enumType); + auto* request = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!request) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return nullptr; + } + resourceType = static_cast(request->GetRequestResourceType()); + ani_enum_item state; + env->Enum_GetEnumItemByIndex(enumType, resourceType, &state); + return state; +} + +static ani_string GetRequestUrl(ani_env* env, ani_object object) +{ + WVLOG_I("getRequestUrl start"); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return nullptr; + } + auto* request = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!request) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return nullptr; + } + char* referrer = request->GetRequestUrl(); + if (referrer == nullptr) { + WVLOG_E("getRequestUrl: referrer is nullptr"); + return nullptr; + } + ani_string value; + if (env->String_NewUTF8(referrer, strlen(referrer), &value) != ANI_OK) { + WVLOG_E("getRequestUrl: failed to create ani_string value"); + return nullptr; + } + return value; +} + +static ani_ref GetHeader(ani_env* env, ani_object object) +{ + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return nullptr; + } + auto* request = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!request) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return nullptr; + } + std::vector> values = request->GetHeader(); + ani_class stringCls; + if (ANI_OK != env->FindClass("L@ohos/web/webview/webview/GetHeaderWebHeader;", &stringCls)) { + WVLOG_E("getHeader find class failed."); + return nullptr; + } + ani_method personInfoCtor; + if (ANI_OK != env->Class_FindMethod(stringCls, "", nullptr, &personInfoCtor)) { + WVLOG_E("getHeader GetUndefined Failed."); + return nullptr; + } + ani_ref undefinedRef = nullptr; + if (ANI_OK != env->GetUndefined(&undefinedRef)) { + WVLOG_E("getHeader GetUndefined Failed."); + return nullptr; + } + ani_array_ref array = nullptr; + if (ANI_OK != env->Array_New_Ref(stringCls, values.size(), undefinedRef, &array)) { + WVLOG_E("getHeader new array ref error."); + return array; + } + for (size_t i = 0; i < values.size(); ++i) { + ani_string headerKey {}; + ani_string headerValue {}; + ani_object webHeaderObj = {}; + ani_status status; + status = env->Object_New(stringCls, personInfoCtor, &webHeaderObj); + if (status != ANI_OK) { + WVLOG_E("getHeader new object error."); + } + env->String_NewUTF8(values[i].first.c_str(), values[i].first.size(), &headerKey); + env->String_NewUTF8(values[i].second.c_str(), values[i].second.size(), &headerValue); + + if ((status = env->Object_SetPropertyByName_Ref(webHeaderObj, "headerKey", static_cast(headerKey))) != + ANI_OK) { + WVLOG_E("getHeader Set headerKey failed status = %{public}d", status); + return nullptr; + } + if (ANI_OK != env->Object_SetPropertyByName_Ref(webHeaderObj, "headerValue", headerValue)) { + WVLOG_E("getHeader Get headerValue failed"); + return nullptr; + } + env->Array_Set_Ref(array, i, webHeaderObj); + } + return array; +} + +static void Constructor(ani_env* env, ani_object object) +{ + WVLOG_I("WebSchemeHandlerRequest native Constructor"); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return; + } +} + +ani_status StsWebSchemeHandlerRequestInit(ani_env* env) +{ + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return ANI_ERROR; + } + + ani_class WebSchemeHandlerRequestCls = nullptr; + ani_status status = env->FindClass(WEB_WEBSCHEME_HANDLER_REQUEST_CLASS_NAME, &WebSchemeHandlerRequestCls); + if (status != ANI_OK || !WebSchemeHandlerRequestCls) { + WVLOG_E("find %{public}s class failed, status: %{public}d", WEB_WEBSCHEME_HANDLER_REQUEST_CLASS_NAME, status); + return ANI_ERROR; + } + std::array allMethods = { + ani_native_function { "", nullptr, reinterpret_cast(Constructor) }, + ani_native_function { "hasGesture", nullptr, reinterpret_cast(JSHasGesture) }, + ani_native_function { "getReferrer", nullptr, reinterpret_cast(GetReferrer) }, + ani_native_function { "getFrameUrl", nullptr, reinterpret_cast(GetFrameUrl) }, + ani_native_function { "getHeader", nullptr, reinterpret_cast(GetHeader) }, + ani_native_function { "getRequestResourceType", nullptr, reinterpret_cast(GetRequestResourceType) }, + ani_native_function { "getRequestUrl", nullptr, reinterpret_cast(GetRequestUrl) }, + ani_native_function { "isMainFrame", nullptr, reinterpret_cast(IsMainFrame) }, + ani_native_function { "getRequestMethod", nullptr, reinterpret_cast(GetRequestMethod) }, + }; + + status = env->Class_BindNativeMethods(WebSchemeHandlerRequestCls, allMethods.data(), allMethods.size()); + if (status != ANI_OK) { + WVLOG_E("Class_BindNativeMethods failed status: %{public}d", status); + } + return ANI_OK; +} + +} // namespace NWeb +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_request.h b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_request.h new file mode 100644 index 0000000000000000000000000000000000000000..c0276b257c43dd0e1909ec97a2e59f6037e4a913 --- /dev/null +++ b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_request.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 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. + */ +#ifndef OHOS_NWEB_ANI_WEB_SCHEME_HANDLER_REQUEST_H +#define OHOS_NWEB_ANI_WEB_SCHEME_HANDLER_REQUEST_H + +#include + +namespace OHOS { +namespace NWeb { +ani_status StsWebSchemeHandlerRequestInit(ani_env* env); +} // namespace NWeb +} // namespace OHOS +#endif // OHOS_NWEB_ANI_WEB_SCHEME_HANDLER_REQUEST_H \ No newline at end of file diff --git a/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_resource.cpp b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_resource.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f5626d90f70d02c6aea0ca4d01348747d22f3ec --- /dev/null +++ b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_resource.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2025 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 + +#include "ani_business_error.h" +#include "ani_native_media_player_handler.h" +#include "ani_parse_utils.h" +#include "native_media_player_impl.h" +#include "nweb_helper.h" +#include "nweb_log.h" +#include "securec.h" +#include "web_errors.h" +#include "web_scheme_handler_request.h" +#include "web_scheme_handler_response.h" + +namespace OHOS { +namespace NWeb { + +using namespace NWebError; +using NWebError::NO_ERROR; + +static void JSDidReceiveResponse(ani_env* env, ani_object object, ani_object response) +{ + WVLOG_I("Enter aniwebResourceHandler JSDidReceiveResponse"); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return; + } + auto* resourceHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!resourceHandler) { + WVLOG_E("stream is nullptr"); + return; + } + + auto* receiveResponse = reinterpret_cast(AniParseUtils::Unwrap(env, response)); + if (!receiveResponse) { + WVLOG_E("stream is nullptr"); + return; + } + + ani_long thisVar; + ani_status status = env->Object_GetFieldByName_Long(response, "nativePtr", &thisVar); + if (status != ANI_OK) { + WVLOG_E("AniUtils_Unwrap Object_GetFieldByName_Long status: %{public}d", status); + return; + } + + int32_t ret = resourceHandler->DidReceiveResponse(receiveResponse->GetArkWebResponse()); + WVLOG_I("aniwebResourceHandler JSDidReceiveResponse ret = %{public}d", ret); + if (ret != 0) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + } + return; +} + +static void JsDidFinish(ani_env* env, ani_object object) +{ + WVLOG_I("Enter aniwebResourceHandler JsDidFinish"); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return; + } + + auto* resourceHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!resourceHandler) { + WVLOG_E("stream is nullptr"); + return; + } + int32_t ret = resourceHandler->DidFinish(); + if (ret != 0) { + AniBusinessError::ThrowErrorByErrCode(env, RESOURCE_HANDLER_INVALID); + WVLOG_E("JsDidFinish ret=%{public}d", ret); + } + return; +} + +static void Constructor(ani_env* env, ani_object object) +{ + WVLOG_E("WebResourceHandler WebResourceHandler native Constructor"); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return; + } +} + +ani_status StsWebSchemeHandlerResourceInit(ani_env* env) +{ + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return ANI_ERROR; + } + + ani_class WebResourceCls = nullptr; + ani_status status = env->FindClass(WEB_RESOURCE_HANDLER_CLASS_NAME, &WebResourceCls); + if (status != ANI_OK || !WebResourceCls) { + WVLOG_E("find %{public}s class failed, status: %{public}d", WEB_RESOURCE_HANDLER_CLASS_NAME, status); + return ANI_ERROR; + } + std::array allMethods = { + ani_native_function { "", nullptr, reinterpret_cast(Constructor) }, + ani_native_function { "didFinish", nullptr, reinterpret_cast(JsDidFinish) }, + ani_native_function { "didReceiveResponse", nullptr, reinterpret_cast(JSDidReceiveResponse) }, + }; + + status = env->Class_BindNativeMethods(WebResourceCls, allMethods.data(), allMethods.size()); + if (status != ANI_OK) { + WVLOG_E("Class_BindNativeMethods failed status: %{public}d", status); + } + return ANI_OK; +} + +} // namespace NWeb +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_resource.h b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_resource.h new file mode 100644 index 0000000000000000000000000000000000000000..f00e70adba42e4f6040c305fd53e6ccafdf3514e --- /dev/null +++ b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_resource.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 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. + */ +#ifndef OHOS_NWEB_ANI_WEB_SCHEME_HANDLER_RESOURCE_H +#define OHOS_NWEB_ANI_WEB_SCHEME_HANDLER_RESOURCE_H + +#include + +namespace OHOS { +namespace NWeb { +ani_status StsWebSchemeHandlerResourceInit(ani_env* env); +} // namespace NWeb +} // namespace OHOS +#endif // OHOS_NWEB_ANI_WEB_SCHEME_HANDLER_RESOURCE_H \ No newline at end of file diff --git a/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_response.cpp b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_response.cpp index 9a41c005e9e4bd26d7612c02cce2c4b46cbb7853..db4eb3566ac0c5e35e40443b2af5a65229ca74b5 100644 --- a/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_response.cpp +++ b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_response.cpp @@ -16,13 +16,12 @@ #include #include -#include "webview_controller.h" -#include "web_scheme_handler_response.h" - #include "ani_business_error.h" #include "ani_parse_utils.h" #include "nweb_log.h" #include "web_errors.h" +#include "web_scheme_handler_response.h" +#include "webview_controller.h" namespace OHOS { namespace NWeb { @@ -33,14 +32,14 @@ namespace { const char* WEB_SCHEME_HANDLER_RESPONSE_CLASS_NAME = "L@ohos/web/webview/webview/WebSchemeHandlerResponse;"; } -static void JsSetUrl(ani_env *env, ani_object object, ani_object urlObject) +static void JsSetUrl(ani_env* env, ani_object object, ani_object urlObject) { WVLOG_D("WebSchemeHandlerResponse JsSetUrl."); if (env == nullptr) { WVLOG_E("env is nullptr"); return; } - auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); if (!schemeHandler) { AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); return; @@ -53,19 +52,19 @@ static void JsSetUrl(ani_env *env, ani_object object, ani_object urlObject) return; } if (!AniParseUtils::IsString(env, urlObject)) { - AniBusinessError::ThrowError(env, PARAM_CHECK_ERROR, - NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "url", "string")); + AniBusinessError::ThrowError( + env, PARAM_CHECK_ERROR, NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "url", "string")); return; } std::string url; if (!AniParseUtils::ParseString(env, urlObject, url)) { - WVLOG_E("ParseString fail"); + WVLOG_E("ParseString fail"); return; } schemeHandler->SetUrl(url.c_str()); } -static ani_string JsGetUrl(ani_env *env, ani_object object) +static ani_string JsGetUrl(ani_env* env, ani_object object) { WVLOG_D("WebSchemeHandlerResponse JsGetUrl."); ani_string url = nullptr; @@ -73,7 +72,7 @@ static ani_string JsGetUrl(ani_env *env, ani_object object) WVLOG_E("env is nullptr"); return url; } - auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); if (!schemeHandler) { AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); return url; @@ -87,7 +86,261 @@ static ani_string JsGetUrl(ani_env *env, ani_object object) return url; } -static void Constructor(ani_env *env, ani_object object) +static void JsSetMimeType(ani_env* env, ani_object object, ani_object mimeTypeObject) +{ + WVLOG_D("WebSchemeHandlerResponse JsSetMimeType."); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return; + } + auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!schemeHandler) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return; + } + ani_boolean isUndefined = true; + if (env->Reference_IsUndefined(mimeTypeObject, &isUndefined) != ANI_OK || isUndefined) { + AniBusinessError::ThrowError(env, PARAM_CHECK_ERROR, + NWebError::FormatString(ParamCheckErrorMsgTemplate::PARAM_NUMBERS_ERROR_ONE, "one")); + return; + } + if (!AniParseUtils::IsString(env, mimeTypeObject)) { + AniBusinessError::ThrowError( + env, PARAM_CHECK_ERROR, NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "type", "string")); + return; + } + std::string mimeType; + if (!AniParseUtils::ParseString(env, mimeTypeObject, mimeType)) { + WVLOG_E("ParseString fail"); + return; + } + schemeHandler->SetMimeType(mimeType.c_str()); +} + +static ani_string JsGetMimeType(ani_env* env, ani_object object) +{ + WVLOG_D("WebSchemeHandlerResponse JsGetMimeType."); + ani_string mimeType = nullptr; + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return mimeType; + } + auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!schemeHandler) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return mimeType; + } + char* result = schemeHandler->GetMimeType(); + if (result == nullptr) { + return mimeType; + } + env->String_NewUTF8(result, strlen(result), &mimeType); + OH_ArkWeb_ReleaseString(result); + return mimeType; +} + +static void JsSetEncoding(ani_env* env, ani_object object, ani_object encodingObject) +{ + WVLOG_D("WebSchemeHandlerResponse JsSetEncoding."); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return; + } + auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!schemeHandler) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return; + } + ani_boolean isUndefined = true; + if (env->Reference_IsUndefined(encodingObject, &isUndefined) != ANI_OK || isUndefined) { + AniBusinessError::ThrowError(env, PARAM_CHECK_ERROR, + NWebError::FormatString(ParamCheckErrorMsgTemplate::PARAM_NUMBERS_ERROR_ONE, "one")); + return; + } + if (!AniParseUtils::IsString(env, encodingObject)) { + AniBusinessError::ThrowError(env, PARAM_CHECK_ERROR, + NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "encoding", "string")); + return; + } + std::string encoding; + if (!AniParseUtils::ParseString(env, encodingObject, encoding)) { + WVLOG_E("ParseString fail"); + return; + } + schemeHandler->SetEncoding(encoding.c_str()); +} + +static ani_string JsGetEncoding(ani_env* env, ani_object object) +{ + WVLOG_D("WebSchemeHandlerResponse JsGetEncoding."); + ani_string encoding = nullptr; + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return encoding; + } + auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!schemeHandler) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return encoding; + } + char* result = schemeHandler->GetEncoding(); + if (result == nullptr) { + return encoding; + } + env->String_NewUTF8(result, strlen(result), &encoding); + OH_ArkWeb_ReleaseString(result); + return encoding; +} + +static void JsSetStatusText(ani_env* env, ani_object object, ani_object statusTextObject) +{ + WVLOG_D("WebSchemeHandlerResponse JsSetStatusText."); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return; + } + auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!schemeHandler) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return; + } + ani_boolean isUndefined = true; + if (env->Reference_IsUndefined(statusTextObject, &isUndefined) != ANI_OK || isUndefined) { + AniBusinessError::ThrowError(env, PARAM_CHECK_ERROR, + NWebError::FormatString(ParamCheckErrorMsgTemplate::PARAM_NUMBERS_ERROR_ONE, "one")); + return; + } + if (!AniParseUtils::IsString(env, statusTextObject)) { + AniBusinessError::ThrowError( + env, PARAM_CHECK_ERROR, NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "text", "string")); + return; + } + std::string statusText; + if (!AniParseUtils::ParseString(env, statusTextObject, statusText)) { + WVLOG_E("ParseString fail"); + return; + } + schemeHandler->SetStatusText(statusText.c_str()); +} + +static ani_string JsGetStatusText(ani_env* env, ani_object object) +{ + WVLOG_D("WebSchemeHandlerResponse JsGetStatusText."); + ani_string statusText = nullptr; + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return statusText; + } + auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!schemeHandler) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return statusText; + } + char* result = schemeHandler->GetStatusText(); + if (result == nullptr) { + return statusText; + } + env->String_NewUTF8(result, strlen(result), &statusText); + OH_ArkWeb_ReleaseString(result); + return statusText; +} + +static void JsSetStatus(ani_env* env, ani_object object, ani_double statusValue) +{ + WVLOG_D("WebSchemeHandlerResponse JsSetStatus."); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return; + } + auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!schemeHandler) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return; + } + schemeHandler->SetStatus(static_cast(statusValue)); +} + +static ani_double JsGetStatus(ani_env* env, ani_object object) +{ + WVLOG_D("WebSchemeHandlerResponse JsGetStatus."); + ani_double result = 0; + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return result; + } + auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!schemeHandler) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return result; + } + double value = schemeHandler->GetStatus(); + result = static_cast(value); + return result; +} + +static void JsSetHeaderByName( + ani_env* env, ani_object object, ani_object nameObject, ani_object valueObject, ani_boolean overWriteObject) +{ + WVLOG_D("WebSchemeHandlerResponse JsSetHeaderByName."); + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return; + } + auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!schemeHandler) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return; + } + if (!AniParseUtils::IsString(env, nameObject)) { + AniBusinessError::ThrowError( + env, PARAM_CHECK_ERROR, NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "name", "string")); + return; + } + if (!AniParseUtils::IsString(env, valueObject)) { + AniBusinessError::ThrowError( + env, PARAM_CHECK_ERROR, NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "value", "string")); + return; + } + std::string name; + std::string value; + if (!AniParseUtils::ParseString(env, nameObject, name)) { + WVLOG_E("ParseString fail"); + return; + } + if (!AniParseUtils::ParseString(env, valueObject, value)) { + WVLOG_E("ParseString fail"); + return; + } + schemeHandler->SetHeaderByName(name.c_str(), value.c_str(), static_cast(overWriteObject)); +} + +static ani_string JsGetHeaderByName(ani_env* env, ani_object object, ani_object nameObject) +{ + WVLOG_D("WebSchemeHandlerResponse JsGetHeaderByName."); + ani_string headerValue = nullptr; + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return headerValue; + } + auto* schemeHandler = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!schemeHandler) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return headerValue; + } + std::string name; + if (!AniParseUtils::ParseString(env, nameObject, name)) { + return nullptr; + } + char* result = schemeHandler->GetHeaderByName(name.c_str()); + if (result == nullptr) { + return headerValue; + } + env->String_NewUTF8(result, strlen(result), &headerValue); + OH_ArkWeb_ReleaseString(result); + return headerValue; +} + +static void Constructor(ani_env* env, ani_object object) { WVLOG_D("WebSchemeHandlerResponse native Constructor"); if (env == nullptr) { @@ -100,15 +353,15 @@ static void Constructor(ani_env *env, ani_object object) WVLOG_E("new webview controller failed"); return; } - if (!AniParseUtils::Wrap(env, object, WEB_SCHEME_HANDLER_RESPONSE_CLASS_NAME, - reinterpret_cast(schemeHandler))) { + if (!AniParseUtils::Wrap( + env, object, WEB_SCHEME_HANDLER_RESPONSE_CLASS_NAME, reinterpret_cast(schemeHandler))) { WVLOG_E("WebSchemeHandlerResponse wrap failed"); delete schemeHandler; schemeHandler = nullptr; } } -ani_status StsWebSchemeHandlerResponseInit(ani_env *env) +ani_status StsWebSchemeHandlerResponseInit(ani_env* env) { if (env == nullptr) { WVLOG_E("env is nullptr"); @@ -121,9 +374,19 @@ ani_status StsWebSchemeHandlerResponseInit(ani_env *env) return ANI_ERROR; } std::array allMethods = { - ani_native_function { "", nullptr, reinterpret_cast(Constructor) }, - ani_native_function { "setUrl", nullptr, reinterpret_cast(JsSetUrl) }, - ani_native_function { "getUrl", nullptr, reinterpret_cast(JsGetUrl) }, + ani_native_function { "", nullptr, reinterpret_cast(Constructor) }, + ani_native_function { "setUrl", nullptr, reinterpret_cast(JsSetUrl) }, + ani_native_function { "getUrl", nullptr, reinterpret_cast(JsGetUrl) }, + ani_native_function { "setMimeType", nullptr, reinterpret_cast(JsSetMimeType) }, + ani_native_function { "getMimeType", nullptr, reinterpret_cast(JsGetMimeType) }, + ani_native_function { "setEncoding", nullptr, reinterpret_cast(JsSetEncoding) }, + ani_native_function { "getEncoding", nullptr, reinterpret_cast(JsGetEncoding) }, + ani_native_function { "setStatusText", nullptr, reinterpret_cast(JsSetStatusText) }, + ani_native_function { "getStatusText", nullptr, reinterpret_cast(JsGetStatusText) }, + ani_native_function { "setStatus", nullptr, reinterpret_cast(JsSetStatus) }, + ani_native_function { "getStatus", nullptr, reinterpret_cast(JsGetStatus) }, + ani_native_function { "setHeaderByName", nullptr, reinterpret_cast(JsSetHeaderByName) }, + ani_native_function { "getHeaderByName", nullptr, reinterpret_cast(JsGetHeaderByName) }, }; status = env->Class_BindNativeMethods(webSchemeHandlerResponseCls, allMethods.data(), allMethods.size()); diff --git a/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_response.h b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_response.h new file mode 100644 index 0000000000000000000000000000000000000000..cea6f00e8cd16b2be22b3e53aaa67f4f13a789c9 --- /dev/null +++ b/interfaces/kits/ani/webview/src/webviewcontroller/ani_web_scheme_handler_response.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 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. + */ +#ifndef OHOS_NWEB_ANI_WEB_SCHEME_HANDLER_RESPONSE_H +#define OHOS_NWEB_ANI_WEB_SCHEME_HANDLER_RESPONSE_H + +#include + +namespace OHOS { +namespace NWeb { +ani_status StsWebHttpBodyStreamInit(ani_env* env); +} // namespace NWeb +} // namespace OHOS +#endif // OHOS_NWEB_ANI_WEB_SCHEME_HANDLER_RESPONSE_H \ No newline at end of file diff --git a/interfaces/kits/ani/webview/src/webviewcontroller/ani_webview_controller.cpp b/interfaces/kits/ani/webview/src/webviewcontroller/ani_webview_controller.cpp index 3938a64376c75bfe3158471fe2bb25efa814bea0..f1ac021147a2937bd294ac39d18f2cd2d0ccad48 100644 --- a/interfaces/kits/ani/webview/src/webviewcontroller/ani_webview_controller.cpp +++ b/interfaces/kits/ani/webview/src/webviewcontroller/ani_webview_controller.cpp @@ -58,12 +58,15 @@ #include "web_download_manager.h" #include "pixel_map.h" #include "pixel_map_ani.h" -// #include "pixel_map_taihe_ani.h" +#include "pixel_map_taihe_ani.h" #include "proxy_config.h" #include "ani_parse_utils.h" #include "web_scheme_handler_response.h" #include "web_download_item.h" #include "ani_webview_createpdf_execute_callback.h" +#include "ani_web_scheme_handler_request.h" +#include "web_scheme_handler_request.h" +#include "arkweb_scheme_handler.h" namespace OHOS { namespace NWeb { @@ -431,6 +434,12 @@ static void Clean(ani_env *env, ani_object object) delete reinterpret_cast(ptr); } else if (clsName == "WebMessagePort") { delete reinterpret_cast(ptr); + } else if (clsName == "WebSchemeHandler") { + delete reinterpret_cast(ptr); + } else if (clsName == "WebSchemeHandlerRequest") { + delete reinterpret_cast(ptr); + } else if (clsName == "WebResourceHandler") { + reinterpret_cast(ptr)->DecStrongRef(reinterpret_cast(ptr)); } else { WVLOG_E("Clean unsupport className: %{public}s", clsName.c_str()); } @@ -2010,6 +2019,78 @@ static void ClearHistory(ani_env *env, ani_object object) controller->ClearHistory(); } +void SetWebSchemeHandler(ani_env* env, ani_object object, ani_string scheme, ani_object handlerObject) +{ + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return; + } + auto* controller = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!controller || !controller->IsInit()) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + return; + } + std::string schemeStr = ""; + if (!AniParseUtils::ParseString(env, scheme, schemeStr)) { + AniBusinessError::ThrowError(env, PARAM_CHECK_ERROR, + NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "scheme", "string")); + return; + } + WebSchemeHandler* handler = nullptr; + ani_long thisVar; + ani_status status = env->Object_GetFieldByName_Long(handlerObject, "nativePtr", &thisVar); + if (status != ANI_OK) { + WVLOG_E("AniUtils_Unwrap Object_GetFieldByName_Long status: %{public}d", status); + return; + } + handler = reinterpret_cast(thisVar); + if (!handler) { + WVLOG_E("AniWebviewController::SetWebSchemeHandler handler is null"); + return; + } + if (!controller->SetWebSchemeHandler(schemeStr.c_str(), handler)) { + WVLOG_E("AniWebviewController::SetWebSchemeHandler failed"); + } + return; +} + +static void SetServiceWorkerWebSchemeHandler( + ani_env* env, ani_object object, ani_string scheme, ani_object handlerObject) +{ + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return; + } + std::string schemePtr = ""; + if (!AniParseUtils::ParseString(env, scheme, schemePtr)) { + WVLOG_E("AniWebviewController::SetWebSchemeHandler parse scheme failed"); + AniBusinessError::ThrowError(env, PARAM_CHECK_ERROR, + NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "scheme", "string")); + return; + } + WebSchemeHandler* handler = nullptr; + ani_long thisVar; + ani_status status = env->Object_GetFieldByName_Long(handlerObject, "nativePtr", &thisVar); + if (status != ANI_OK) { + WVLOG_E("AniUtils_Unwrap Object_GetFieldByName_Long status: %{public}d", status); + return; + } + handler = reinterpret_cast(thisVar); + if (!handler) { + AniBusinessError::ThrowErrorByErrCode(env, INIT_ERROR); + WVLOG_E("Unwrap WebSchemeHandler failed"); + return; + } + if (ANI_OK != env->GlobalReference_Create(handlerObject, &handler->delegate_)) { + WVLOG_E("SetServiceWorkerWebSchemeHandler failed to create reference for callback"); + return; + } + if (!WebviewController::SetWebServiveWorkerSchemeHandler(schemePtr.c_str(), handler)) { + WVLOG_E("AniWebviewController::SetWebSchemeHandler failed"); + } + return; +} + static void ClearWebSchemeHandler(ani_env *env, ani_object object) { if (env == nullptr) { @@ -3185,8 +3266,8 @@ WebSnapshotCallback CreateWebPageSnapshotResultCallback( uint64_t stride = static_cast(returnWidth) << 2; uint64_t bufferSize = stride * static_cast(returnHeight); pixelMap->WritePixels(static_cast(returnData), bufferSize); - // std::shared_ptr pixelMapToJs(pixelMap.release()); - // jsPixelMap = OHOS::Media::PixelMapTaiheAni::CreateEtsPixelMap(env, pixelMapToJs); + std::shared_ptr pixelMapToJs(pixelMap.release()); + jsPixelMap = OHOS::Media::PixelMapTaiheAni::CreateEtsPixelMap(env, pixelMapToJs); } else { WVLOG_E("WebPageSnapshot create pixel map error"); } @@ -3991,7 +4072,7 @@ ani_object ConvertToAniHandlerOfInt64Array(ani_env* env, std::shared_ptr(values[i]); + ani_long item = static_cast(values[i]); ani_class cls {}; if (ANI_OK != env->FindClass("Lstd/core/Long;", &cls)) { return nullptr; @@ -4255,6 +4336,8 @@ ani_status StsWebviewControllerInit(ani_env *env) ani_native_function { "getMediaPlaybackState", nullptr, reinterpret_cast(GetMediaPlaybackState) }, ani_native_function { "webPageSnapshot", nullptr, reinterpret_cast(WebPageSnapshot) }, ani_native_function { "innerCompleteWindowNew", nullptr, reinterpret_cast(InnerCompleteWindowNew) }, + ani_native_function { "setWebSchemeHandler", nullptr, reinterpret_cast(SetWebSchemeHandler) }, + ani_native_function { "setServiceWorkerWebSchemeHandler", nullptr, reinterpret_cast(SetServiceWorkerWebSchemeHandler) }, }; status = env->Class_BindNativeMethods(webviewControllerCls, controllerMethods.data(), controllerMethods.size()); diff --git a/interfaces/kits/ani/webview/src/webviewcontroller/ani_webview_controller.h b/interfaces/kits/ani/webview/src/webviewcontroller/ani_webview_controller.h index 68577cbc5fd76b05378b43a8527b322af95ba3d8..f158247ecc3bfe7d7353de09345f62e662070f8d 100644 --- a/interfaces/kits/ani/webview/src/webviewcontroller/ani_webview_controller.h +++ b/interfaces/kits/ani/webview/src/webviewcontroller/ani_webview_controller.h @@ -40,6 +40,9 @@ ani_status StsWebDownLoadItemInit(ani_env *env); ani_status StsWebDownloadManagerInit(ani_env *env); ani_status StsWebCookieManagerInit(ani_env *env); ani_status StsNativeMediaPlayerHandlerinnerInit(ani_env *env); +ani_status StsWebSchemeHandlerResourceInit(ani_env *env); +ani_status StsWebSchemeHandlerRequestInit(ani_env *env); +ani_status StsWebSchemeHandlerInit(ani_env *env); } // namespace NWeb } // namespace OHOS #endif // OHOS_NWEB_ANI_WEBVIEW_CONTROLLER_H \ No newline at end of file diff --git a/interfaces/kits/ani/webview/src/webviewcontroller/web_schme_handler_request.h b/interfaces/kits/ani/webview/src/webviewcontroller/web_schme_handler_request.h deleted file mode 100644 index ce746c5ba259864d44250d12cc19c34e4a214f02..0000000000000000000000000000000000000000 --- a/interfaces/kits/ani/webview/src/webviewcontroller/web_schme_handler_request.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2025 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. - */ - -#ifndef OHOS_NWEB_ANI_SCHEME_HANDLER_REQUEST_H -#define OHOS_NWEB_ANI_SCHEME_HANDLER_REQUEST_H - -#include -#include -#include - -#include "arkweb_scheme_handler.h" -#include "refbase.h" - -namespace OHOS { -namespace NWeb { - -class WebSchemeHandler { -public: - explicit WebSchemeHandler(ani_env *env); - ~WebSchemeHandler(); - - static const ArkWeb_SchemeHandler* GetArkWebSchemeHandler( - WebSchemeHandler* handler); - static WebSchemeHandler* GetWebSchemeHandler( - const ArkWeb_SchemeHandler* handler); - - void RequestStart(ArkWeb_ResourceRequest* request, - const ArkWeb_ResourceHandler* ArkWeb_ResourceHandler, - bool* intercept); - void RequestStop(const ArkWeb_ResourceRequest* resourceRequest); - - void PutRequestStart(ani_env *env, napi_value callback); - void PutRequestStop(ani_env *env, napi_value callback); - - napi_ref delegate_ = nullptr; - static std::unordered_map - webSchemeHandlerMap_; - static std::unordered_map - arkWebSchemeHandlerMap_; -private: - typedef struct RequestStopParam { - ani_env *env_; - ani_ref callbackRef_; - WebSchemeHandlerRequest* request_; - const ArkWeb_ResourceRequest* arkWebRequest_; - } RequestStopParam; - - static void RequestStopAfterWorkCb(uv_work_t* work, int status); - - ani_env *env_; - ArkWeb_OnRequestStart onRequestStart_ = nullptr; - ArkWeb_OnRequestStop onRequestStop_ = nullptr; - ani_ref request_start_callback_ = nullptr; - ani_ref request_stop_callback_ = nullptr; -}; - -} // namespace NWeb -} // namespace OHOS -#endif // OHOS_NWEB_ANI_SCHEME_HANDLER_REQUEST_H \ No newline at end of file