Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement onShouldStartLoadWithRequest and webView turboModule #250

Merged
merged 2 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 42 additions & 3 deletions harmony/rn_webview/src/main/ets/RNCWebView.ets
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import { RNComponentContext } from '@rnoh/react-native-openharmony';
import webview from '@ohos.web.webview';
import { url as OSUrl } from '@kit.ArkTS';
import { RNC } from '@rnoh/react-native-openharmony/generated';
import { RNC, TM } from '@rnoh/react-native-openharmony/generated';
import Logger from './Logger';
import { BaseOperate } from './WebViewBaseOperate';
import {
Expand All @@ -45,6 +45,7 @@ import {
REFRESH_OFFSET,
MINHEIGHT,
} from './Magic';
import { WebViewTurboModule } from './WebViewTurboModule';
import { bundleManager } from '@kit.AbilityKit';

export const TAG = "WebView"
Expand Down Expand Up @@ -97,6 +98,8 @@ export struct RNCWebView {
private cleanUpCallbacks: (() => void)[] = []
private descriptorWrapper: WebViewDescriptor = Object() as WebViewDescriptor
private webViewBaseOperate: BaseOperate | null = null
private shouldInterceptLoad: boolean = true
static readonly SHOULD_OVERRIDE_URL_LOADING_TIMEOUT: number = 250

aboutToAppear() {
try {
Expand Down Expand Up @@ -261,14 +264,15 @@ export struct RNCWebView {
controllerAttachedInit(): void {
this.controllerAttached = true;
this.eventEmitter = new RNC.RNCWebView.EventEmitter(this.ctx.rnInstance, this.tag)
this.webViewBaseOperate = new BaseOperate(this.eventEmitter, this.controller)
this.webViewBaseOperate = new BaseOperate(this.tag, this.eventEmitter, this.controller)
this.webViewBaseOperate.setCustomUserAgent(this.descriptorWrapper.rawProps.userAgent,
this.descriptorWrapper.rawProps.applicationNameForUserAgent)
this.webViewBaseOperate.setFraudulentWebsiteWarningEnabled(this.descriptorWrapper.rawProps.fraudulentWebsiteWarningEnabled)
let baseUrl = this.source.baseUrl
let uri = this.source.uri
if (this.source.html != undefined && this.source.html != "") {
try {
this.shouldInterceptLoad = true
this.controller.loadData(
this.source.html,
"text/html",
Expand All @@ -280,8 +284,10 @@ export struct RNCWebView {
Logger.error(TAG, "error:" + error)
}
} else if (uri != undefined && uri != "") {
this.shouldInterceptLoad = true
this.controller.loadUrl(uri, this.headers);
} else {
this.shouldInterceptLoad = true
this.controller.loadUrl(uri, this.headers);
}
if (!this.hasRegisterJavaScriptProxy) {
Expand Down Expand Up @@ -352,8 +358,38 @@ export struct RNCWebView {
}

onLoadIntercept(event: OnLoadInterceptEvent): boolean {
if (!this.shouldInterceptLoad) {
return false
}

let webViewTurboModule = this.ctx.rnInstance.getUITurboModule<WebViewTurboModule>(TM.RNCWebViewModule.NAME)
let timer = setTimeout(()=>{
webViewTurboModule.callLoadFunction(this.tag)
}, RNCWebView.SHOULD_OVERRIDE_URL_LOADING_TIMEOUT)

webViewTurboModule.setLoadCallback(this.tag, ()=>{
clearTimeout(timer)
this.shouldInterceptLoad = false
Logger.debug(TAG, "call setLoadCallback")
if (this.html != "") {
try {
this.controller.loadData(
this.source.html,
"text/html",
"UTF-8",
this.source.baseUrl,
" "
);
} catch (error) {
Logger.error(TAG, "error: " + error)
}
} else if (this.source.uri != "") {
Logger.debug(TAG, `[RNOH] newDescriptor props update uri: ` + this.source.uri);
this.controller.loadUrl(this.descriptorWrapper.rawProps.newSource.uri, this.headers)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

都为空的时候是否需要添加判断

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

进入加载拦截的回调中都是有url 或者data的,前面加载前已经做了判断处理

Copy link

@ninjarz ninjarz Nov 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.descriptorWrapper.rawProps.newSource.uri 导致 asset:// 转换失效了
@425765923

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果没有onShouldStartLoadWithRequest使用需求,建议0.2.33版本webview。当前版本onShouldStartLoadWithRequest实现的适用场景比较有限,完整实现需要依赖后续rnoh接口。若目前对该接口有简单需求,也可修改arkts实现代码,将rn拦截逻辑放置与原生端做规避。

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

})
this.webViewBaseOperate?.emitShouldStartLoadWithRequest(event)
return false
return true
}

onOverrideUrlLoading(event: WebResourceRequest) {
Expand Down Expand Up @@ -444,6 +480,7 @@ export struct RNCWebView {
this.html = this.source.html
if (this.controllerAttached) {
try {
this.shouldInterceptLoad = true
this.controller.loadData(
this.source.html,
"text/html",
Expand All @@ -459,6 +496,7 @@ export struct RNCWebView {
Logger.debug(TAG, `[RNOH] newDescriptor props update uri: ` + this.source.uri);
this.url = this.source.uri as string;
if (this.controllerAttached) {
this.shouldInterceptLoad = true
this.controller.loadUrl(this.descriptorWrapper.rawProps.newSource.uri, this.headers)
}
}
Expand Down Expand Up @@ -536,6 +574,7 @@ export struct RNCWebView {
}
};
this.controller.registerJavaScriptProxy(bridge, JAVASCRIPT_INTERFACE, ["postMessage"])
this.shouldInterceptLoad = true
this.source.uri ?
this.controller.loadUrl(this.source.uri, this.headers) : this.controller.refresh()
this.hasRegisterJavaScriptProxy = true
Expand Down
23 changes: 21 additions & 2 deletions harmony/rn_webview/src/main/ets/RNCWebViewPackage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,32 @@ import type {
DescriptorWrapperFactoryByDescriptorType,
DescriptorWrapperFactoryByDescriptorTypeCtx,
} from '@rnoh/react-native-openharmony/ts';
import { RNPackage } from '@rnoh/react-native-openharmony/ts';
import { RNC } from '@rnoh/react-native-openharmony/generated/ts';
import { RNPackage, UITurboModuleFactory, UITurboModule } from '@rnoh/react-native-openharmony/ts';
import { RNC, TM } from '@rnoh/react-native-openharmony/generated/ts';
import { WebViewTurboModule } from './WebViewTurboModule'
import { UITurboModuleContext } from '@rnoh/react-native-openharmony/src/main/ets/RNOH/RNOHContext';

export class RNCWebViewPackage extends RNPackage {
createDescriptorWrapperFactoryByDescriptorType(ctx: DescriptorWrapperFactoryByDescriptorTypeCtx): DescriptorWrapperFactoryByDescriptorType {
return {
[RNC.RNCWebView.NAME]: (ctx) => new RNC.RNCWebView.DescriptorWrapper(ctx.descriptor)
}
}

createUITurboModuleFactory(ctx: UITurboModuleContext): UITurboModuleFactory {
return new WebViewTurboModulesFactory(ctx);
}
}

class WebViewTurboModulesFactory extends UITurboModuleFactory {
createTurboModule(name: string): UITurboModule | null {
if (name === TM.RNCWebViewModule.NAME) {
return new WebViewTurboModule(this.ctx);
}
return null;
}

hasTurboModule(name: string): boolean {
return name === TM.RNCWebViewModule.NAME;
}
}
19 changes: 10 additions & 9 deletions harmony/rn_webview/src/main/ets/WebViewBaseOperate.ets
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ interface CreateWebViewEventInterface {
export class BaseOperate {
private eventEmitter: RNC.RNCWebView.EventEmitter
private controller: webview.WebviewController
private title: string = ''
private tag: number

constructor(eventEmitter: RNC.RNCWebView.EventEmitter, controller: webview.WebviewController) {
constructor(tag: number, eventEmitter: RNC.RNCWebView.EventEmitter, controller: webview.WebviewController) {
this.tag = tag
this.eventEmitter = eventEmitter
this.controller = controller
}
Expand Down Expand Up @@ -52,7 +53,7 @@ export class BaseOperate {
title: this.controller.getTitle(),
canGoBack: this.controller.accessBackward(),
canGoForward: this.controller.accessForward(),
lockIdentifier: 0,
lockIdentifier: this.tag,
progress: params.progress / ONE_HUNDRED
})
} catch (error) {
Expand All @@ -68,7 +69,7 @@ export class BaseOperate {
title: this.controller.getTitle(),
canGoBack: this.controller.accessBackward(),
canGoForward: this.controller.accessForward(),
lockIdentifier: 0,
lockIdentifier: this.tag,
navigationType: "other",
mainDocumentURL: ""
})
Expand All @@ -85,7 +86,7 @@ export class BaseOperate {
title: this.controller.getTitle(),
canGoBack: this.controller.accessBackward(),
canGoForward: this.controller.accessForward(),
lockIdentifier: 0,
lockIdentifier: this.tag,
navigationType: "other",
mainDocumentURL: ""
})
Expand All @@ -106,7 +107,7 @@ export class BaseOperate {
title: this.controller.getTitle(),
canGoBack: this.controller.accessBackward(),
canGoForward: this.controller.accessForward(),
lockIdentifier: 0,
lockIdentifier: this.tag,
domain: "",
code: event.error.getErrorCode(),
description: event.error.getErrorInfo()
Expand All @@ -124,7 +125,7 @@ export class BaseOperate {
title: this.controller.getTitle(),
canGoBack: this.controller.accessBackward(),
canGoForward: this.controller.accessForward(),
lockIdentifier: 0,
lockIdentifier: this.tag,
description: event.response.getResponseData(),
statusCode: event.response.getResponseCode()
})
Expand Down Expand Up @@ -159,7 +160,7 @@ export class BaseOperate {
title: this.controller.getTitle(),
canGoBack: this.controller.accessBackward(),
canGoForward: this.controller.accessForward(),
lockIdentifier: 0,
lockIdentifier: this.tag,
navigationType: "other",
mainDocumentURL: "",
isTopFrame: false
Expand All @@ -177,7 +178,7 @@ export class BaseOperate {
title: this.controller.getTitle(),
canGoBack: this.controller.accessBackward(),
canGoForward: this.controller.accessForward(),
lockIdentifier: 0,
lockIdentifier: this.tag,
navigationType: "other",
mainDocumentURL: "",
isTopFrame: false
Expand Down
27 changes: 27 additions & 0 deletions harmony/rn_webview/src/main/ets/WebViewTurboModule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { UITurboModule } from '@rnoh/react-native-openharmony/ts';
import { TM } from '@rnoh/react-native-openharmony/generated/ts';

export class WebViewTurboModule extends UITurboModule implements TM.RNCWebViewModule.Spec {
private loadCallbackMap : Map<number,()=> void> = new Map();

isFileUploadSupported(): Promise<boolean> {
return Promise.resolve(true)
}

shouldStartLoadWithLockIdentifier(shouldStart: boolean, lockIdentifier: number): void {
if (shouldStart) {
this.callLoadFunction(lockIdentifier)
}else {
this.loadCallbackMap.delete(lockIdentifier)
}
}

setLoadCallback(tag:number, cb: ()=> void) {
this.loadCallbackMap.set(tag,cb)
}

callLoadFunction(tag:number){
this.loadCallbackMap.get(tag)?.()
this.loadCallbackMap.delete(tag)
}
}
13 changes: 13 additions & 0 deletions src/NativeRNCWebViewModule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';
import { Double } from 'react-native/Libraries/Types/CodegenTypes';

export interface Spec extends TurboModule {
isFileUploadSupported(): Promise<boolean>;
shouldStartLoadWithLockIdentifier(
shouldStart: boolean,
lockIdentifier: Double
): void;
}

export default TurboModuleRegistry.getEnforcing<Spec>('RNCWebViewModule');
11 changes: 3 additions & 8 deletions src/WebView.harmony.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import React, {
useRef
} from 'react';
import { Image, View, ImageSourcePropType, HostComponent } from 'react-native';
import { Double } from 'react-native/Libraries/Types/CodegenTypes';
import invariant from 'invariant';

import RNCWebView, { Commands, NativeProps } from './RNCWebViewNativeComponent';
import RNCWebViewModule from './NativeRNCWebViewModule';

import {
defaultOriginWhitelist,
Expand Down Expand Up @@ -46,11 +46,6 @@ const useWarnIfChanges = <T extends unknown>(value: T, name: string) => {
}
};

const shouldStartLoadWithLockIdentifier: (
shouldStart: boolean,
lockIdentifier: Double
) => void = () => { }

const WebViewComponent = forwardRef<{}, IOSWebViewProps & { scalesPageToFit: boolean, minimumFontSize: number, thirdPartyCookiesEnabled: boolean, geolocationEnabled: boolean }>(
(
{
Expand Down Expand Up @@ -113,7 +108,7 @@ const WebViewComponent = forwardRef<{}, IOSWebViewProps & { scalesPageToFit: boo

const onShouldStartLoadWithRequestCallback = useCallback(
(shouldStart: boolean, _url: string, lockIdentifier = 0) => {
shouldStartLoadWithLockIdentifier(
RNCWebViewModule.shouldStartLoadWithLockIdentifier(
shouldStart,
lockIdentifier
);
Expand Down Expand Up @@ -328,4 +323,4 @@ const isFileUploadSupported: () => Promise<boolean> = async () => true;

const WebView = Object.assign(WebViewComponent, { isFileUploadSupported });

export default WebView;
export default WebView;