diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/EventConstant.ts b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/EventConstant.ts index 5c3fee289440d2b0f113c77708aa6ba13cb1b4d4..ab51641f338810921d5020b15020459e433bd52a 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/EventConstant.ts +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/EventConstant.ts @@ -16,4 +16,5 @@ export default class EventConstant { public static readonly EVENT_PULL_SETREFRESHING = "pull_setRefreshing"; public static readonly EVENT_UPDATE_STARTSCRIPTS = "update_startScripts"; + public static readonly EVENT_UPDATE_CACHEENABLE = "update_cacheEnable"; } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/InAppWebViewFlutterPlugin.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/InAppWebViewFlutterPlugin.ets index f463571ad2de0eb6a9870b25567b6cc035eae82a..0f71d0697c92d69dbd448e620123611732b14fcb 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/InAppWebViewFlutterPlugin.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/InAppWebViewFlutterPlugin.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -import { BinaryMessenger, Log } from '@ohos/flutter_ohos'; +import { AbilityAware, AbilityPluginBinding, BinaryMessenger, Log } from '@ohos/flutter_ohos'; import { FlutterAssets, FlutterPlugin, @@ -24,11 +24,13 @@ import MyCookieManager from './MyCookieManager'; import PrintJobManager from './print_job/PrintJobManager'; import FlutterWebViewFactory from './webview/FlutterWebViewFactory'; import { InAppWebViewManager } from './webview/InAppWebViewManager'; +import InAppBrowserManager from './in_app_browser/InAppBrowserManager'; import common from '@ohos.app.ability.common'; +import { UIAbility } from '@kit.AbilityKit'; const TAG = "InAppWebViewFlutterPlugin"; -export default class InAppWebViewFlutterPlugin implements FlutterPlugin { +export default class InAppWebViewFlutterPlugin implements FlutterPlugin, AbilityAware { public flutterAssets: FlutterAssets | null = null; public flutterWebViewFactory: FlutterWebViewFactory | null = null public messenger: BinaryMessenger | null = null @@ -36,11 +38,21 @@ export default class InAppWebViewFlutterPlugin implements FlutterPlugin { public myCookieManager: MyCookieManager | null = null public headlessInAppWebViewManager: HeadlessInAppWebViewManager | null = null; public inAppWebViewManager: InAppWebViewManager | null = null; + public inAppBrowserManager: InAppBrowserManager | null = null; public applicationContext: common.Context | null = null + public uiAbility: UIAbility | null = null; constructor() { } + onAttachedToAbility(binding: AbilityPluginBinding): void { + this.uiAbility = binding.getAbility() + } + + onDetachedFromAbility(): void { + this.uiAbility = null; + } + getUniqueClassName(): string { return "InAppWebViewFlutterPlugin" } @@ -49,6 +61,7 @@ export default class InAppWebViewFlutterPlugin implements FlutterPlugin { Log.d(TAG, "onAttachedToEngine") this.messenger = binding.getBinaryMessenger() this.flutterAssets = binding.getFlutterAssets(); + this.inAppBrowserManager = new InAppBrowserManager(this); this.flutterWebViewFactory = new FlutterWebViewFactory(this); this.messenger = binding.getBinaryMessenger(); this.applicationContext = binding.getApplicationContext() @@ -64,6 +77,10 @@ export default class InAppWebViewFlutterPlugin implements FlutterPlugin { this.printJobManager.dispose(); this.printJobManager = null; } + if (this.inAppBrowserManager != null) { + this.inAppBrowserManager.dispose(); + this.inAppBrowserManager = null; + } if (this.myCookieManager != null) { this.myCookieManager.dispose(); this.myCookieManager = null; diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserActivity.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserAbility.ets similarity index 93% rename from flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserActivity.ets rename to flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserAbility.ets index 04396592818290184facf723128d9eadfcb21fd6..9bcc826ca4a0c05a2cf9d6d836e1797c04c66271 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserActivity.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserAbility.ets @@ -13,6 +13,11 @@ * limitations under the License. */ +import UIAbility from '@ohos.app.ability.UIAbility'; +import window from '@ohos.window'; +import common from '@ohos.app.ability.common'; +import Want from '@ohos.app.ability.Want'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; import PullToRefreshLayout from '../pull_to_refresh/PullToRefreshLayout' import { Disposable } from '../types/Disposable' import InAppWebView from '../webview/in_app_webview/InAppWebView' @@ -27,12 +32,13 @@ import InAppWebViewSettings from '../webview/in_app_webview/InAppWebViewSettings import Util from '../Util' import { MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel' import { Any } from '@ohos/flutter_ohos' +import { Log } from '@ohos/flutter_ohos'; -const LOG_TAG = "InAppBrowserActivity" +const LOG_TAG = "InAppBrowserAbility" const METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappbrowser_" -// export default class InAppBrowserActivity extends AppCompatActivity implements InAppBrowserDelegate, Disposable{ -export default class InAppBrowserActivity implements InAppBrowserDelegate, Disposable{ +//TODO 这种模式不支持,OHOS的har不支持定义Ability +export default class InAppBrowserAbility extends UIAbility implements InAppBrowserDelegate, Disposable{ public windowId: string | null = null public id: string | null = null @@ -60,9 +66,18 @@ export default class InAppBrowserActivity implements InAppBrowserDelegate, Dispo public channelDelegate: InAppBrowserChannelDelegate | null = null public menuItems: List = new List() - // protected onCreate(savedInstanceState: Bundle): void { - // - // } + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + + } + + onWindowStageCreate(windowStage: window.WindowStage) { + windowStage.loadContent('components/plugin/pages/InAppBrowser', (err, data) => { + if (err.code) { + Log.e(LOG_TAG, `Failed to load the content. Cause: ${JSON.stringify(err)}`); + return; + } + }); + } private prepareView(): void { if (this.webView != null) { diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserManager.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserManager.ets index b62bf6231dbf9cc59b4119ff26b515c0e7d42826..b75e052163c89f7f396aad72019dc7eea8075997 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserManager.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserManager.ets @@ -16,8 +16,10 @@ import InAppWebViewFlutterPlugin from '../InAppWebViewFlutterPlugin'; import ChannelDelegateImpl from '../types/ChannelDelegateImpl'; import { util } from '@kit.ArkTS'; -import { MethodCall, MethodChannel } from '@ohos/flutter_ohos'; +import { Any, Log, MethodCall, MethodChannel } from '@ohos/flutter_ohos'; import { MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; const LOG_TAG = "InAppBrowserManager" const METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappbrowser" @@ -27,69 +29,76 @@ export default class InAppBrowserManager extends ChannelDelegateImpl { public plugin: InAppWebViewFlutterPlugin | null public id: string - public shared: Map = new Map() + public static shared: Map = new Map() constructor(plugin:InAppWebViewFlutterPlugin) { super(new MethodChannel(plugin.messenger!, METHOD_CHANNEL_NAME)); this.id = util.generateRandomUUID(true) this.plugin = plugin - this.shared.set(this.id, this) + InAppBrowserManager.shared.set(this.id, this) } public onMethodCall(call: MethodCall, result: MethodResult): void { switch (call.method) { case "open": - // if (this.plugin != null && this.plugin.activity != null) { - // open(this.plugin.activity, call.arguments() as Map); - // result.success(true); - // } else { - // result.success(false); - // } + if (this.plugin != null && this.plugin.uiAbility != null) { + this.open(this.plugin.uiAbility, call.args as Map); + result.success(true); + } else { + result.success(false); + } break; case "openWithSystemBrowser": - // if (this.plugin != null && this.plugin.activity != null) { - // let url: string = call.argument("url") as string; - // openWithSystemBrowser(this.plugin.activity, url, result); - // } else { - // result.success(false); - // } + if (this.plugin != null && this.plugin.uiAbility != null) { + let url: string = call.argument("url") as string; + this.openWithSystemBrowser(this.plugin.uiAbility, url, result); + } else { + result.success(false); + } break; default: result.notImplemented(); } } - public static getMimeType(url: string): string { - let type: string | null = null; - // let extension: string = MimeTypeMap.getFileExtensionFromUrl(url) - // if (extension != null) { - // type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); - // } - return type??'' + public open(uiAbility: UIAbility, args: Map) { + let want: Want = { + bundleName: uiAbility.context.abilityInfo.bundleName, + abilityName: 'InAppBrowserAbility' + }; + + uiAbility.context.startAbility(want, (err: BusinessError) => { + if (err.code) { + Log.e(LOG_TAG, `Failed to startAbility. Code: ${err.code}, message: ${err.message}`); + } + }); } - // public openWithSystemBrowser(activity: Activity, url: string, result: Result): void { - // try { - // let intent: Intent; - // intent = new Intent(Intent.ACTION_VIEW); - // let uri: uri = Uri.parse(url); - // if ("file".equals(uri.getScheme())) { - // intent.setDataAndType(uri, getMimeType(url)); - // } else { - // intent.setData(uri); - // } - // intent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName()); - // this.openExternalExcludeCurrentApp(activity, intent); - // result.success(true); - // } catch (java.lang.RuntimeException e) { - // Log.d(LOG_TAG, url + " cannot be opened: " + e.toString()); - // result.error(LOG_TAG, url + " cannot be opened!", null); - // } - // } + public openWithSystemBrowser(uiAbility: UIAbility, url: string, result: MethodResult): void { + try { + let want: Want = { + action: 'ohos.want.action.viewData', + entities: ['entity.system.browsable'], + uri: url + } + + uiAbility.context.startAbility(want, (err: BusinessError) => { + if (err.code) { + Log.e(LOG_TAG, `Failed to startAbility. Code: ${err.code}, message: ${err.message}`); + result.error(`Code: ${err.code}`, err.message, null); + } else { + result.success(true) + } + }); + } catch ( e) { + Log.d(LOG_TAG, url + " cannot be opened: " + e.toString()); + result.error(LOG_TAG, url + " cannot be opened!", null); + } + } public dispose(): void { super.dispose(); - // this.shared.remove(this.id); + InAppBrowserManager.shared.delete(this.id); this.plugin = null; } } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserSettings.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserSettings.ets index ce9e24c1783f9a4044c120302b81e1fa6a6a7d34..6392da51848f8458a7470c74f96ba35f564a1610 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserSettings.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/in_app_browser/InAppBrowserSettings.ets @@ -15,11 +15,11 @@ import { Any } from '@ohos/flutter_ohos'; import ISettings from '../ISettings'; -import InAppBrowserActivity from './InAppBrowserActivity'; +import InAppBrowserAbility from './InAppBrowserAbility'; const LOG_TAG = "InAppBrowserSettings" -export default class InAppBrowserSettings implements ISettings { +export default class InAppBrowserSettings implements ISettings { public hidden: boolean = false public hideToolbarTop: boolean = false @@ -99,12 +99,12 @@ export default class InAppBrowserSettings implements ISettings { + public getRealSettings(InAppBrowserAbility: InAppBrowserAbility): Map { let realSettings: Map = this.toMap() - realSettings.set("hidden", inAppBrowserActivity.isHidden); - // realSettings.set("hideToolbarTop", inAppBrowserActivity.actionBar == null || !inAppBrowserActivity.actionBar.isShowing()); - // realSettings.set("hideUrlBar", inAppBrowserActivity.menu == null || !inAppBrowserActivity.menu.findItem(R.id.menu_search).isVisible()); - // realSettings.set("hideProgressBar", inAppBrowserActivity.progressBar == null || inAppBrowserActivity.progressBar.getMax() == 0); + realSettings.set("hidden", InAppBrowserAbility.isHidden); + // realSettings.set("hideToolbarTop", InAppBrowserAbility.actionBar == null || !InAppBrowserAbility.actionBar.isShowing()); + // realSettings.set("hideUrlBar", InAppBrowserAbility.menu == null || !InAppBrowserAbility.menu.findItem(R.id.menu_search).isVisible()); + // realSettings.set("hideProgressBar", InAppBrowserAbility.progressBar == null || InAppBrowserAbility.progressBar.getMax() == 0); return realSettings; } } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/WebViewChannelDelegate.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/WebViewChannelDelegate.ets index 41d0c710b5d285f8c1d6886adf0ffa05f9df11b8..0e9f008a8d34452294787781a88a289bb5a72868 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/WebViewChannelDelegate.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/WebViewChannelDelegate.ets @@ -13,9 +13,10 @@ * limitations under the License. */ +import web_webview from '@ohos.web.webview'; import { Any, Log, MethodCall, MethodChannel } from '@ohos/flutter_ohos'; import { MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; -import InAppBrowserActivity from '../in_app_browser/InAppBrowserActivity'; +import InAppBrowserAbility from '../in_app_browser/InAppBrowserAbility'; import ChannelDelegateImpl from '../types/ChannelDelegateImpl'; import ContentWorld from '../types/ContentWorld'; import URLRequest from '../types/URLRequest'; @@ -205,12 +206,12 @@ export default class WebViewChannelDelegate extends ChannelDelegateImpl { result.success(null); break; case WebViewChannelDelegateMethods.setSettings: - if (this.webView != null && this.webView.getInAppBrowserDelegate() instanceof InAppBrowserActivity) { - let inAppBrowserActivity: InAppBrowserActivity = this.webView.getInAppBrowserDelegate() as InAppBrowserActivity; + if (this.webView != null && this.webView.getInAppBrowserDelegate() instanceof InAppBrowserAbility) { + let InAppBrowserAbility: InAppBrowserAbility = this.webView.getInAppBrowserDelegate() as InAppBrowserAbility; let inAppBrowserSettings: InAppBrowserSettings = new InAppBrowserSettings(); let inAppBrowserSettingsMap: Map = call.argument("settings") as Map; inAppBrowserSettings.parse(inAppBrowserSettingsMap); - inAppBrowserActivity.setSettings(inAppBrowserSettings, inAppBrowserSettingsMap); + InAppBrowserAbility.setSettings(inAppBrowserSettings, inAppBrowserSettingsMap); } else if (this.webView != null) { let inAppWebViewSettings: InAppWebViewSettings = new InAppWebViewSettings(); let inAppWebViewSettingsMap: Map = call.argument("settings") as Map; @@ -220,43 +221,43 @@ export default class WebViewChannelDelegate extends ChannelDelegateImpl { result.success(true); break; case WebViewChannelDelegateMethods.getSettings: - if (this.webView != null && this.webView.getInAppBrowserDelegate() instanceof InAppBrowserActivity) { - let inAppBrowserActivity: InAppBrowserActivity = this.webView.getInAppBrowserDelegate() as InAppBrowserActivity; - result.success(inAppBrowserActivity.getCustomSettings()); + if (this.webView != null && this.webView.getInAppBrowserDelegate() instanceof InAppBrowserAbility) { + let InAppBrowserAbility: InAppBrowserAbility = this.webView.getInAppBrowserDelegate() as InAppBrowserAbility; + result.success(InAppBrowserAbility.getCustomSettings()); } else { result.success((this.webView != null) ? this.webView.getCustomSettings() : null); } break; case WebViewChannelDelegateMethods.close: - if (this.webView != null && this.webView.getInAppBrowserDelegate() instanceof InAppBrowserActivity) { - let inAppBrowserActivity: InAppBrowserActivity = this.webView.getInAppBrowserDelegate() as InAppBrowserActivity; - inAppBrowserActivity.close(result); + if (this.webView != null && this.webView.getInAppBrowserDelegate() instanceof InAppBrowserAbility) { + let InAppBrowserAbility: InAppBrowserAbility = this.webView.getInAppBrowserDelegate() as InAppBrowserAbility; + InAppBrowserAbility.close(result); } else { result.notImplemented(); } break; case WebViewChannelDelegateMethods.show: - if (this.webView != null && this.webView.getInAppBrowserDelegate() instanceof InAppBrowserActivity) { - let inAppBrowserActivity: InAppBrowserActivity = this.webView.getInAppBrowserDelegate() as InAppBrowserActivity; - inAppBrowserActivity.show(); + if (this.webView != null && this.webView.getInAppBrowserDelegate() instanceof InAppBrowserAbility) { + let InAppBrowserAbility: InAppBrowserAbility = this.webView.getInAppBrowserDelegate() as InAppBrowserAbility; + InAppBrowserAbility.show(); result.success(true); } else { result.notImplemented(); } break; case WebViewChannelDelegateMethods.hide: - if (this.webView != null && this.webView.getInAppBrowserDelegate() instanceof InAppBrowserActivity) { - let inAppBrowserActivity: InAppBrowserActivity = this.webView.getInAppBrowserDelegate() as InAppBrowserActivity; - inAppBrowserActivity.hide(); + if (this.webView != null && this.webView.getInAppBrowserDelegate() instanceof InAppBrowserAbility) { + let InAppBrowserAbility: InAppBrowserAbility = this.webView.getInAppBrowserDelegate() as InAppBrowserAbility; + InAppBrowserAbility.hide(); result.success(true); } else { result.notImplemented(); } break; case WebViewChannelDelegateMethods.isHidden: - if (this.webView != null && this.webView.getInAppBrowserDelegate() instanceof InAppBrowserActivity) { - let inAppBrowserActivity: InAppBrowserActivity = this.webView.getInAppBrowserDelegate() as InAppBrowserActivity; - result.success(inAppBrowserActivity.isHidden); + if (this.webView != null && this.webView.getInAppBrowserDelegate() instanceof InAppBrowserAbility) { + let InAppBrowserAbility: InAppBrowserAbility = this.webView.getInAppBrowserDelegate() as InAppBrowserAbility; + result.success(InAppBrowserAbility.isHidden); } else { result.notImplemented(); } @@ -569,68 +570,54 @@ export default class WebViewChannelDelegate extends ChannelDelegateImpl { break; case WebViewChannelDelegateMethods.createWebMessageChannel: if (this.webView != null) { - // if (this.webView instanceof InAppWebView && WebViewFeature.isFeatureSupported(WebViewFeature.CREATE_WEB_MESSAGE_CHANNEL)) { - // result.success(this.webView.createCompatWebMessageChannel().toMap()); - // } else { - // result.success(null); - // } + result.success(this.webView.createCompatWebMessageChannel().toMap()); } else { result.success(null); } break; case WebViewChannelDelegateMethods.postWebMessage: - // if (this.webView != null && WebViewFeature.isFeatureSupported(WebViewFeature.POST_WEB_MESSAGE)) { - // let message: WebMessageCompatExt | null = WebMessageCompatExt.fromMap(call.argument("message") as Map); - // let targetOrigin: string = call.argument("targetOrigin"); - // let compatPorts: List = new List(); - // let portsExt: List = message.getPorts(); - // if (portsExt != null) { - // for (let portExt of portsExt) { - // let webMessageChannel: WebMessageChannel | undefined = this.webView.getWebMessageChannels().get(portExt.getWebMessageChannelId()); - // if (webMessageChannel != null) { - // if (this.webView instanceof InAppWebView) { - // // compatPorts.add(webMessageChannel.compatPorts.get(portExt.getIndex())); - // } - // } - // } - // } - // let data: Any = message.getData(); - // if (webView instanceof InAppWebView) { - // try { - // if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_ARRAY_BUFFER) && data != null && - // message.getType() == WebMessageCompat.TYPE_ARRAY_BUFFER) { - // WebViewCompat.postWebMessage((WebView) webView, - // new WebMessageCompat((byte[]) data, compatPorts.toArray(new WebMessagePortCompat[0])), - // Uri.parse(targetOrigin)); - // } else { - // WebViewCompat.postWebMessage((WebView) webView, - // new WebMessageCompat(data != null ? data.toString() : null, compatPorts.toArray(new WebMessagePortCompat[0])), - // Uri.parse(targetOrigin)); - // } - // result.success(true); - // } catch (Exception e) { - // result.error(LOG_TAG, e.getMessage(), null); - // } - // } - // } else { - // result.success(true); - // } + let message: WebMessageCompatExt | null = WebMessageCompatExt.fromMap(call.argument("message") as Map); + let targetOrigin: string = call.argument("targetOrigin"); + let compatPorts: List = new List(); + let portsExt: List = message!.getPorts(); + if (portsExt != null) { + for (let portExt of portsExt) { + let webMessageChannel: WebMessageChannel | undefined = this.webView.getWebMessageChannels().get(portExt.getWebMessageChannelId()); + if (webMessageChannel != null) { + if (this.webView instanceof InAppWebView) { + compatPorts.add(webMessageChannel.compatPorts[portExt.getIndex()]); + } + } + } + } + let data: Any = message!.getData(); + if (this.webView instanceof InAppWebView) { + try { + if (data != null && message!.getType() == web_webview.WebMessageType.ARRAY_BUFFER) { + // TODO 怎么post arraybuffer + // WebViewCompat.postWebMessage((WebView) webView, + // new WebMessageCompat((byte[]) data, compatPorts.toArray(new WebMessagePortCompat[0])), + // Uri.parse(targetOrigin)); + } else { + this.webView.controller.postMessage(data != null ? data.toString() : null, compatPorts.convertToArray(), targetOrigin) + } + result.success(true); + } catch (e) { + result.error(LOG_TAG, e.getMessage(), null); + } + } break; case WebViewChannelDelegateMethods.addWebMessageListener: if (this.webView != null) { let webMessageListenerMap: Map = call.argument("webMessageListener") as Map; let webMessageListener: WebMessageListener | null = WebMessageListener.fromMap(this.webView, this.webView.getPlugin() .messenger, webMessageListenerMap); - // if (this.webView instanceof InAppWebView && WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) { - // try { - // this.webView.addWebMessageListener(webMessageListener!); - // result.success(true); - // } catch (e) { - // result.error(LOG_TAG, e.getMessage(), null); - // } - // } else { - // result.success(true); - // } + try { + this.webView.addWebMessageListener(webMessageListener!); + result.success(true); + } catch (e) { + result.error(LOG_TAG, e.getMessage(), null); + } } else { result.success(true); } @@ -1077,6 +1064,28 @@ export default class WebViewChannelDelegate extends ChannelDelegateImpl { obj.set("threatType", threatType); channel.invokeMethod("onSafeBrowsingHit", obj, callback); } + + onRenderProcessUnresponsive(url: string, callback: RenderProcessUnresponsiveCallback) { + let channel = this.getChannel(); + if (channel == null) { + callback.defaultBehaviour(null); + return; + } + let obj: Map = new Map(); + obj.set("url", url); + channel.invokeMethod("onRenderProcessUnresponsive", obj, callback); + } + + onRenderProcessResponsive(url: string, callback: RenderProcessResponsiveCallback) { + let channel = this.getChannel(); + if (channel == null) { + callback.defaultBehaviour(null); + return; + } + let obj: Map = new Map(); + obj.set("url", url); + channel.invokeMethod("onRenderProcessResponsive", obj, callback); + } } export class JsAlertCallback extends BaseCallbackResultImpl { @@ -1194,4 +1203,16 @@ export class SafeBrowsingHitCallback extends BaseCallbackResultImpl { + public decodeResult(obj: Any): number | null { + return typeof obj == "number" ? obj as number : null; + } +} + +export class RenderProcessResponsiveCallback extends BaseCallbackResultImpl { + public decodeResult(obj: Any): number | null { + return typeof obj == "number" ? obj as number : null; + } } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebView.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebView.ets index 070cc431a4572fbb7752700862fe457fa5c3e9ab..cb969e519e5d55a1bfb35c7f85ad7926a61a6c06 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebView.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebView.ets @@ -37,7 +37,7 @@ import util from '@ohos.util'; import Util from '../../Util'; import PluginScriptsUtil from '../../plugin_scripts_js/PluginScriptsUtil'; import { MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; -import InAppWebViewChromeClient from './InAppWebViewChromeClient'; +import InAppWebViewClient from './InAppWebViewClient'; import PluginScript from '../../types/PluginScript'; import PromisePolyfillJS from '../../plugin_scripts_js/PromisePolyfillJS'; import ConsoleLogJS from '../../plugin_scripts_js/ConsoleLogJS'; @@ -62,9 +62,8 @@ import window from '@ohos.window'; import animator, { AnimatorOptions, AnimatorResult } from '@ohos.animator'; import common from '@ohos.app.ability.common'; import { FindInteractionController } from '../../find_interaction/FindInteractionController'; -import { InAppWebViewClient } from './InAppWebViewClient'; -import { InAppWebViewClientCompat } from './InAppWebViewClientCompat'; import PullToRefreshLayout from '../../pull_to_refresh/PullToRefreshLayout'; +import EventConstant from '../../EventConstant' const TAG = "InAppWebView" const METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_"; @@ -75,8 +74,6 @@ export default class InAppWebView implements InAppWebViewInterface { public id: number; public windowId: number | null | undefined; public inAppWebViewClient: InAppWebViewClient | null = null; - public inAppWebViewClientCompat: InAppWebViewClientCompat | null = null; - public inAppWebViewChromeClient: InAppWebViewChromeClient | null = null; public channelDelegate: WebViewChannelDelegate; private javaScriptBridgeInterface: JavaScriptBridgeInterface | null = null; public customSettings: InAppWebViewSettings; @@ -137,41 +134,6 @@ export default class InAppWebView implements InAppWebViewInterface { return this.pullToRefreshLayout!!; } - public async createWebClient(inAppBrowserDelegate: InAppBrowserDelegate): Promise { - // TODO 应返回 Promise - let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT; - let packageInfo = await bundleManager.getBundleInfoForSelf(bundleFlags); - if (packageInfo != null) { - Log.d(TAG, "Using InAppWebViewClient implementation"); - //TODO - // return new InAppWebViewClient(inAppBrowserDelegate); - } - - let isChromiumWebView: boolean = "com.android.webview" == (packageInfo.name) || - "com.google.android.webview" == (packageInfo.name) || - "com.android.chrome" == (packageInfo.name); - - let isChromiumWebViewBugFixed: boolean = false; - if (isChromiumWebView) { - let versionName = packageInfo.versionName != null ? packageInfo.versionName : ""; - try { - let majorVersion: number = versionName.includes(".") ? Number(versionName.split("\\.")[0]) : 0; - isChromiumWebViewBugFixed = majorVersion >= 73; - } catch (error) { - } - } - - if (isChromiumWebViewBugFixed || !isChromiumWebView) { - Log.d(TAG, "Using InAppWebViewClientCompat implementation"); - //TODO - // return new InAppWebViewClientCompat(inAppBrowserDelegate); - } else { - Log.d(TAG, "Using InAppWebViewClient implementation"); - //TODO - // return new InAppWebViewClient(inAppBrowserDelegate); - } - } - public async prepare() { if (this.plugin != null) { this.webViewAssetLoaderExt = WebViewAssetLoaderExt.fromMap(this.customSettings.webViewAssetLoader, this.plugin, getContext()); @@ -180,20 +142,7 @@ export default class InAppWebView implements InAppWebViewInterface { this.javaScriptBridgeInterface = new JavaScriptBridgeInterface(this); //addJavascriptInterface(javaScriptBridgeInterface, JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME); - this.inAppWebViewChromeClient = new InAppWebViewChromeClient(this.plugin, this); - // setWebChromeClient(inAppWebViewChromeClient); - - // WebViewClient webViewClient = createWebViewClient(inAppBrowserDelegate); - // if (this.webViewClient instanceof InAppWebViewClientCompat) { - // this.inAppWebViewClientCompat = webViewClient as InAppWebViewClientCompat; - // setWebViewClient(inAppWebViewClientCompat); - // } else if (webViewClient instanceof InAppWebViewClient) { - // inAppWebViewClient = (InAppWebViewClient) webViewClient; - // setWebViewClient(inAppWebViewClient); - // } - - // this.inAppWebViewRenderProcessClient = new InAppWebViewRenderProcessClient(); - // WebViewCompat.setWebViewRenderProcessClient(this, inAppWebViewRenderProcessClient); + this.inAppWebViewClient = new InAppWebViewClient(this.plugin, this); if (this.windowId == null || this.windowId == undefined) { this.prepareAndAddUserScripts(); @@ -225,6 +174,11 @@ export default class InAppWebView implements InAppWebViewInterface { await this.waitControllerAttached() this.controller.registerJavaScriptProxy(this.javaScriptBridgeInterface, JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME, this.javaScriptBridgeInterface.getMethodList()); + if (this.customSettings.incognito) + this.setIncognito(true); + + this.setCacheEnabled(this.customSettings.cacheEnabled); + // settings if (this.customSettings.userAgent != null && this.customSettings.userAgent.length > 0) { this.controller.setCustomUserAgent(this.customSettings.userAgent); @@ -265,11 +219,31 @@ export default class InAppWebView implements InAppWebViewInterface { } public setIncognito(enabled: boolean): void { - //TODO + if (enabled) { + web_webview.WebCookieManager.clearAllCookiesSync(true); + + this.setCacheEnabled(false); + + this.controller.clearHistory(); + this.controller.clearMatches(); + this.controller.clearSslCache(); + this.controller.removeCache(true); + + // No form data or autofill enabled + // clearFormData(); + // settings.setSavePassword(false); + // settings.setSaveFormData(false); + } else { + this.setCacheEnabled(true); + + // settings.setSavePassword(true); + // settings.setSaveFormData(true); + } } - public setCacheEnabled(): void { - //TODO + public setCacheEnabled(enabled: boolean): void { + let context = this.context as common.UIAbilityContext; + context.eventHub.emit(EventConstant.EVENT_UPDATE_CACHEENABLE, enabled); } async loadUrl(urlRequest: URLRequest) { @@ -453,6 +427,13 @@ export default class InAppWebView implements InAppWebViewInterface { this.controller.setCustomUserAgent(userAgentWithApplicationName); } + if (newSettingsMap.has("incognito") && this.customSettings.incognito != newCustomSettings.incognito){ + this.setIncognito(newCustomSettings.incognito); + } + + if (newSettingsMap.has("cacheEnabled") && this.customSettings.cacheEnabled != newCustomSettings.cacheEnabled) + this.setCacheEnabled(newCustomSettings.cacheEnabled); + if (this.plugin != null) { if (this.webViewAssetLoaderExt != null) { this.webViewAssetLoaderExt.dispose(); @@ -717,7 +698,7 @@ export default class InAppWebView implements InAppWebViewInterface { } getProgress(): number { - throw Error("Ohos currently does not support this feature") + return this.inAppWebViewClient ? this.inAppWebViewClient!.progress : 0 } reload(): void { @@ -769,19 +750,21 @@ export default class InAppWebView implements InAppWebViewInterface { } onPause(): void { - throw Error("Ohos currently does not support this feature") + this.controller.pauseAllMedia() + this.controller.onInactive() } onResume(): void { - throw Error("Ohos currently does not support this feature") + this.controller.resumeAllMedia() + this.controller.onActive() } pauseTimers(): void { - throw Error("Ohos currently does not support this feature") + web_webview.WebviewController.pauseAllTimers(); } resumeTimers(): void { - throw Error("Ohos currently does not support this feature") + web_webview.WebviewController.resumeAllTimers(); } getContentHeight(): number { @@ -801,7 +784,15 @@ export default class InAppWebView implements InAppWebViewInterface { } public isSecureContext(resultCallback: ValueCallback): void { - + this.evaluateJavascript("window.isSecureContext", null, { + onReceiveValue: (value) => { + if (value == null || value.length == 0 || value == "null" || value == "false") { + resultCallback.onReceiveValue(false); + return; + } + resultCallback.onReceiveValue(true); + } + }); } zoomBy(zoomFactor: number): void { @@ -862,7 +853,7 @@ export default class InAppWebView implements InAppWebViewInterface { } clearFocus(): void { - this.controller.onInactive + this.controller.onInactive() } async getCertificate() { diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewChromeClient.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewChromeClient.ets deleted file mode 100644 index bf8d04b2163d171e4729b263f1d93c805d460a59..0000000000000000000000000000000000000000 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewChromeClient.ets +++ /dev/null @@ -1,1535 +0,0 @@ -/* -* Copyright (c) 2024 Hunan OpenValley Digital Industry Development 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. -*/ - -import { Any, Log } from '@ohos/flutter_ohos'; -import web_webview from '@ohos.web.webview'; -import cameraPicker from '@ohos.multimedia.cameraPicker'; -import picker from '@ohos.file.picker'; -import uri from '@ohos.uri' -import InAppWebViewFlutterPlugin from '../../InAppWebViewFlutterPlugin'; -import DownloadStartRequest from '../../types/DownloadStartRequest'; -import URLUtil from '../../types/URLUtil'; -import InAppWebView from './InAppWebView'; -import WebResourceResponseExt from '../../types/WebResourceResponseExt'; -import CustomSchemeResponse from '../../types/CustomSchemeResponse'; -import WebResourceRequestExt from '../../types/WebResourceRequestExt'; -import URLRequest from '../../types/URLRequest'; -import NavigationAction from '../../types/NavigationAction'; -import { NavigationActionPolicy } from '../../types/NavigationActionPolicy'; -import URLCredential from '../../types/URLCredential'; -import JavaScriptBridgeJS from '../../plugin_scripts_js/JavaScriptBridgeJS'; -import { image } from '@kit.ImageKit'; -import { InAppBrowserDelegate } from '../../in_app_browser/InAppBrowserDelegate'; -import WebResourceErrorExt from '../../types/WebResourceErrorExt'; -import Util from '../../Util'; -import { - GeolocationPermissionsShowPromptCallback, - JsAlertCallback, - JsBeforeUnloadCallback, - JsConfirmCallback, - JsPromptCallback, - PermissionRequestCallback, - ReceivedHttpAuthRequestCallback, - ReceivedServerTrustAuthRequestCallback, - ReceivedClientCertRequestCallback, - CreateWindowCallback, - FormResubmissionCallback, - ShouldOverrideUrlLoadingCallback, - SafeBrowsingHitCallback -} from '../WebViewChannelDelegate'; -import JsAlertResponse from '../../types/JsAlertResponse'; -import JsConfirmResponse from '../../types/JsConfirmResponse'; -import JsPromptResponse from '../../types/JsPromptResponse'; -import HttpAuthResponse from '../../types/HttpAuthResponse'; -import { ohosPromptDialogBuilder } from './OhosPromptDialog'; -import { promptAction } from '@kit.ArkUI'; -import JsBeforeUnloadResponse from '../../types/JsBeforeUnloadResponse'; -import { camera } from '@kit.CameraKit'; -import { BusinessError } from '@kit.BasicServicesKit'; -import MimeTypes from '../../MimeTypes'; -import PermissionResponse from '../../types/PermissionResponse'; -import GeolocationPermissionShowPromptResponse from '../../types/GeolocationPermissionShowPromptResponse'; -import CredentialDatabase from '../../credential_database/CredentialDatabase'; -import HttpAuthenticationChallenge from '../../types/HttpAuthenticationChallenge'; -import URLProtectionSpace from '../../types/URLProtectionSpace'; -import ServerTrustAuthResponse from '../../types/ServerTrustAuthResponse'; -import ServerTrustChallenge from '../../types/ServerTrustChallenge'; -import ClientCertChallenge from '../../types/ClientCertChallenge'; -import ClientCertResponse from '../../types/ClientCertResponse'; -import CreateWindowAction from '../../types/CreateWindowAction'; -import SafeBrowsingResponse from '../../types/SafeBrowsingResponse'; -import { cert } from '@kit.DeviceCertificateKit' -import { List } from '@kit.ArkTS'; -import { common } from '@kit.AbilityKit'; - -const TAG = "InAppWebViewChromeClient"; - -// 参考文档 所有事件 https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-arkweb/ts-basic-components-web.md#onalert -export default class InAppWebViewChromeClient { - public static previousAuthRequestFailureCount = 0; - public static credentialsProposed: List | null = null; - private plugin: InAppWebViewFlutterPlugin; - private inAppWebView: InAppWebView; - private inAppBrowserDelegate: InAppBrowserDelegate | null = null; - private fullScreenExitHandler: FullScreenExitHandler | null = null; - private isOriginalLayoutFullScreen = false; - private isOriginalFullScreen = false; - - constructor(plugin: InAppWebViewFlutterPlugin, inAppWebView: InAppWebView) { - this.plugin = plugin; - this.inAppWebView = inAppWebView; - } - - onAlert = (event: Any) => { - Log.d(TAG, "onAlert=" + JSON.stringify(event)) - if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onJsAlert(event.url, event.message, null, - new InnerJsAlertCallback(event.result, event.message)); - return true; - } - return false; - } - onBeforeUnload = (event: Any) => { - Log.d(TAG, "onBeforeUnload=" + JSON.stringify(event)) - if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onJsBeforeUnload(event.url, event.message, - new InnerJsBeforeUnloadCallback(event.result, event.message)); - return true; - } - return false; - } - onConfirm = (event: Any) => { - Log.d(TAG, "onConfirm=" + JSON.stringify(event)) - if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onJsConfirm(event.url, event.message, null, - new InnerJsConfirmCallback(event.result, event.message)); - return true; - } - return false; - } - onPrompt = (event: Any, uiObject: Any) => { - Log.d(TAG, "onPrompt=" + JSON.stringify(event)) - if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onJsPrompt(event.url, event.message, event.value, null, - new InnerJsPromptCallback(event.result, event.message, event.value, uiObject)); - return true; - } - return false; - } - onConsole = (event: Any) => { - Log.d(TAG, "onConsole=" + JSON.stringify(event)) - if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onConsoleMessage(event.message.getMessage(), event.message.getMessageLevel()); - return true; - } - return false; - } - onDownloadStart = (event: Any) => { //对应安卓setDownloadListener - Log.d(TAG, "onDownloadStart=" + JSON.stringify(event)) - if (this.inAppWebView.customSettings.useOnDownloadStart) { - let downloadStartRequest = new DownloadStartRequest( - event.url, - event.userAgent, - event.contentDisposition, - event.mimetype, - event.contentLength, - URLUtil.guessFileName(event.url, event.contentDisposition, event.mimetype), - null - ); - this.inAppWebView.channelDelegate.onDownloadStartRequest(downloadStartRequest) - } - } - onErrorReceive = (event: Any) => { - Log.d(TAG, "onErrorReceive=" + JSON.stringify(event)) - let request: WebResourceRequest = event.request; - let error: WebResourceError = event.error; - if (request.isMainFrame()) { - if (this.inAppWebView.customSettings.disableDefaultErrorPage) { - this.inAppWebView.stopLoading(); - this.inAppWebView.controller.loadUrl("about:blank"); - } - - this.inAppWebView.isLoading = false; - InAppWebViewChromeClient.previousAuthRequestFailureCount = 0; - InAppWebViewChromeClient.credentialsProposed = null; - - if (this.inAppBrowserDelegate != null) { - let type = error.getErrorCode(); - let description = error.getErrorInfo(); - this.inAppBrowserDelegate.didFailNavigation(request.getRequestUrl(), type, description); - } - } - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onReceivedError( - WebResourceRequestExt.fromWebResourceRequest(request), - WebResourceErrorExt.fromWebResourceError(error)); - } - } - onHttpErrorReceive = (event: Any) => { - Log.d(TAG, "onHttpErrorReceive=" + JSON.stringify(event)) - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onReceivedHttpError( - WebResourceRequestExt.fromWebResourceRequest(event.request), - WebResourceResponseExt.fromWebResourceResponse(event.response)); - } - } - onPageBegin = (event: Any) => { - Log.d(TAG, "onPageBegin=" + JSON.stringify(event)) - this.inAppWebView.isLoading = true; - this.inAppWebView.disposeWebMessageChannels(); - this.inAppWebView.userContentController.resetContentWorlds(); - this.loadCustomJavaScriptOnPageStarted(this.inAppWebView); - - if (this.inAppBrowserDelegate != null) { - this.inAppBrowserDelegate.didStartNavigation(event.url); - } - - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onLoadStart(event.url); - } - } - onPageEnd = (event: Any) => { - Log.d(TAG, "onPageBegin=" + JSON.stringify(event)) - this.inAppWebView.isLoading = false; - this.loadCustomJavaScriptOnPageFinished(this.inAppWebView); - InAppWebViewChromeClient.previousAuthRequestFailureCount = 0; - InAppWebViewChromeClient.credentialsProposed = null; - - if (this.inAppBrowserDelegate != null) { - this.inAppBrowserDelegate.didFinishNavigation(event.url); - } - - web_webview.WebCookieManager.saveCookieAsync() - - let js = JavaScriptBridgeJS.PLATFORM_READY_JS_SOURCE; - this.inAppWebView.controller.runJavaScriptExt(js) - - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onLoadStop(event.url); - } - } - onProgressChange = (event: Any) => { - Log.d(TAG, "onProgressChange=" + JSON.stringify(event)) - if (this.inAppBrowserDelegate != null) { - this.inAppBrowserDelegate.didChangeProgress(event.newProgress); - } - - this.loadCustomJavaScriptOnPageStarted(this.inAppWebView); - - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onProgressChanged(event.newProgress); - } - } - onTitleReceive = (event: Any) => { - Log.d(TAG, "onTitleReceive=" + JSON.stringify(event)) - if (this.inAppBrowserDelegate != null) { - this.inAppBrowserDelegate.didChangeTitle(event.title); - } - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onTitleChanged(event.title); - } - } - onRefreshAccessedHistory = (event: Any) => { - Log.d(TAG, "onRefreshAccessedHistory=" + JSON.stringify(event)) - if (this.inAppBrowserDelegate != null) { - this.inAppBrowserDelegate.didUpdateVisitedHistory(event.url); - } - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onUpdateVisitedHistory(event.url, event.isRefreshed); - } - } - onRenderExited = (event: Any) => { - Log.d(TAG, "onRenderExited=" + JSON.stringify(event)) - if (this.inAppWebView.customSettings.useOnRenderProcessGone && this.inAppWebView.channelDelegate != null) { - let didCrash = event.renderExitReason == RenderExitReason.ProcessCrashed; - this.inAppWebView.channelDelegate.onRenderProcessGone(didCrash, event.renderExitReason); - } - } - onShowFileSelector = (event: Any) => { - Log.d(TAG, "onShowFileSelector=" + JSON.stringify(event)) - Log.d(TAG, "onShowFileSelector=" + JSON.stringify(event.fileSelector)) - let acceptTypes: Array = event.fileSelector.getAcceptType(); - let allowMultiple = event.fileSelector.getMode() == FileSelectorMode.FileOpenMultipleMode; - let captureEnabled: boolean = event.fileSelector.isCapture(); - let images = this.acceptsImages(acceptTypes); - let video = this.acceptsVideo(acceptTypes); - if (captureEnabled) { - if (!this.needsCameraPermission()) { - if (images || video) { - let pickerProfile: cameraPicker.PickerProfile = { - cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK - }; - cameraPicker.pick(this.inAppWebView.context, - images ? [cameraPicker.PickerMediaType.PHOTO] : [cameraPicker.PickerMediaType.VIDEO], pickerProfile) - .then(result => { - event.result.handleFileList([result.resultUri]); - }).catch((err: BusinessError) => { - event.result.handleFileList([]); - Log.e(TAG, `the pick call failed. error code: ${err.code}`); - }); - return true; - } - } - } - - //缺少从系统直接选择全部,这里做了一个弹窗选择 这里OHOS存在一个bug。 - ActionSheet.show({ - title: '请选择', - message: '', - autoCancel: true, - isModal: true, - cancel: () => { - Log.d(TAG, 'actionSheet canceled') - event.result.handleFileList([]); - }, - alignment: DialogAlignment.Center, - offset: { - dx: 0, dy: 100 - }, - sheets: [ - { - title: '相册', - action: () => { - Log.d(TAG, 'apples') - let photoSelectOptions = new picker.PhotoSelectOptions(); - photoSelectOptions.MIMEType = (images && video) ? picker.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE : - (images ? picker.PhotoViewMIMETypes.IMAGE_TYPE : picker.PhotoViewMIMETypes.VIDEO_TYPE); - photoSelectOptions.maxSelectNumber = allowMultiple ? 100000 : 1 - let photoPicker = new picker.PhotoViewPicker(); - photoPicker.select(photoSelectOptions).then((photoSelectResult: picker.PhotoSelectResult) => { - event.result.handleFileList(photoSelectResult.photoUris); - Log.d(TAG, - 'PhotoViewPicker.select successfully, photoSelectResult uri: ' + JSON.stringify(photoSelectResult)); - }).catch((err: BusinessError) => { - event.result.handleFileList([]); - Log.e(TAG, 'PhotoViewPicker.select failed with err: ' + JSON.stringify(err)); - }); - } - }, - { - title: '档案', - action: () => { - let documentPicker = new picker.DocumentViewPicker(); - let documentSelectOptions = new picker.DocumentSelectOptions(); - documentSelectOptions.maxSelectNumber = allowMultiple ? 100000 : 1 - documentSelectOptions.fileSuffixFilters = acceptTypes; - documentPicker.select(documentSelectOptions).then((documentSelectResult) => { - Log.d(TAG, - 'documentViewPicker.select to file succeed and uri is:' + JSON.stringify(documentSelectResult)); - event.result.handleFileList(documentSelectResult); - }).catch((err: BusinessError) => { - event.result.handleFileList([]); - Log.d(TAG, `Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`); - }) - } - }, - { - title: '音频', - action: () => { - let audioSelectOptions = new picker.AudioSelectOptions(); - let audioPicker = new picker.AudioViewPicker(); - audioPicker.select(audioSelectOptions).then((audioSelectResult: Array) => { - event.result.handleFileList(audioSelectResult); - Log.d(TAG, - 'AudioViewPicker.select successfully, audioSelectResult uri: ' + JSON.stringify(audioSelectResult)); - }).catch((err: BusinessError) => { - Log.d(TAG, 'AudioViewPicker.select failed with err: ' + JSON.stringify(err)); - event.result.handleFileList([]); - }); - } - } - ] - }) - return true; - } - onResourceLoad = (event: Any) => { - // TODO 没有找到安卓对于方法 - Log.d(TAG, "onResourceLoad=" + JSON.stringify(event)) - } - onScaleChange = (event: Any) => { - Log.d(TAG, "onScaleChange=" + JSON.stringify(event)) - this.inAppWebView.zoomScale = event.newScale / Util.getPixelDensity(); - - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onZoomScaleChanged(event.oldScale, event.newScale); - } - } - onInterceptRequest = (event: Any) => { //对应安卓shouldInterceptRequest - let request = WebResourceRequestExt.fromWebResourceRequest(event.request); - Log.d(TAG, "onInterceptRequest=" + JSON.stringify(event)) - if (this.inAppWebView.webViewAssetLoaderExt != null && this.inAppWebView.webViewAssetLoaderExt.loader != null) { - try { - let url = new uri.URI(request.getUrl()); - let webResourceResponse = this.inAppWebView.webViewAssetLoaderExt.loader.shouldInterceptRequest(url); - if (webResourceResponse != null) { - return webResourceResponse; - } - } catch (e) { - Log.e(TAG, "", e); - } - } - if (this.inAppWebView.customSettings.useShouldInterceptRequest) { - if (this.inAppWebView.channelDelegate != null) { - let webResourceResponse = new WebResourceResponse(); - try { - this.inAppWebView.channelDelegate.shouldInterceptRequest(request).then(response => { - if (response != null) { - webResourceResponse.setResponseData(response.getData()) - webResourceResponse.setResponseMimeType(response.getContentType()) - webResourceResponse.setResponseEncoding(response.getContentEncoding()) - webResourceResponse.setResponseCode(response.getStatusCode()) - webResourceResponse.setReasonMessage(response.getReasonPhrase()) - webResourceResponse.setResponseHeader(response.getHeaderArray()) - webResourceResponse.setResponseIsReady(true) - } else { - webResourceResponse.setResponseIsReady(false); - } - }) - } catch (e) { - Log.e(TAG, "", e); - webResourceResponse.setResponseIsReady(false); - } - return webResourceResponse; - } - return null; - } - - let url: string = request.getUrl(); - let scheme = url.split(":")[0].toLowerCase(); - try { - scheme = new uri.URI(url).scheme; - } catch (e) { - - } - - if (this.inAppWebView.customSettings.resourceCustomSchemes != null && - this.inAppWebView.customSettings.resourceCustomSchemes.indexOf(scheme) > -1) { - if (this.inAppWebView.channelDelegate != null) { - let resourceResponse = new WebResourceResponse(); - try { - this.inAppWebView.channelDelegate.onLoadResourceWithCustomScheme(request).then(customSchemeResponse => { - if (customSchemeResponse != null) { - try { - response = this.inAppWebView.contentBlockerHandler.checkUrl(this.inAppWebView, request, - customSchemeResponse.getContentType()); - } catch (e) { - Log.e(TAG, "", e); - } - if (response != null) { - resourceResponse.setResponseData(response.getResponseData()) - resourceResponse.setResponseMimeType(response.getResponseMimeType()) - resourceResponse.setResponseEncoding(response.getResponseEncoding()) - resourceResponse.setResponseCode(response.getResponseCode()) - resourceResponse.setReasonMessage(response.getReasonMessage()) - resourceResponse.setResponseHeader(response.getResponseHeader()) - resourceResponse.setResponseIsReady(true) - } else { - resourceResponse.setResponseMimeType(customSchemeResponse.getContentType()); - resourceResponse.setResponseEncoding(customSchemeResponse.getContentEncoding()); - resourceResponse.setResponseData(customSchemeResponse.getData()) - } - } else { - resourceResponse.setResponseIsReady(false) - } - }); - } catch (e) { - Log.e(TAG, "", e); - resourceResponse.setResponseIsReady(false) - } - return resourceResponse; - } - } - - let response: WebResourceResponse | null = null; - if (this.inAppWebView.contentBlockerHandler.getRuleList().length > 0) { - try { - response = this.inAppWebView.contentBlockerHandler.checkUrl(this.inAppWebView, request); - } catch (e) { - Log.e(TAG, "", e); - } - } - Log.d(TAG, "onInterceptRequestend= end") - return response; - } - onHttpAuthRequest = (event: Any) => { - Log.d(TAG, "onHttpAuthRequest=" + JSON.stringify(event)) - this.onReceivedHttpAuthRequest(event.handler, event.host, event.realm) - return true; - } - onSslErrorEventReceive = (event: Any) => { - Log.d(TAG, "onSslErrorEventReceive=" + JSON.stringify(event)) - this.onReceivedSslErrorEventReceive(event.handler, event.error) - } - onClientAuthenticationRequest = (event: Any) => { - Log.d(TAG, "onClientAuthenticationRequest=" + JSON.stringify(event)) - this.onReceivedClientAuthenticationRequest(event.handler, event.host, event.port, event.keyTypes, event.issuers) - } - onPermissionRequest = (event: Any) => { - if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onPermissionRequest(event.request.getOrigin(), - event.request.getAccessibleResource(), null, - new InnerPermissionRequestCallback(event.request)); - } else { - event.request.deny(); - } - Log.d(TAG, "onPermissionRequest=" + JSON.stringify(event)) - } - onContextMenuShow = (event: Any) => { - // TODO - Log.d(TAG, "onContextMenuShow=" + JSON.stringify(event)) - return true; - } - onContextMenuHide = () => { - // TODO - Log.d(TAG, "onContextMenuHide=") - } - onScroll = (event: Any) => { - Log.d(TAG, "onScroll=" + JSON.stringify(event)) - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onScrollChanged(event.xOffset, - event.yOffset); - } - } - onGeolocationShow = (event: Any) => { - Log.d(TAG, "onGeolocationShow=" + JSON.stringify(event)) - if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onGeolocationPermissionsShowPrompt(event.origin, - new InnerGeolocationPermissionsShowPromptCallback(event.origin, event.geolocation)); - } else { - event.geolocation.invoke(event.origin, false, false); - } - } - onGeolocationHide = () => { - Log.d(TAG, "onGeolocationHide=") - if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onGeolocationPermissionsHidePrompt(); - } - } - onFullScreenEnter = (event: Any) => { - let context = this.inAppWebView.context as common.UIAbilityContext; - let windowClass = context.windowStage.getMainWindowSync(); - let windowProperties = windowClass.getWindowProperties(); - this.isOriginalLayoutFullScreen = windowProperties.isLayoutFullScreen; - this.isOriginalFullScreen = windowProperties.isFullScreen; - windowClass.setWindowLayoutFullScreen(true) - windowClass.setWindowSystemBarEnable([]) - this.fullScreenExitHandler = event.handler - Log.d(TAG, "onFullScreenEnter=" + JSON.stringify(event)) - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onEnterFullscreen(); - } - this.inAppWebView.setInFullscreen(true); - } - onFullScreenExit = () => { - Log.d(TAG, "onFullScreenExit=") - let context = this.inAppWebView.context as common.UIAbilityContext; - let windowClass = context.windowStage.getMainWindowSync(); - windowClass.setWindowLayoutFullScreen(this.isOriginalLayoutFullScreen) - windowClass.setWindowSystemBarEnable(this.isOriginalFullScreen ? [] : ['status', 'navigation']) - if (this.fullScreenExitHandler) { - this.fullScreenExitHandler.exitFullScreen() - } - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onExitFullscreen(); - } - this.inAppWebView.setInFullscreen(false); - } - onWindowNew = (event: Any) => { - Log.d(TAG, "onWindowNew=" + JSON.stringify(event)) - let windowId = 0; - if (this.plugin != null && this.plugin.inAppWebViewManager != null) { - this.plugin.inAppWebViewManager.windowAutoincrementId++; - windowId = this.plugin.inAppWebViewManager.windowAutoincrementId; - } - - let request = new URLRequest(event.targetUrl, "GET", null, new Map()); - let createWindowAction = new CreateWindowAction(request, true, event.isUserTrigger, false, windowId, event.isAlert); - if (this.plugin != null && this.plugin.inAppWebViewManager != null) { - this.plugin.inAppWebViewManager.windowWebViewMessages.set(windowId, event.handler); - } - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onCreateWindow(createWindowAction, - new InnerCreateWindowCallback(this.inAppWebView, windowId)); - } - } - onWindowExit = () => { - Log.d(TAG, "onWindowExit=") - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onCloseWindow(); - } - } - onSearchResultReceive = (event: Any) => { - Log.d(TAG, "onSearchResultReceive=" + JSON.stringify(event)) - // TODO - } - onDataResubmitted = (event: Any) => { - Log.d(TAG, "onDataResubmitted=" + JSON.stringify(event)) - let callback = new InnerFormResubmissionCallback(event.handler); - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onFormResubmission(this.inAppWebView!.controller!.getUrl(), callback); - } else { - callback.defaultBehaviour(null); - } - } - onPageVisible = (event: Any) => { - Log.d(TAG, "onPageVisible=" + JSON.stringify(event)) - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onPageCommitVisible(event.url); - } - } - onInterceptKeyEvent = (event: Any) => { - Log.d(TAG, "onInterceptKeyEvent=" + JSON.stringify(event)) - // TODO - return false; - } - onTouchIconUrlReceived = (event: Any) => { - Log.d(TAG, "onTouchIconUrlReceived=" + JSON.stringify(event)) - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onReceivedTouchIconUrl(event.url, event.precomposed); - } - } - onFaviconReceived = async (event: Any) => { - Log.d(TAG, "onFaviconReceived=" + JSON.stringify(event)) - let options: image.PackingOption = { - format: 'image/png', - quality: 100 - }; - let packer = image.createImagePacker(); - let imageBuffer = await packer.packing(event.favicon, options); - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onReceivedIcon(imageBuffer); - } - await event.favicon.release() - await packer.release() - } - onAudioStateChanged = (event: Any) => { - Log.d(TAG, "onAudioStateChanged=" + JSON.stringify(event)) - // TODO - } - onFirstContentfulPaint = (event: Any) => { - Log.d(TAG, "onFirstContentfulPaint=" + JSON.stringify(event)) - // TODO - } - onLoadIntercept = (event: Any) : boolean => { - Log.d(TAG, "onLoadIntercept=" + event.data.getRequestUrl()) - // TODO - return false; - } - onOverrideUrlLoading = (request: WebResourceRequest) : boolean => { - Log.d(TAG, "onOverrideUrlLoading=" + request.getRequestUrl()) - if (this.inAppWebView.customSettings.useShouldOverrideUrlLoading) { - let headers = new Map() - request.getRequestHeader().forEach(header => headers.set(header.headerKey, header.headerValue)); - - this.onShouldOverrideUrlLoading( - this.inAppWebView, - request.getRequestUrl(), - request.getRequestMethod(), - headers, - request.isMainFrame(), - request.isRequestGesture(), - request.isRedirect()); - - if (this.inAppWebView.regexToCancelSubFramesLoadingCompiled != null) { - if (request.isMainFrame()) - return true - else { - return this.inAppWebView.regexToCancelSubFramesLoadingCompiled!.test(request.getRequestUrl()); - } - } else { - // There isn't any way to load an URL for a frame that is not the main frame, - // so if the request is not for the main frame, the navigation is allowed. - return request.isMainFrame(); - } - } - return false; - } - onRequestSelected = () => { - Log.d(TAG, "onRequestSelected=") - if(this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onRequestFocus(); - } - } - onScreenCaptureRequest = (event: Any) => { - Log.d(TAG, "onScreenCaptureRequest=" + JSON.stringify(event)) - // TODO - } - onOverScroll = (event: Any) => { - // TODO 没有clampedX clampedY? - Log.d(TAG, "onOverScroll=" + JSON.stringify(event)) - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.canScrollHorizontally({ - onReceiveValue(canScroll: boolean | null): void { - let overScrolledHorizontally: boolean = canScroll!; - let overScrolledVertically: boolean = this.inAppWebView.canScrollVertically(); - this.inAppWebView.channelDelegate.onOverScrolled(event.xOffset, event.yOffset, overScrolledHorizontally, overScrolledVertically); - } - }); - } - } - onNavigationEntryCommitted = () => { - Log.d(TAG, "onNavigationEntryCommitted=") - // TODO - } - onSafeBrowsingCheckResult = (threatType: ThreatType) => { - Log.d(TAG, "onSafeBrowsingCheckResult=") - let resultCallback = new InnerSafeBrowsingHitCallback(); - if (this.inAppWebView.channelDelegate != null) { - let url = this.inAppWebView!.controller!.getUrl(); - this.inAppWebView.channelDelegate.onSafeBrowsingHit(url, threatType, resultCallback); - } else { - resultCallback.defaultBehaviour(null); - } - } - onNativeEmbedLifecycleChange = (callback: NativeEmbedDataInfo) => { - Log.d(TAG, "onNativeEmbedLifecycleChange=") - // TODO - } - onNativeEmbedGestureEvent = (callback: NativeEmbedTouchInfo) => { - Log.d(TAG, "onNativeEmbedGestureEvent=") - // TODO - } - - private onShouldOverrideUrlLoading(webView: InAppWebView, url: string, method: string, - headers: Map, - isForMainFrame: boolean, hasGesture: boolean, isRedirect: boolean) { - let request = new URLRequest(url, method, null, headers); - let navigationAction = new NavigationAction(request, isForMainFrame, hasGesture, isRedirect); - - let callback = new InnerShouldOverrideUrlLoadingCallback(this.inAppWebView, url, headers, isForMainFrame) - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.shouldOverrideUrlLoading(navigationAction, callback); - } else { - callback.defaultBehaviour(null); - } - } - - private async onReceivedHttpAuthRequest(handler: HttpAuthHandler, host: string, realm: string) { - let url = this.inAppWebView!.controller!.getUrl(); - let protocol = "https"; - let port = 0; - - if (url != null) { - try { - let uriurl = new uri.URI(url); - protocol = uriurl.scheme; - port = Number.parseInt(uriurl.port); - } catch (e) { - Log.e(TAG, "", e); - } - } - - InAppWebViewChromeClient.previousAuthRequestFailureCount++; - - if (InAppWebViewChromeClient.credentialsProposed == null) { - InAppWebViewChromeClient.credentialsProposed = await CredentialDatabase.getInstance(this.inAppWebView.context) - .getHttpAuthCredentials(host, protocol, realm, port); - } - - let credentialProposed: URLCredential | null = null; - if (InAppWebViewChromeClient.credentialsProposed != null && - InAppWebViewChromeClient.credentialsProposed.length > 0) { - credentialProposed = InAppWebViewChromeClient.credentialsProposed.get(0); - } - - let certificate: cert.X509Cert | null = null; - let certificates = await this.inAppWebView!.controller!.getCertificate(); - if (certificates && certificates.length > 0) { - certificate = certificates[0]; - } - let protectionSpace = new URLProtectionSpace(host, protocol, realm, port, null, certificate, null); - let challenge = - new HttpAuthenticationChallenge(protectionSpace, InAppWebViewChromeClient.previousAuthRequestFailureCount, - credentialProposed); - - let callback = new InnerReceivedHttpAuthRequestCallback(this.inAppWebView, handler, host, protocol, realm, port); - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onReceivedHttpAuthRequest(challenge, callback); - } else { - callback.defaultBehaviour(null); - } - } - - private onReceivedSslErrorEventReceive(handler: SslErrorHandler, sslError: SslError) { - let url = this.inAppWebView!.controller!.getUrl(); - let host = ""; - let protocol = "https"; - let port = 0; - - try { - let uriurl = new uri.URI(url); - host = uriurl.host; - protocol = uriurl.scheme; - port = Number.parseInt(uriurl.port); - } catch (e) { - Log.e(TAG, "", e); - } - - // TODO sslError.getCertificate()没有这方法 用null先适配 - let protectionSpace = new URLProtectionSpace(host, protocol, null, port, null, null, sslError); - let challenge = new ServerTrustChallenge(protectionSpace); - let callback = new InnerReceivedServerTrustAuthRequestCallback(handler); - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onReceivedServerTrustAuthRequest(challenge, callback); - } else { - callback.defaultBehaviour(null); - } - } - - private async onReceivedClientAuthenticationRequest(handler: ClientAuthenticationHandler, host: string, - port: number, keyTypes: Array, issuers: Array) { - let url = this.inAppWebView!.controller!.getUrl(); - let protocol = "https"; - - if (url != null) { - try { - let uriurl = new uri.URI(url); - protocol = uriurl.scheme; - } catch (e) { - Log.e(TAG, "", e); - } - } - - let certificate: cert.X509Cert | null = null; - let certificates = await this.inAppWebView!.controller!.getCertificate(); - if (certificates && certificates.length > 0) { - certificate = certificates[0]; - } - let protectionSpace = new URLProtectionSpace(host, protocol, null, port, null, certificate, null); - let challenge = new ClientCertChallenge(protectionSpace, issuers, keyTypes); - - let callback = new InnerReceivedClientCertRequestCallback(this.inAppWebView!, handler); - if (this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onReceivedClientCertRequest(challenge, callback); - } else { - callback.defaultBehaviour(null); - } - } - - private loadCustomJavaScriptOnPageStarted(webView: InAppWebView) { - let source = webView.userContentController.generateWrappedCodeForDocumentStart(); - webView.controller.runJavaScriptExt(source) - } - - private loadCustomJavaScriptOnPageFinished(webView: InAppWebView) { - let source = webView.userContentController.generateWrappedCodeForDocumentEnd(); - webView.controller.runJavaScriptExt(source) - } - - private needsCameraPermission(): boolean { - return false - } - - private acceptsVideo(types: Array): boolean { - let mimeTypes = this.getAcceptedMimeType(types); - return this.acceptsAny(mimeTypes) || this.arrayContainsString(mimeTypes, "video"); - } - - private acceptsImages(types: Array): boolean { - let mimeTypes = this.getAcceptedMimeType(types); - return this.acceptsAny(mimeTypes) || this.arrayContainsString(mimeTypes, "image"); - } - - private getAcceptedMimeType(types: Array): Array { - if (this.isArrayEmpty(types)) { - return ["*/*"]; - } - let mimeTypes = new Array(); - for (let i = 0; i < types.length; i++) { - let t = types[i]; - // convert file extensions to mime types - if (t.indexOf(".") > -1) { - let mimeType = MimeTypes.getMimeTypeFromExtension(t.replace(".", "")); - mimeTypes[i] = mimeType; - } else { - mimeTypes[i] = t; - } - } - return mimeTypes; - } - - private acceptsAny(types: Array) { - if (this.isArrayEmpty(types)) { - return true; - } - for (let type of types) { - if (type == "*/*") { - return true; - } - } - return false; - } - - private arrayContainsString(array: Array, pattern: string): boolean { - for (let content of array) { - if (content != null && content.indexOf(pattern) > -1) { - return true; - } - } - return false; - } - - private isArrayEmpty(arr: Array): boolean { - // when our array returned from getAcceptTypes() has no values set from the webview - // i.e. , without any "accept" attr - // will be an array with one empty string element, afaik - return arr.length == 0 || (arr.length == 1 && arr[0].length == 0); - } -} - -class InnerJsAlertCallback extends JsAlertCallback { - private result: JsResult; - private message: string; - - constructor(result: JsResult, message: string) { - super(); - this.result = result; - this.message = message; - } - - nonNullSuccess(response: JsAlertResponse): boolean { - if (response.isHandledByClient()) { - let action = response.getAction(); - action = action != null ? action : 1; - switch (action) { - case 0: - this.result.handleConfirm(); - break; - case 1: - default: - this.result.handleCancel(); - } - return false; - } - return true; - } - - defaultBehaviour(response: JsAlertResponse | null): void { - let responseMessage: string | null = null; - let confirmButtonTitle: string | null = null; - if (response != null) { - responseMessage = response.getMessage(); - confirmButtonTitle = response.getConfirmButtonTitle(); - } - this.createAlertDialog(this.message, this.result, responseMessage, confirmButtonTitle); - } - - error(errorCode: string, errorMessage: string, errorDetails: Any): void { - Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); - this.result.handleCancel(); - } - - private createAlertDialog(message: string, result: JsResult, responseMessage: string | null, - confirmButtonTitle: string | null) { - let alertMessage = (responseMessage != null && responseMessage.length > 0) ? responseMessage : message; - AlertDialog.show( - { - message: alertMessage, - autoCancel: true, - alignment: DialogAlignment.Center, - confirm: { - value: confirmButtonTitle != null ? confirmButtonTitle : "确定", - action: () => { - result.handleConfirm() - } - }, - cancel: () => { - result.handleCancel() - } - } - ) - } -} - -class InnerJsConfirmCallback extends JsConfirmCallback { - private result: JsResult; - private message: string; - - constructor(result: JsResult, message: string) { - super(); - this.result = result; - this.message = message; - } - - nonNullSuccess(response: JsConfirmResponse): boolean { - if (response.isHandledByClient()) { - let action = response.getAction(); - action = action != null ? action : 1; - switch (action) { - case 0: - this.result.handleConfirm(); - break; - case 1: - default: - this.result.handleCancel(); - } - return false; - } - return true; - } - - defaultBehaviour(response: JsConfirmResponse | null): void { - let responseMessage: string | null = null; - let confirmButtonTitle: string | null = null; - let cancelButtonTitle: string | null = null; - if (response != null) { - responseMessage = response.getMessage(); - confirmButtonTitle = response.getConfirmButtonTitle(); - cancelButtonTitle = response.getCancelButtonTitle(); - } - this.createConfirmDialog(this.message, this.result, responseMessage, confirmButtonTitle, cancelButtonTitle); - } - - error(errorCode: string, errorMessage: string, errorDetails: Any): void { - Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); - this.result.handleCancel(); - } - - private createConfirmDialog(message: string, result: JsResult, responseMessage: string | null, - confirmButtonTitle: string | null, cancelButtonTitle: string | null) { - let alertMessage = (responseMessage != null && responseMessage.length > 0) ? responseMessage : message; - AlertDialog.show( - { - message: alertMessage, - autoCancel: true, - alignment: DialogAlignment.Center, - primaryButton: { - value: cancelButtonTitle != null ? cancelButtonTitle : "取消", - action: () => { - result.handleCancel() - } - }, - secondaryButton: { - defaultFocus: true, - value: confirmButtonTitle != null ? confirmButtonTitle : "确定", - action: () => { - result.handleConfirm() - } - }, - cancel: () => { - result.handleCancel() - } - } - ) - } -} - -class InnerJsPromptCallback extends JsPromptCallback { - private result: JsResult; - private message: string; - private defaultValue: string; - private uiObject: Any; - - constructor(result: JsResult, message: string, defaultValue: string, uiObject: Any) { - super(); - this.result = result; - this.message = message; - this.defaultValue = defaultValue; - this.uiObject = uiObject; - } - - nonNullSuccess(response: JsPromptResponse): boolean { - if (response.isHandledByClient()) { - let action = response.getAction(); - action = action != null ? action : 1; - switch (action) { - case 0: - this.result.handlePromptConfirm(response.getValue()); - break; - case 1: - default: - this.result.handleCancel(); - } - return false; - } - return true; - } - - defaultBehaviour(response: JsPromptResponse | null): void { - let responseMessage: string | null = null; - let responseDefaultValue: string | null = null; - let value: string | null = null; - let confirmButtonTitle: string | null = null; - let cancelButtonTitle: string | null = null; - if (response != null) { - responseMessage = response.getMessage(); - responseDefaultValue = response.getDefaultValue(); - value = response.getValue(); - confirmButtonTitle = response.getConfirmButtonTitle(); - cancelButtonTitle = response.getCancelButtonTitle(); - } - this.createPromptDialog(this.message, this.defaultValue, this.result, responseMessage, responseDefaultValue, value, - cancelButtonTitle, confirmButtonTitle); - } - - error(errorCode: string, errorMessage: string, errorDetails: Any): void { - Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); - this.result.handleCancel(); - } - - private createPromptDialog(message: string, defaultValue: string, result: JsResult, responseMessage: string | null, - responseDefaultValue: string | null, value: string | null, cancelButtonTitle: string | null, - confirmButtonTitle: string | null) { - let initValue = - (responseDefaultValue != null && responseDefaultValue.length > 0) ? responseDefaultValue : defaultValue; - let alertMessage = (responseMessage != null && responseMessage.length > 0) ? responseMessage : message; - let finalValue = value; - let customDialogId = -1; - let isCancel = true; - promptAction.openCustomDialog({ - builder: ohosPromptDialogBuilder.bind(this.uiObject, initValue, alertMessage, cancelButtonTitle, - confirmButtonTitle, () => { - isCancel = false - result.handleCancel() - promptAction.closeCustomDialog(customDialogId) - }, (value: string | null) => { - isCancel = false - promptAction.closeCustomDialog(customDialogId) - result.handlePromptConfirm(finalValue != null ? finalValue : value); - }), - alignment: DialogAlignment.Center, - onDidDisappear: () => { - if (isCancel) { - result.handleCancel() - } - } - }).then((dialogId: number) => { - customDialogId = dialogId - }) - } -} - -class InnerJsBeforeUnloadCallback extends JsBeforeUnloadCallback { - private result: JsResult; - private message: string; - - constructor(result: JsResult, message: string) { - super(); - this.result = result; - this.message = message; - } - - nonNullSuccess(response: JsBeforeUnloadResponse): boolean { - if (response.isHandledByClient()) { - let action = response.getAction(); - action = action != null ? action : 1; - switch (action) { - case 0: - this.result.handleConfirm(); - break; - case 1: - default: - this.result.handleCancel(); - } - return false; - } - return true; - } - - defaultBehaviour(response: JsBeforeUnloadResponse | null): void { - let responseMessage: string | null = null; - let confirmButtonTitle: string | null = null; - let cancelButtonTitle: string | null = null; - if (response != null) { - responseMessage = response.getMessage(); - confirmButtonTitle = response.getConfirmButtonTitle(); - cancelButtonTitle = response.getCancelButtonTitle(); - } - this.createBeforeUnloadDialog(this.message, this.result, responseMessage, confirmButtonTitle, cancelButtonTitle); - } - - error(errorCode: string, errorMessage: string, errorDetails: Any): void { - Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); - this.result.handleCancel(); - } - - private createBeforeUnloadDialog(message: string, result: JsResult, responseMessage: string | null, - confirmButtonTitle: string | null, cancelButtonTitle: string | null) { - let alertMessage = (responseMessage != null && responseMessage.length > 0) ? responseMessage : message; - AlertDialog.show( - { - message: alertMessage, - autoCancel: true, - alignment: DialogAlignment.Center, - primaryButton: { - value: cancelButtonTitle != null ? cancelButtonTitle : "取消", - action: () => { - result.handleCancel() - } - }, - secondaryButton: { - defaultFocus: true, - value: confirmButtonTitle != null ? confirmButtonTitle : "确定", - action: () => { - result.handleConfirm() - } - }, - cancel: () => { - result.handleCancel() - } - } - ) - } -} - -class InnerPermissionRequestCallback extends PermissionRequestCallback { - private request: PermissionRequest; - - constructor(request: PermissionRequest) { - super(); - this.request = request; - } - - nonNullSuccess(response: PermissionResponse): boolean { - let action = response.getAction(); - if (action != null) { - switch (action) { - case 1: - this.request.grant(response.getResources().convertToArray()); - break; - case 0: - default: - this.request.deny(); - } - return false; - } - return true; - } - - defaultBehaviour(response: PermissionResponse | null): void { - this.request.deny(); - } - - error(errorCode: string, errorMessage: string, errorDetails: Any): void { - Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); - this.defaultBehaviour(null); - } -} - -class InnerGeolocationPermissionsShowPromptCallback extends GeolocationPermissionsShowPromptCallback { - private geolocation: JsGeolocation; - private origin: string; - - constructor(origin: string, geolocation: JsGeolocation) { - super(); - this.geolocation = geolocation; - this.origin = origin; - } - - nonNullSuccess(response: GeolocationPermissionShowPromptResponse): boolean { - this.geolocation.invoke(response.getOrigin(), response.isAllow(), response.isRetain()); - return false; - } - - defaultBehaviour(response: GeolocationPermissionShowPromptResponse | null): void { - this.geolocation.invoke(this.origin, false, false); - } - - error(errorCode: string, errorMessage: string, errorDetails: Any): void { - Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); - this.defaultBehaviour(null); - } -} - -class InnerReceivedHttpAuthRequestCallback extends ReceivedHttpAuthRequestCallback { - private handler: HttpAuthHandler; - private host: string; - private finalProtocol: string; - private realm: string; - private finalPort: number; - private inAppWebView: InAppWebView; - - constructor(inAppWebView: InAppWebView, handler: HttpAuthHandler, host: string, protocol: string, realm: string, - port: number) { - super(); - this.handler = handler; - this.host = host; - this.finalProtocol = protocol; - this.realm = realm; - this.finalPort = port; - this.inAppWebView = inAppWebView; - } - - nonNullSuccess(response: HttpAuthResponse): boolean { - let action = response.getAction(); - if (action != null) { - switch (action) { - case 1: - let username = response.getUsername(); - let password = response.getPassword(); - let permanentPersistence = response.isPermanentPersistence(); - if (permanentPersistence) { - CredentialDatabase.getInstance(this.inAppWebView.context) - .setHttpAuthCredential(this.host, this.finalProtocol, this.realm, this.finalPort, username, password); - } - this.handler.confirm(username, password); - break; - case 2: - if (InAppWebViewChromeClient.credentialsProposed!.length > 0) { - let credential = InAppWebViewChromeClient.credentialsProposed!.removeByIndex(0); - this.handler.confirm(credential.getUsername(), credential.getPassword()); - } else { - this.handler.cancel(); - } - // used custom CredentialDatabase! - // handler.useHttpAuthUsernamePassword(); - break; - case 0: - default: - InAppWebViewChromeClient.credentialsProposed = null; - InAppWebViewChromeClient.previousAuthRequestFailureCount = 0; - this.handler.cancel(); - } - return false; - } - return true; - } - - defaultBehaviour(result: HttpAuthResponse | null): void { - if (result == null) { - this.handler.cancel(); - } else { - this.nonNullSuccess(result) - } - } - - error(errorCode: string, errorMessage: string, errorDetails: Any): void { - Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); - this.defaultBehaviour(null); - } -} - -class InnerReceivedServerTrustAuthRequestCallback extends ReceivedServerTrustAuthRequestCallback { - private handler: SslErrorHandler; - - constructor(handler: SslErrorHandler) { - super(); - this.handler = handler; - } - - nonNullSuccess(response: ServerTrustAuthResponse): boolean { - let action = response.getAction(); - if (action != null) { - switch (action) { - case 1: - this.handler.handleConfirm(); - break; - case 0: - default: - this.handler.handleCancel(); - } - return false; - } - return true; - } - - defaultBehaviour(result: ServerTrustAuthResponse | null) { - if (result != null) { - this.nonNullSuccess(result); - } else { - this.handler.handleCancel(); - } - } - - error(errorCode: string, errorMessage: string, errorDetails: Any): void { - Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); - this.defaultBehaviour(null); - } -} - -class InnerReceivedClientCertRequestCallback extends ReceivedClientCertRequestCallback { - private handler: ClientAuthenticationHandler; - private inAppWebView: InAppWebView; - - constructor(inAppWebView: InAppWebView, handler: ClientAuthenticationHandler) { - super(); - this.inAppWebView = inAppWebView; - this.handler = handler; - } - - nonNullSuccess(response: ClientCertResponse): boolean { - let action = response.getAction(); - if (action != null && this.inAppWebView.plugin != null) { - switch (action) { - case 1: { - let certificatePath = response.getCertificatePath(); - let certificatePassword = response.getCertificatePassword(); - let keyStoreType = response.getKeyStoreType(); - //TODO priKeyFile? - this.handler.confirm(keyStoreType, certificatePath) - } - break; - case 2: - this.handler.ignore(); - break; - case 0: - default: - this.handler.cancel(); - } - return false; - } - return true; - } - - defaultBehaviour(result: ClientCertResponse | null) { - if (result != null) { - this.nonNullSuccess(result); - } else { - this.handler.cancel(); - } - } - - error(errorCode: string, errorMessage: string, errorDetails: Any): void { - Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); - this.defaultBehaviour(null); - } -} - -class InnerCreateWindowCallback extends CreateWindowCallback { - private finalWindowId: number; - private inAppWebView: InAppWebView; - - constructor(inAppWebView: InAppWebView, finalWindowId: number) { - super(); - this.inAppWebView = inAppWebView; - this.finalWindowId = finalWindowId; - } - - nonNullSuccess(handledByClient: boolean): boolean { - return !handledByClient; - } - - defaultBehaviour(handledByClient: boolean | null) { - if (this.inAppWebView.plugin != null && this.inAppWebView.plugin.inAppWebViewManager != null) { - this.inAppWebView.plugin.inAppWebViewManager.windowWebViewMessages.delete(this.finalWindowId); - } - } - - error(errorCode: string, errorMessage: string, errorDetails: Any): void { - Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); - this.defaultBehaviour(null); - } -} - -class InnerFormResubmissionCallback extends FormResubmissionCallback { - private hanlder: DataResubmissionHandler; - - constructor(hanlder: DataResubmissionHandler) { - super(); - this.hanlder = hanlder; - } - - nonNullSuccess(action: number): boolean { - switch (action) { - case 0: - this.hanlder.resend(); - break; - case 1: - default: - this.hanlder.cancel(); - } - return false; - } - - defaultBehaviour(result: number | null) { - if (result != null) { - this.nonNullSuccess(result); - } else { - this.hanlder.cancel(); - } - } - - error(errorCode: string, errorMessage: string, errorDetails: Any): void { - Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); - this.defaultBehaviour(null); - } -}; - -class InnerShouldOverrideUrlLoadingCallback extends ShouldOverrideUrlLoadingCallback { - - private inAppWebView: InAppWebView; - private url: string; - private headers: Map; - private isForMainFrame: boolean; - - constructor(inAppWebView: InAppWebView, url: string, headers: Map, isForMainFrame: boolean) { - super(); - this.inAppWebView = inAppWebView; - this.url = url; - this.headers = headers; - this.isForMainFrame = isForMainFrame; - } - - nonNullSuccess(result: NavigationActionPolicy) : boolean { - switch (result) { - case NavigationActionPolicy.ALLOW: - this.allowShouldOverrideUrlLoading(this.inAppWebView, this.url, this.headers, this.isForMainFrame); - break; - case NavigationActionPolicy.CANCEL: - default: - break; - } - return false; - } - - defaultBehaviour(result: NavigationActionPolicy | null) { - this.allowShouldOverrideUrlLoading(this.inAppWebView, this.url, this.headers, this.isForMainFrame); - } - - error(errorCode: string, errorMessage: string, errorDetails: Any): void { - Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); - this.defaultBehaviour(null); - } - - allowShouldOverrideUrlLoading(inAppWebView: InAppWebView, url: string, headers: Map, - isForMainFrame: boolean) { - if (isForMainFrame) { - this.inAppWebView.controller.loadUrl(url, this.inAppWebView.toWebHeaders(headers)); - } - } -}; - -class InnerSafeBrowsingHitCallback extends SafeBrowsingHitCallback { - public nonNullSuccess(response: SafeBrowsingResponse): boolean { - let action = response.getAction(); - if (action != null) { - let report = response.isReport(); - switch (action) { - case 0: // TODO android backToSafety - return true; - break; - case 1: // TODO android proceed - return true; - break; - case 2: - default: //TODO android showInterstitial - return true; - } - return false; - } - return true; - } - - defaultBehaviour(result: SafeBrowsingResponse | null) { - if (result != null) { - this.nonNullSuccess(result) - } - } - - error(errorCode: string, errorMessage: string, errorDetails: Any): void { - Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); - this.defaultBehaviour(null); - } -} \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewClient.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewClient.ets index 0d3d319024fa08b7e732592789df14391bb9c2da..1129f339477ce72491cb25c0312f22389e144b9b 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewClient.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewClient.ets @@ -13,6 +13,1597 @@ * limitations under the License. */ -export class InAppWebViewClient { //extends WebViewClient +import { Any, Log } from '@ohos/flutter_ohos'; +import web_webview from '@ohos.web.webview'; +import cameraPicker from '@ohos.multimedia.cameraPicker'; +import picker from '@ohos.file.picker'; +import uri from '@ohos.uri' +import InAppWebViewFlutterPlugin from '../../InAppWebViewFlutterPlugin'; +import DownloadStartRequest from '../../types/DownloadStartRequest'; +import URLUtil from '../../types/URLUtil'; +import InAppWebView from './InAppWebView'; +import WebResourceResponseExt from '../../types/WebResourceResponseExt'; +import CustomSchemeResponse from '../../types/CustomSchemeResponse'; +import WebResourceRequestExt from '../../types/WebResourceRequestExt'; +import URLRequest from '../../types/URLRequest'; +import NavigationAction from '../../types/NavigationAction'; +import { NavigationActionPolicy } from '../../types/NavigationActionPolicy'; +import URLCredential from '../../types/URLCredential'; +import JavaScriptBridgeJS from '../../plugin_scripts_js/JavaScriptBridgeJS'; +import { image } from '@kit.ImageKit'; +import { InAppBrowserDelegate } from '../../in_app_browser/InAppBrowserDelegate'; +import WebResourceErrorExt from '../../types/WebResourceErrorExt'; +import Util from '../../Util'; +import { + GeolocationPermissionsShowPromptCallback, + JsAlertCallback, + JsBeforeUnloadCallback, + JsConfirmCallback, + JsPromptCallback, + PermissionRequestCallback, + ReceivedHttpAuthRequestCallback, + ReceivedServerTrustAuthRequestCallback, + ReceivedClientCertRequestCallback, + CreateWindowCallback, + FormResubmissionCallback, + ShouldOverrideUrlLoadingCallback, + SafeBrowsingHitCallback, + RenderProcessUnresponsiveCallback, + RenderProcessResponsiveCallback +} from '../WebViewChannelDelegate'; +import JsAlertResponse from '../../types/JsAlertResponse'; +import JsConfirmResponse from '../../types/JsConfirmResponse'; +import JsPromptResponse from '../../types/JsPromptResponse'; +import HttpAuthResponse from '../../types/HttpAuthResponse'; +import { ohosPromptDialogBuilder } from './OhosPromptDialog'; +import { promptAction } from '@kit.ArkUI'; +import JsBeforeUnloadResponse from '../../types/JsBeforeUnloadResponse'; +import { camera } from '@kit.CameraKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import MimeTypes from '../../MimeTypes'; +import PermissionResponse from '../../types/PermissionResponse'; +import GeolocationPermissionShowPromptResponse from '../../types/GeolocationPermissionShowPromptResponse'; +import CredentialDatabase from '../../credential_database/CredentialDatabase'; +import HttpAuthenticationChallenge from '../../types/HttpAuthenticationChallenge'; +import URLProtectionSpace from '../../types/URLProtectionSpace'; +import ServerTrustAuthResponse from '../../types/ServerTrustAuthResponse'; +import ServerTrustChallenge from '../../types/ServerTrustChallenge'; +import ClientCertChallenge from '../../types/ClientCertChallenge'; +import ClientCertResponse from '../../types/ClientCertResponse'; +import CreateWindowAction from '../../types/CreateWindowAction'; +import SafeBrowsingResponse from '../../types/SafeBrowsingResponse'; +import { cert } from '@kit.DeviceCertificateKit' +import { List } from '@kit.ArkTS'; +import { common } from '@kit.AbilityKit'; +const TAG = "InAppWebViewClient"; + +// 参考文档 所有事件 https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-arkweb/ts-basic-components-web.md#onalert +export default class InAppWebViewClient { + public static previousAuthRequestFailureCount = 0; + public static credentialsProposed: List | null = null; + private plugin: InAppWebViewFlutterPlugin; + private inAppWebView: InAppWebView; + private inAppBrowserDelegate: InAppBrowserDelegate | null = null; + private fullScreenExitHandler: FullScreenExitHandler | null = null; + private isOriginalLayoutFullScreen = false; + private isOriginalFullScreen = false; + public progress = 0; + + constructor(plugin: InAppWebViewFlutterPlugin, inAppWebView: InAppWebView) { + this.plugin = plugin; + this.inAppWebView = inAppWebView; + } + + onAlert = (event: Any) => { + Log.d(TAG, "onAlert=" + JSON.stringify(event)) + if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onJsAlert(event.url, event.message, null, + new InnerJsAlertCallback(event.result, event.message)); + return true; + } + return false; + } + onBeforeUnload = (event: Any) => { + Log.d(TAG, "onBeforeUnload=" + JSON.stringify(event)) + if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onJsBeforeUnload(event.url, event.message, + new InnerJsBeforeUnloadCallback(event.result, event.message)); + return true; + } + return false; + } + onConfirm = (event: Any) => { + Log.d(TAG, "onConfirm=" + JSON.stringify(event)) + if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onJsConfirm(event.url, event.message, null, + new InnerJsConfirmCallback(event.result, event.message)); + return true; + } + return false; + } + onPrompt = (event: Any, uiObject: Any) => { + Log.d(TAG, "onPrompt=" + JSON.stringify(event)) + if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onJsPrompt(event.url, event.message, event.value, null, + new InnerJsPromptCallback(event.result, event.message, event.value, uiObject)); + return true; + } + return false; + } + onConsole = (event: Any) => { + Log.d(TAG, "onConsole=" + JSON.stringify(event)) + if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onConsoleMessage(event.message.getMessage(), event.message.getMessageLevel()); + return true; + } + return false; + } + onDownloadStart = (event: Any) => { //对应安卓setDownloadListener + Log.d(TAG, "onDownloadStart=" + JSON.stringify(event)) + if (this.inAppWebView.customSettings.useOnDownloadStart) { + let downloadStartRequest = new DownloadStartRequest( + event.url, + event.userAgent, + event.contentDisposition, + event.mimetype, + event.contentLength, + URLUtil.guessFileName(event.url, event.contentDisposition, event.mimetype), + null + ); + this.inAppWebView.channelDelegate.onDownloadStartRequest(downloadStartRequest) + } + } + onErrorReceive = (event: Any) => { + Log.d(TAG, "onErrorReceive=" + JSON.stringify(event)) + let request: WebResourceRequest = event.request; + let error: WebResourceError = event.error; + if (request.isMainFrame()) { + if (this.inAppWebView.customSettings.disableDefaultErrorPage) { + this.inAppWebView.stopLoading(); + this.inAppWebView.controller.loadUrl("about:blank"); + } + + this.inAppWebView.isLoading = false; + InAppWebViewClient.previousAuthRequestFailureCount = 0; + InAppWebViewClient.credentialsProposed = null; + + if (this.inAppBrowserDelegate != null) { + let type = error.getErrorCode(); + let description = error.getErrorInfo(); + this.inAppBrowserDelegate.didFailNavigation(request.getRequestUrl(), type, description); + } + } + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onReceivedError( + WebResourceRequestExt.fromWebResourceRequest(request), + WebResourceErrorExt.fromWebResourceError(error)); + } + } + onHttpErrorReceive = (event: Any) => { + Log.d(TAG, "onHttpErrorReceive=" + JSON.stringify(event)) + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onReceivedHttpError( + WebResourceRequestExt.fromWebResourceRequest(event.request), + WebResourceResponseExt.fromWebResourceResponse(event.response)); + } + } + onPageBegin = (event: Any) => { + Log.d(TAG, "onPageBegin=" + JSON.stringify(event)) + this.inAppWebView.isLoading = true; + this.inAppWebView.disposeWebMessageChannels(); + this.inAppWebView.userContentController.resetContentWorlds(); + this.loadCustomJavaScriptOnPageStarted(this.inAppWebView); + + if (this.inAppBrowserDelegate != null) { + this.inAppBrowserDelegate.didStartNavigation(event.url); + } + + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onLoadStart(event.url); + } + } + onPageEnd = (event: Any) => { + Log.d(TAG, "onPageBegin=" + JSON.stringify(event)) + this.inAppWebView.isLoading = false; + this.loadCustomJavaScriptOnPageFinished(this.inAppWebView); + InAppWebViewClient.previousAuthRequestFailureCount = 0; + InAppWebViewClient.credentialsProposed = null; + + if (this.inAppBrowserDelegate != null) { + this.inAppBrowserDelegate.didFinishNavigation(event.url); + } + + web_webview.WebCookieManager.saveCookieAsync() + + let js = JavaScriptBridgeJS.PLATFORM_READY_JS_SOURCE; + this.inAppWebView.controller.runJavaScriptExt(js) + + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onLoadStop(event.url); + } + } + onProgressChange = (event: Any) => { + Log.d(TAG, "onProgressChange=" + JSON.stringify(event)) + if (this.inAppBrowserDelegate != null) { + this.inAppBrowserDelegate.didChangeProgress(event.newProgress); + } + + this.progress = event.newProgress + this.loadCustomJavaScriptOnPageStarted(this.inAppWebView); + + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onProgressChanged(event.newProgress); + } + } + onTitleReceive = (event: Any) => { + Log.d(TAG, "onTitleReceive=" + JSON.stringify(event)) + if (this.inAppBrowserDelegate != null) { + this.inAppBrowserDelegate.didChangeTitle(event.title); + } + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onTitleChanged(event.title); + } + } + onRefreshAccessedHistory = (event: Any) => { + Log.d(TAG, "onRefreshAccessedHistory=" + JSON.stringify(event)) + if (this.inAppBrowserDelegate != null) { + this.inAppBrowserDelegate.didUpdateVisitedHistory(event.url); + } + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onUpdateVisitedHistory(event.url, event.isRefreshed); + } + } + onRenderExited = (event: Any) => { + Log.d(TAG, "onRenderExited=" + JSON.stringify(event)) + if (this.inAppWebView.customSettings.useOnRenderProcessGone && this.inAppWebView.channelDelegate != null) { + let didCrash = event.renderExitReason == RenderExitReason.ProcessCrashed; + this.inAppWebView.channelDelegate.onRenderProcessGone(didCrash, event.renderExitReason); + } + } + onShowFileSelector = (event: Any) => { + Log.d(TAG, "onShowFileSelector=" + JSON.stringify(event)) + Log.d(TAG, "onShowFileSelector=" + JSON.stringify(event.fileSelector)) + let acceptTypes: Array = event.fileSelector.getAcceptType(); + let allowMultiple = event.fileSelector.getMode() == FileSelectorMode.FileOpenMultipleMode; + let captureEnabled: boolean = event.fileSelector.isCapture(); + let images = this.acceptsImages(acceptTypes); + let video = this.acceptsVideo(acceptTypes); + if (captureEnabled) { + if (!this.needsCameraPermission()) { + if (images || video) { + let pickerProfile: cameraPicker.PickerProfile = { + cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK + }; + cameraPicker.pick(this.inAppWebView.context, + images ? [cameraPicker.PickerMediaType.PHOTO] : [cameraPicker.PickerMediaType.VIDEO], pickerProfile) + .then(result => { + event.result.handleFileList([result.resultUri]); + }).catch((err: BusinessError) => { + event.result.handleFileList([]); + Log.e(TAG, `the pick call failed. error code: ${err.code}`); + }); + return true; + } + } + } + + //缺少从系统直接选择全部,这里做了一个弹窗选择 这里OHOS存在一个bug。 + ActionSheet.show({ + title: '请选择', + message: '', + autoCancel: true, + isModal: true, + cancel: () => { + Log.d(TAG, 'actionSheet canceled') + event.result.handleFileList([]); + }, + alignment: DialogAlignment.Center, + offset: { + dx: 0, dy: 100 + }, + sheets: [ + { + title: '相册', + action: () => { + Log.d(TAG, 'apples') + let photoSelectOptions = new picker.PhotoSelectOptions(); + photoSelectOptions.MIMEType = (images && video) ? picker.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE : + (images ? picker.PhotoViewMIMETypes.IMAGE_TYPE : picker.PhotoViewMIMETypes.VIDEO_TYPE); + photoSelectOptions.maxSelectNumber = allowMultiple ? 100000 : 1 + let photoPicker = new picker.PhotoViewPicker(); + photoPicker.select(photoSelectOptions).then((photoSelectResult: picker.PhotoSelectResult) => { + event.result.handleFileList(photoSelectResult.photoUris); + Log.d(TAG, + 'PhotoViewPicker.select successfully, photoSelectResult uri: ' + JSON.stringify(photoSelectResult)); + }).catch((err: BusinessError) => { + event.result.handleFileList([]); + Log.e(TAG, 'PhotoViewPicker.select failed with err: ' + JSON.stringify(err)); + }); + } + }, + { + title: '档案', + action: () => { + let documentPicker = new picker.DocumentViewPicker(); + let documentSelectOptions = new picker.DocumentSelectOptions(); + documentSelectOptions.maxSelectNumber = allowMultiple ? 100000 : 1 + documentSelectOptions.fileSuffixFilters = acceptTypes; + documentPicker.select(documentSelectOptions).then((documentSelectResult) => { + Log.d(TAG, + 'documentViewPicker.select to file succeed and uri is:' + JSON.stringify(documentSelectResult)); + event.result.handleFileList(documentSelectResult); + }).catch((err: BusinessError) => { + event.result.handleFileList([]); + Log.d(TAG, `Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`); + }) + } + }, + { + title: '音频', + action: () => { + let audioSelectOptions = new picker.AudioSelectOptions(); + let audioPicker = new picker.AudioViewPicker(); + audioPicker.select(audioSelectOptions).then((audioSelectResult: Array) => { + event.result.handleFileList(audioSelectResult); + Log.d(TAG, + 'AudioViewPicker.select successfully, audioSelectResult uri: ' + JSON.stringify(audioSelectResult)); + }).catch((err: BusinessError) => { + Log.d(TAG, 'AudioViewPicker.select failed with err: ' + JSON.stringify(err)); + event.result.handleFileList([]); + }); + } + } + ] + }) + return true; + } + onResourceLoad = (event: Any) => { + // TODO 没有找到安卓对于方法 + Log.d(TAG, "onResourceLoad=" + JSON.stringify(event)) + } + onScaleChange = (event: Any) => { + Log.d(TAG, "onScaleChange=" + JSON.stringify(event)) + this.inAppWebView.zoomScale = event.newScale / Util.getPixelDensity(); + + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onZoomScaleChanged(event.oldScale, event.newScale); + } + } + onInterceptRequest = (event: Any) => { //对应安卓shouldInterceptRequest + let request = WebResourceRequestExt.fromWebResourceRequest(event.request); + Log.d(TAG, "onInterceptRequest=" + JSON.stringify(event)) + if (this.inAppWebView.webViewAssetLoaderExt != null && this.inAppWebView.webViewAssetLoaderExt.loader != null) { + try { + let url = new uri.URI(request.getUrl()); + let webResourceResponse = this.inAppWebView.webViewAssetLoaderExt.loader.shouldInterceptRequest(url); + if (webResourceResponse != null) { + return webResourceResponse; + } + } catch (e) { + Log.e(TAG, "", e); + } + } + if (this.inAppWebView.customSettings.useShouldInterceptRequest) { + if (this.inAppWebView.channelDelegate != null) { + let webResourceResponse = new WebResourceResponse(); + try { + this.inAppWebView.channelDelegate.shouldInterceptRequest(request).then(response => { + if (response != null) { + webResourceResponse.setResponseData(response.getData()) + webResourceResponse.setResponseMimeType(response.getContentType()) + webResourceResponse.setResponseEncoding(response.getContentEncoding()) + webResourceResponse.setResponseCode(response.getStatusCode()) + webResourceResponse.setReasonMessage(response.getReasonPhrase()) + webResourceResponse.setResponseHeader(response.getHeaderArray()) + webResourceResponse.setResponseIsReady(true) + } else { + webResourceResponse.setResponseIsReady(false); + } + }) + } catch (e) { + Log.e(TAG, "", e); + webResourceResponse.setResponseIsReady(false); + } + return webResourceResponse; + } + return null; + } + + let url: string = request.getUrl(); + let scheme = url.split(":")[0].toLowerCase(); + try { + scheme = new uri.URI(url).scheme; + } catch (e) { + + } + + if (this.inAppWebView.customSettings.resourceCustomSchemes != null && + this.inAppWebView.customSettings.resourceCustomSchemes.indexOf(scheme) > -1) { + if (this.inAppWebView.channelDelegate != null) { + let resourceResponse = new WebResourceResponse(); + try { + this.inAppWebView.channelDelegate.onLoadResourceWithCustomScheme(request).then(customSchemeResponse => { + if (customSchemeResponse != null) { + try { + response = this.inAppWebView.contentBlockerHandler.checkUrl(this.inAppWebView, request, + customSchemeResponse.getContentType()); + } catch (e) { + Log.e(TAG, "", e); + } + if (response != null) { + resourceResponse.setResponseData(response.getResponseData()) + resourceResponse.setResponseMimeType(response.getResponseMimeType()) + resourceResponse.setResponseEncoding(response.getResponseEncoding()) + resourceResponse.setResponseCode(response.getResponseCode()) + resourceResponse.setReasonMessage(response.getReasonMessage()) + resourceResponse.setResponseHeader(response.getResponseHeader()) + resourceResponse.setResponseIsReady(true) + } else { + resourceResponse.setResponseMimeType(customSchemeResponse.getContentType()); + resourceResponse.setResponseEncoding(customSchemeResponse.getContentEncoding()); + resourceResponse.setResponseData(customSchemeResponse.getData()) + } + } else { + resourceResponse.setResponseIsReady(false) + } + }); + } catch (e) { + Log.e(TAG, "", e); + resourceResponse.setResponseIsReady(false) + } + return resourceResponse; + } + } + + let response: WebResourceResponse | null = null; + if (this.inAppWebView.contentBlockerHandler.getRuleList().length > 0) { + try { + response = this.inAppWebView.contentBlockerHandler.checkUrl(this.inAppWebView, request); + } catch (e) { + Log.e(TAG, "", e); + } + } + Log.d(TAG, "onInterceptRequestend= end") + return response; + } + onHttpAuthRequest = (event: Any) => { + Log.d(TAG, "onHttpAuthRequest=" + JSON.stringify(event)) + this.onReceivedHttpAuthRequest(event.handler, event.host, event.realm) + return true; + } + onSslErrorEventReceive = (event: Any) => { + Log.d(TAG, "onSslErrorEventReceive=" + JSON.stringify(event)) + this.onReceivedSslErrorEventReceive(event.handler, event.error) + } + onClientAuthenticationRequest = (event: Any) => { + Log.d(TAG, "onClientAuthenticationRequest=" + JSON.stringify(event)) + this.onReceivedClientAuthenticationRequest(event.handler, event.host, event.port, event.keyTypes, event.issuers) + } + onPermissionRequest = (event: Any) => { + if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onPermissionRequest(event.request.getOrigin(), + event.request.getAccessibleResource(), null, + new InnerPermissionRequestCallback(event.request)); + } else { + event.request.deny(); + } + Log.d(TAG, "onPermissionRequest=" + JSON.stringify(event)) + } + onContextMenuShow = (event: Any) => { + // TODO + Log.d(TAG, "onContextMenuShow=" + JSON.stringify(event)) + return true; + } + onContextMenuHide = () => { + // TODO + Log.d(TAG, "onContextMenuHide=") + } + onScroll = (event: Any) => { + Log.d(TAG, "onScroll=" + JSON.stringify(event)) + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onScrollChanged(event.xOffset, + event.yOffset); + } + } + onGeolocationShow = (event: Any) => { + Log.d(TAG, "onGeolocationShow=" + JSON.stringify(event)) + if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onGeolocationPermissionsShowPrompt(event.origin, + new InnerGeolocationPermissionsShowPromptCallback(event.origin, event.geolocation)); + } else { + event.geolocation.invoke(event.origin, false, false); + } + } + onGeolocationHide = () => { + Log.d(TAG, "onGeolocationHide=") + if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onGeolocationPermissionsHidePrompt(); + } + } + onFullScreenEnter = (event: Any) => { + let context = this.inAppWebView.context as common.UIAbilityContext; + let windowClass = context.windowStage.getMainWindowSync(); + let windowProperties = windowClass.getWindowProperties(); + this.isOriginalLayoutFullScreen = windowProperties.isLayoutFullScreen; + this.isOriginalFullScreen = windowProperties.isFullScreen; + windowClass.setWindowLayoutFullScreen(true) + windowClass.setWindowSystemBarEnable([]) + this.fullScreenExitHandler = event.handler + Log.d(TAG, "onFullScreenEnter=" + JSON.stringify(event)) + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onEnterFullscreen(); + } + this.inAppWebView.setInFullscreen(true); + } + onFullScreenExit = () => { + Log.d(TAG, "onFullScreenExit=") + let context = this.inAppWebView.context as common.UIAbilityContext; + let windowClass = context.windowStage.getMainWindowSync(); + windowClass.setWindowLayoutFullScreen(this.isOriginalLayoutFullScreen) + windowClass.setWindowSystemBarEnable(this.isOriginalFullScreen ? [] : ['status', 'navigation']) + if (this.fullScreenExitHandler) { + this.fullScreenExitHandler.exitFullScreen() + } + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onExitFullscreen(); + } + this.inAppWebView.setInFullscreen(false); + } + onWindowNew = (event: Any) => { + Log.d(TAG, "onWindowNew=" + JSON.stringify(event)) + let windowId = 0; + if (this.plugin != null && this.plugin.inAppWebViewManager != null) { + this.plugin.inAppWebViewManager.windowAutoincrementId++; + windowId = this.plugin.inAppWebViewManager.windowAutoincrementId; + } + + let request = new URLRequest(event.targetUrl, "GET", null, new Map()); + let createWindowAction = new CreateWindowAction(request, true, event.isUserTrigger, false, windowId, event.isAlert); + if (this.plugin != null && this.plugin.inAppWebViewManager != null) { + this.plugin.inAppWebViewManager.windowWebViewMessages.set(windowId, event.handler); + } + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onCreateWindow(createWindowAction, + new InnerCreateWindowCallback(this.inAppWebView, windowId)); + } + } + onWindowExit = () => { + Log.d(TAG, "onWindowExit=") + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onCloseWindow(); + } + } + onSearchResultReceive = (event: Any) => { + Log.d(TAG, "onSearchResultReceive=" + JSON.stringify(event)) + // TODO + } + onDataResubmitted = (event: Any) => { + Log.d(TAG, "onDataResubmitted=" + JSON.stringify(event)) + let callback = new InnerFormResubmissionCallback(event.handler); + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onFormResubmission(this.inAppWebView!.controller!.getUrl(), callback); + } else { + callback.defaultBehaviour(null); + } + } + onPageVisible = (event: Any) => { + Log.d(TAG, "onPageVisible=" + JSON.stringify(event)) + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onPageCommitVisible(event.url); + } + } + onInterceptKeyEvent = (event: Any) => { + Log.d(TAG, "onInterceptKeyEvent=" + JSON.stringify(event)) + // TODO + return false; + } + onTouchIconUrlReceived = (event: Any) => { + Log.d(TAG, "onTouchIconUrlReceived=" + JSON.stringify(event)) + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onReceivedTouchIconUrl(event.url, event.precomposed); + } + } + onFaviconReceived = async (event: Any) => { + Log.d(TAG, "onFaviconReceived=" + JSON.stringify(event)) + let options: image.PackingOption = { + format: 'image/png', + quality: 100 + }; + let packer = image.createImagePacker(); + let imageBuffer = await packer.packing(event.favicon, options); + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onReceivedIcon(imageBuffer); + } + await event.favicon.release() + await packer.release() + } + onAudioStateChanged = (event: Any) => { + Log.d(TAG, "onAudioStateChanged=" + JSON.stringify(event)) + // TODO + } + onFirstContentfulPaint = (event: Any) => { + Log.d(TAG, "onFirstContentfulPaint=" + JSON.stringify(event)) + // TODO + } + onLoadIntercept = (event: Any) : boolean => { + Log.d(TAG, "onLoadIntercept=" + event.data.getRequestUrl()) + // TODO + return false; + } + onOverrideUrlLoading = (request: WebResourceRequest) : boolean => { + Log.d(TAG, "onOverrideUrlLoading=" + request.getRequestUrl()) + if (this.inAppWebView.customSettings.useShouldOverrideUrlLoading) { + let headers = new Map() + request.getRequestHeader().forEach(header => headers.set(header.headerKey, header.headerValue)); + + this.onShouldOverrideUrlLoading( + this.inAppWebView, + request.getRequestUrl(), + request.getRequestMethod(), + headers, + request.isMainFrame(), + request.isRequestGesture(), + request.isRedirect()); + + if (this.inAppWebView.regexToCancelSubFramesLoadingCompiled != null) { + if (request.isMainFrame()) + return true + else { + return this.inAppWebView.regexToCancelSubFramesLoadingCompiled!.test(request.getRequestUrl()); + } + } else { + // There isn't any way to load an URL for a frame that is not the main frame, + // so if the request is not for the main frame, the navigation is allowed. + return request.isMainFrame(); + } + } + return false; + } + onRequestSelected = () => { + Log.d(TAG, "onRequestSelected=") + if(this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onRequestFocus(); + } + } + onScreenCaptureRequest = (event: Any) => { + Log.d(TAG, "onScreenCaptureRequest=" + JSON.stringify(event)) + // TODO + } + onOverScroll = (event: Any) => { + // TODO 没有clampedX clampedY? + Log.d(TAG, "onOverScroll=" + JSON.stringify(event)) + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.canScrollHorizontally({ + onReceiveValue(canScroll: boolean | null): void { + let overScrolledHorizontally: boolean = canScroll!; + let overScrolledVertically: boolean = this.inAppWebView.canScrollVertically(); + this.inAppWebView.channelDelegate.onOverScrolled(event.xOffset, event.yOffset, overScrolledHorizontally, overScrolledVertically); + } + }); + } + } + onNavigationEntryCommitted = () => { + Log.d(TAG, "onNavigationEntryCommitted=") + // TODO + } + onSafeBrowsingCheckResult = (threatType: ThreatType) => { + Log.d(TAG, "onSafeBrowsingCheckResult=") + let resultCallback = new InnerSafeBrowsingHitCallback(); + if (this.inAppWebView.channelDelegate != null) { + let url = this.inAppWebView!.controller!.getUrl(); + this.inAppWebView.channelDelegate.onSafeBrowsingHit(url, threatType, resultCallback); + } else { + resultCallback.defaultBehaviour(null); + } + } + onNativeEmbedLifecycleChange = (callback: NativeEmbedDataInfo) => { + Log.d(TAG, "onNativeEmbedLifecycleChange=") + // TODO + } + onNativeEmbedGestureEvent = (callback: NativeEmbedTouchInfo) => { + Log.d(TAG, "onNativeEmbedGestureEvent=") + // TODO + } + onRenderProcessNotResponding = (data: RenderProcessNotRespondingData) => { + let callback = new InnerRenderProcessUnresponsiveCallback(this.inAppWebView) + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onRenderProcessUnresponsive(this.inAppWebView.getUrl(), callback); + } else { + callback.defaultBehaviour(null); + } + } + onRenderProcessResponding = () => { + let callback = new InnerRenderProcessResponsiveCallback(this.inAppWebView) + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onRenderProcessResponsive(this.inAppWebView.getUrl(), callback); + } else { + callback.defaultBehaviour(null); + } + } + + private onShouldOverrideUrlLoading(webView: InAppWebView, url: string, method: string, + headers: Map, + isForMainFrame: boolean, hasGesture: boolean, isRedirect: boolean) { + let request = new URLRequest(url, method, null, headers); + let navigationAction = new NavigationAction(request, isForMainFrame, hasGesture, isRedirect); + + let callback = new InnerShouldOverrideUrlLoadingCallback(this.inAppWebView, url, headers, isForMainFrame) + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.shouldOverrideUrlLoading(navigationAction, callback); + } else { + callback.defaultBehaviour(null); + } + } + + private async onReceivedHttpAuthRequest(handler: HttpAuthHandler, host: string, realm: string) { + let url = this.inAppWebView!.controller!.getUrl(); + let protocol = "https"; + let port = 0; + + if (url != null) { + try { + let uriurl = new uri.URI(url); + protocol = uriurl.scheme; + port = Number.parseInt(uriurl.port); + } catch (e) { + Log.e(TAG, "", e); + } + } + + InAppWebViewClient.previousAuthRequestFailureCount++; + + if (InAppWebViewClient.credentialsProposed == null) { + InAppWebViewClient.credentialsProposed = await CredentialDatabase.getInstance(this.inAppWebView.context) + .getHttpAuthCredentials(host, protocol, realm, port); + } + + let credentialProposed: URLCredential | null = null; + if (InAppWebViewClient.credentialsProposed != null && + InAppWebViewClient.credentialsProposed.length > 0) { + credentialProposed = InAppWebViewClient.credentialsProposed.get(0); + } + + let certificate: cert.X509Cert | null = null; + let certificates = await this.inAppWebView!.controller!.getCertificate(); + if (certificates && certificates.length > 0) { + certificate = certificates[0]; + } + let protectionSpace = new URLProtectionSpace(host, protocol, realm, port, null, certificate, null); + let challenge = + new HttpAuthenticationChallenge(protectionSpace, InAppWebViewClient.previousAuthRequestFailureCount, + credentialProposed); + + let callback = new InnerReceivedHttpAuthRequestCallback(this.inAppWebView, handler, host, protocol, realm, port); + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onReceivedHttpAuthRequest(challenge, callback); + } else { + callback.defaultBehaviour(null); + } + } + + private onReceivedSslErrorEventReceive(handler: SslErrorHandler, sslError: SslError) { + let url = this.inAppWebView!.controller!.getUrl(); + let host = ""; + let protocol = "https"; + let port = 0; + + try { + let uriurl = new uri.URI(url); + host = uriurl.host; + protocol = uriurl.scheme; + port = Number.parseInt(uriurl.port); + } catch (e) { + Log.e(TAG, "", e); + } + + // TODO sslError.getCertificate()没有这方法 用null先适配 + let protectionSpace = new URLProtectionSpace(host, protocol, null, port, null, null, sslError); + let challenge = new ServerTrustChallenge(protectionSpace); + let callback = new InnerReceivedServerTrustAuthRequestCallback(handler); + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onReceivedServerTrustAuthRequest(challenge, callback); + } else { + callback.defaultBehaviour(null); + } + } + + private async onReceivedClientAuthenticationRequest(handler: ClientAuthenticationHandler, host: string, + port: number, keyTypes: Array, issuers: Array) { + let url = this.inAppWebView!.controller!.getUrl(); + let protocol = "https"; + + if (url != null) { + try { + let uriurl = new uri.URI(url); + protocol = uriurl.scheme; + } catch (e) { + Log.e(TAG, "", e); + } + } + + let certificate: cert.X509Cert | null = null; + let certificates = await this.inAppWebView!.controller!.getCertificate(); + if (certificates && certificates.length > 0) { + certificate = certificates[0]; + } + let protectionSpace = new URLProtectionSpace(host, protocol, null, port, null, certificate, null); + let challenge = new ClientCertChallenge(protectionSpace, issuers, keyTypes); + + let callback = new InnerReceivedClientCertRequestCallback(this.inAppWebView!, handler); + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onReceivedClientCertRequest(challenge, callback); + } else { + callback.defaultBehaviour(null); + } + } + + private loadCustomJavaScriptOnPageStarted(webView: InAppWebView) { + let source = webView.userContentController.generateWrappedCodeForDocumentStart(); + webView.controller.runJavaScriptExt(source) + } + + private loadCustomJavaScriptOnPageFinished(webView: InAppWebView) { + let source = webView.userContentController.generateWrappedCodeForDocumentEnd(); + webView.controller.runJavaScriptExt(source) + } + + private needsCameraPermission(): boolean { + return false + } + + private acceptsVideo(types: Array): boolean { + let mimeTypes = this.getAcceptedMimeType(types); + return this.acceptsAny(mimeTypes) || this.arrayContainsString(mimeTypes, "video"); + } + + private acceptsImages(types: Array): boolean { + let mimeTypes = this.getAcceptedMimeType(types); + return this.acceptsAny(mimeTypes) || this.arrayContainsString(mimeTypes, "image"); + } + + private getAcceptedMimeType(types: Array): Array { + if (this.isArrayEmpty(types)) { + return ["*/*"]; + } + let mimeTypes = new Array(); + for (let i = 0; i < types.length; i++) { + let t = types[i]; + // convert file extensions to mime types + if (t.indexOf(".") > -1) { + let mimeType = MimeTypes.getMimeTypeFromExtension(t.replace(".", "")); + mimeTypes[i] = mimeType; + } else { + mimeTypes[i] = t; + } + } + return mimeTypes; + } + + private acceptsAny(types: Array) { + if (this.isArrayEmpty(types)) { + return true; + } + for (let type of types) { + if (type == "*/*") { + return true; + } + } + return false; + } + + private arrayContainsString(array: Array, pattern: string): boolean { + for (let content of array) { + if (content != null && content.indexOf(pattern) > -1) { + return true; + } + } + return false; + } + + private isArrayEmpty(arr: Array): boolean { + // when our array returned from getAcceptTypes() has no values set from the webview + // i.e. , without any "accept" attr + // will be an array with one empty string element, afaik + return arr.length == 0 || (arr.length == 1 && arr[0].length == 0); + } +} + +class InnerJsAlertCallback extends JsAlertCallback { + private result: JsResult; + private message: string; + + constructor(result: JsResult, message: string) { + super(); + this.result = result; + this.message = message; + } + + nonNullSuccess(response: JsAlertResponse): boolean { + if (response.isHandledByClient()) { + let action = response.getAction(); + action = action != null ? action : 1; + switch (action) { + case 0: + this.result.handleConfirm(); + break; + case 1: + default: + this.result.handleCancel(); + } + return false; + } + return true; + } + + defaultBehaviour(response: JsAlertResponse | null): void { + let responseMessage: string | null = null; + let confirmButtonTitle: string | null = null; + if (response != null) { + responseMessage = response.getMessage(); + confirmButtonTitle = response.getConfirmButtonTitle(); + } + this.createAlertDialog(this.message, this.result, responseMessage, confirmButtonTitle); + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.result.handleCancel(); + } + + private createAlertDialog(message: string, result: JsResult, responseMessage: string | null, + confirmButtonTitle: string | null) { + let alertMessage = (responseMessage != null && responseMessage.length > 0) ? responseMessage : message; + AlertDialog.show( + { + message: alertMessage, + autoCancel: true, + alignment: DialogAlignment.Center, + confirm: { + value: confirmButtonTitle != null ? confirmButtonTitle : "确定", + action: () => { + result.handleConfirm() + } + }, + cancel: () => { + result.handleCancel() + } + } + ) + } +} + +class InnerJsConfirmCallback extends JsConfirmCallback { + private result: JsResult; + private message: string; + + constructor(result: JsResult, message: string) { + super(); + this.result = result; + this.message = message; + } + + nonNullSuccess(response: JsConfirmResponse): boolean { + if (response.isHandledByClient()) { + let action = response.getAction(); + action = action != null ? action : 1; + switch (action) { + case 0: + this.result.handleConfirm(); + break; + case 1: + default: + this.result.handleCancel(); + } + return false; + } + return true; + } + + defaultBehaviour(response: JsConfirmResponse | null): void { + let responseMessage: string | null = null; + let confirmButtonTitle: string | null = null; + let cancelButtonTitle: string | null = null; + if (response != null) { + responseMessage = response.getMessage(); + confirmButtonTitle = response.getConfirmButtonTitle(); + cancelButtonTitle = response.getCancelButtonTitle(); + } + this.createConfirmDialog(this.message, this.result, responseMessage, confirmButtonTitle, cancelButtonTitle); + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.result.handleCancel(); + } + + private createConfirmDialog(message: string, result: JsResult, responseMessage: string | null, + confirmButtonTitle: string | null, cancelButtonTitle: string | null) { + let alertMessage = (responseMessage != null && responseMessage.length > 0) ? responseMessage : message; + AlertDialog.show( + { + message: alertMessage, + autoCancel: true, + alignment: DialogAlignment.Center, + primaryButton: { + value: cancelButtonTitle != null ? cancelButtonTitle : "取消", + action: () => { + result.handleCancel() + } + }, + secondaryButton: { + defaultFocus: true, + value: confirmButtonTitle != null ? confirmButtonTitle : "确定", + action: () => { + result.handleConfirm() + } + }, + cancel: () => { + result.handleCancel() + } + } + ) + } +} + +class InnerJsPromptCallback extends JsPromptCallback { + private result: JsResult; + private message: string; + private defaultValue: string; + private uiObject: Any; + + constructor(result: JsResult, message: string, defaultValue: string, uiObject: Any) { + super(); + this.result = result; + this.message = message; + this.defaultValue = defaultValue; + this.uiObject = uiObject; + } + + nonNullSuccess(response: JsPromptResponse): boolean { + if (response.isHandledByClient()) { + let action = response.getAction(); + action = action != null ? action : 1; + switch (action) { + case 0: + this.result.handlePromptConfirm(response.getValue()); + break; + case 1: + default: + this.result.handleCancel(); + } + return false; + } + return true; + } + + defaultBehaviour(response: JsPromptResponse | null): void { + let responseMessage: string | null = null; + let responseDefaultValue: string | null = null; + let value: string | null = null; + let confirmButtonTitle: string | null = null; + let cancelButtonTitle: string | null = null; + if (response != null) { + responseMessage = response.getMessage(); + responseDefaultValue = response.getDefaultValue(); + value = response.getValue(); + confirmButtonTitle = response.getConfirmButtonTitle(); + cancelButtonTitle = response.getCancelButtonTitle(); + } + this.createPromptDialog(this.message, this.defaultValue, this.result, responseMessage, responseDefaultValue, value, + cancelButtonTitle, confirmButtonTitle); + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.result.handleCancel(); + } + + private createPromptDialog(message: string, defaultValue: string, result: JsResult, responseMessage: string | null, + responseDefaultValue: string | null, value: string | null, cancelButtonTitle: string | null, + confirmButtonTitle: string | null) { + let initValue = + (responseDefaultValue != null && responseDefaultValue.length > 0) ? responseDefaultValue : defaultValue; + let alertMessage = (responseMessage != null && responseMessage.length > 0) ? responseMessage : message; + let finalValue = value; + let customDialogId = -1; + let isCancel = true; + promptAction.openCustomDialog({ + builder: ohosPromptDialogBuilder.bind(this.uiObject, initValue, alertMessage, cancelButtonTitle, + confirmButtonTitle, () => { + isCancel = false + result.handleCancel() + promptAction.closeCustomDialog(customDialogId) + }, (value: string | null) => { + isCancel = false + promptAction.closeCustomDialog(customDialogId) + result.handlePromptConfirm(finalValue != null ? finalValue : value); + }), + alignment: DialogAlignment.Center, + onDidDisappear: () => { + if (isCancel) { + result.handleCancel() + } + } + }).then((dialogId: number) => { + customDialogId = dialogId + }) + } +} + +class InnerJsBeforeUnloadCallback extends JsBeforeUnloadCallback { + private result: JsResult; + private message: string; + + constructor(result: JsResult, message: string) { + super(); + this.result = result; + this.message = message; + } + + nonNullSuccess(response: JsBeforeUnloadResponse): boolean { + if (response.isHandledByClient()) { + let action = response.getAction(); + action = action != null ? action : 1; + switch (action) { + case 0: + this.result.handleConfirm(); + break; + case 1: + default: + this.result.handleCancel(); + } + return false; + } + return true; + } + + defaultBehaviour(response: JsBeforeUnloadResponse | null): void { + let responseMessage: string | null = null; + let confirmButtonTitle: string | null = null; + let cancelButtonTitle: string | null = null; + if (response != null) { + responseMessage = response.getMessage(); + confirmButtonTitle = response.getConfirmButtonTitle(); + cancelButtonTitle = response.getCancelButtonTitle(); + } + this.createBeforeUnloadDialog(this.message, this.result, responseMessage, confirmButtonTitle, cancelButtonTitle); + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.result.handleCancel(); + } + + private createBeforeUnloadDialog(message: string, result: JsResult, responseMessage: string | null, + confirmButtonTitle: string | null, cancelButtonTitle: string | null) { + let alertMessage = (responseMessage != null && responseMessage.length > 0) ? responseMessage : message; + AlertDialog.show( + { + message: alertMessage, + autoCancel: true, + alignment: DialogAlignment.Center, + primaryButton: { + value: cancelButtonTitle != null ? cancelButtonTitle : "取消", + action: () => { + result.handleCancel() + } + }, + secondaryButton: { + defaultFocus: true, + value: confirmButtonTitle != null ? confirmButtonTitle : "确定", + action: () => { + result.handleConfirm() + } + }, + cancel: () => { + result.handleCancel() + } + } + ) + } +} + +class InnerPermissionRequestCallback extends PermissionRequestCallback { + private request: PermissionRequest; + + constructor(request: PermissionRequest) { + super(); + this.request = request; + } + + nonNullSuccess(response: PermissionResponse): boolean { + let action = response.getAction(); + if (action != null) { + switch (action) { + case 1: + this.request.grant(response.getResources().convertToArray()); + break; + case 0: + default: + this.request.deny(); + } + return false; + } + return true; + } + + defaultBehaviour(response: PermissionResponse | null): void { + this.request.deny(); + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +} + +class InnerGeolocationPermissionsShowPromptCallback extends GeolocationPermissionsShowPromptCallback { + private geolocation: JsGeolocation; + private origin: string; + + constructor(origin: string, geolocation: JsGeolocation) { + super(); + this.geolocation = geolocation; + this.origin = origin; + } + + nonNullSuccess(response: GeolocationPermissionShowPromptResponse): boolean { + this.geolocation.invoke(response.getOrigin(), response.isAllow(), response.isRetain()); + return false; + } + + defaultBehaviour(response: GeolocationPermissionShowPromptResponse | null): void { + this.geolocation.invoke(this.origin, false, false); + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +} + +class InnerReceivedHttpAuthRequestCallback extends ReceivedHttpAuthRequestCallback { + private handler: HttpAuthHandler; + private host: string; + private finalProtocol: string; + private realm: string; + private finalPort: number; + private inAppWebView: InAppWebView; + + constructor(inAppWebView: InAppWebView, handler: HttpAuthHandler, host: string, protocol: string, realm: string, + port: number) { + super(); + this.handler = handler; + this.host = host; + this.finalProtocol = protocol; + this.realm = realm; + this.finalPort = port; + this.inAppWebView = inAppWebView; + } + + nonNullSuccess(response: HttpAuthResponse): boolean { + let action = response.getAction(); + if (action != null) { + switch (action) { + case 1: + let username = response.getUsername(); + let password = response.getPassword(); + let permanentPersistence = response.isPermanentPersistence(); + if (permanentPersistence) { + CredentialDatabase.getInstance(this.inAppWebView.context) + .setHttpAuthCredential(this.host, this.finalProtocol, this.realm, this.finalPort, username, password); + } + this.handler.confirm(username, password); + break; + case 2: + if (InAppWebViewClient.credentialsProposed!.length > 0) { + let credential = InAppWebViewClient.credentialsProposed!.removeByIndex(0); + this.handler.confirm(credential.getUsername(), credential.getPassword()); + } else { + this.handler.cancel(); + } + // used custom CredentialDatabase! + // handler.useHttpAuthUsernamePassword(); + break; + case 0: + default: + InAppWebViewClient.credentialsProposed = null; + InAppWebViewClient.previousAuthRequestFailureCount = 0; + this.handler.cancel(); + } + return false; + } + return true; + } + + defaultBehaviour(result: HttpAuthResponse | null): void { + if (result == null) { + this.handler.cancel(); + } else { + this.nonNullSuccess(result) + } + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +} + +class InnerReceivedServerTrustAuthRequestCallback extends ReceivedServerTrustAuthRequestCallback { + private handler: SslErrorHandler; + + constructor(handler: SslErrorHandler) { + super(); + this.handler = handler; + } + + nonNullSuccess(response: ServerTrustAuthResponse): boolean { + let action = response.getAction(); + if (action != null) { + switch (action) { + case 1: + this.handler.handleConfirm(); + break; + case 0: + default: + this.handler.handleCancel(); + } + return false; + } + return true; + } + + defaultBehaviour(result: ServerTrustAuthResponse | null) { + if (result != null) { + this.nonNullSuccess(result); + } else { + this.handler.handleCancel(); + } + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +} + +class InnerReceivedClientCertRequestCallback extends ReceivedClientCertRequestCallback { + private handler: ClientAuthenticationHandler; + private inAppWebView: InAppWebView; + + constructor(inAppWebView: InAppWebView, handler: ClientAuthenticationHandler) { + super(); + this.inAppWebView = inAppWebView; + this.handler = handler; + } + + nonNullSuccess(response: ClientCertResponse): boolean { + let action = response.getAction(); + if (action != null && this.inAppWebView.plugin != null) { + switch (action) { + case 1: { + let certificatePath = response.getCertificatePath(); + let certificatePassword = response.getCertificatePassword(); + let keyStoreType = response.getKeyStoreType(); + //TODO priKeyFile? + this.handler.confirm(keyStoreType, certificatePath) + } + break; + case 2: + this.handler.ignore(); + break; + case 0: + default: + this.handler.cancel(); + } + return false; + } + return true; + } + + defaultBehaviour(result: ClientCertResponse | null) { + if (result != null) { + this.nonNullSuccess(result); + } else { + this.handler.cancel(); + } + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +} + +class InnerCreateWindowCallback extends CreateWindowCallback { + private finalWindowId: number; + private inAppWebView: InAppWebView; + + constructor(inAppWebView: InAppWebView, finalWindowId: number) { + super(); + this.inAppWebView = inAppWebView; + this.finalWindowId = finalWindowId; + } + + nonNullSuccess(handledByClient: boolean): boolean { + return !handledByClient; + } + + defaultBehaviour(handledByClient: boolean | null) { + if (this.inAppWebView.plugin != null && this.inAppWebView.plugin.inAppWebViewManager != null) { + this.inAppWebView.plugin.inAppWebViewManager.windowWebViewMessages.delete(this.finalWindowId); + } + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +} + +class InnerFormResubmissionCallback extends FormResubmissionCallback { + private hanlder: DataResubmissionHandler; + + constructor(hanlder: DataResubmissionHandler) { + super(); + this.hanlder = hanlder; + } + + nonNullSuccess(action: number): boolean { + switch (action) { + case 0: + this.hanlder.resend(); + break; + case 1: + default: + this.hanlder.cancel(); + } + return false; + } + + defaultBehaviour(result: number | null) { + if (result != null) { + this.nonNullSuccess(result); + } else { + this.hanlder.cancel(); + } + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +}; + +class InnerShouldOverrideUrlLoadingCallback extends ShouldOverrideUrlLoadingCallback { + + private inAppWebView: InAppWebView; + private url: string; + private headers: Map; + private isForMainFrame: boolean; + + constructor(inAppWebView: InAppWebView, url: string, headers: Map, isForMainFrame: boolean) { + super(); + this.inAppWebView = inAppWebView; + this.url = url; + this.headers = headers; + this.isForMainFrame = isForMainFrame; + } + + nonNullSuccess(result: NavigationActionPolicy) : boolean { + switch (result) { + case NavigationActionPolicy.ALLOW: + this.allowShouldOverrideUrlLoading(this.inAppWebView, this.url, this.headers, this.isForMainFrame); + break; + case NavigationActionPolicy.CANCEL: + default: + break; + } + return false; + } + + defaultBehaviour(result: NavigationActionPolicy | null) { + this.allowShouldOverrideUrlLoading(this.inAppWebView, this.url, this.headers, this.isForMainFrame); + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } + + allowShouldOverrideUrlLoading(inAppWebView: InAppWebView, url: string, headers: Map, + isForMainFrame: boolean) { + if (isForMainFrame) { + this.inAppWebView.controller.loadUrl(url, this.inAppWebView.toWebHeaders(headers)); + } + } +}; + +class InnerSafeBrowsingHitCallback extends SafeBrowsingHitCallback { + public nonNullSuccess(response: SafeBrowsingResponse): boolean { + let action = response.getAction(); + if (action != null) { + let report = response.isReport(); + switch (action) { + case 0: // TODO android backToSafety + return true; + break; + case 1: // TODO android proceed + return true; + break; + case 2: + default: //TODO android showInterstitial + return true; + } + return false; + } + return true; + } + + defaultBehaviour(result: SafeBrowsingResponse | null) { + if (result != null) { + this.nonNullSuccess(result) + } + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +} + +class InnerRenderProcessUnresponsiveCallback extends RenderProcessUnresponsiveCallback { + private inAppWebView: InAppWebView; + + constructor(inAppWebView: InAppWebView) { + super(); + this.inAppWebView = inAppWebView; + } + + public nonNullSuccess(action: number): boolean { + switch (action) { + case 0: + this.inAppWebView.controller.terminateRenderProcess(); + break; + } + return false; + } + + defaultBehaviour(result: number | null) { + + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +} + +class InnerRenderProcessResponsiveCallback extends RenderProcessResponsiveCallback { + private inAppWebView: InAppWebView; + + constructor(inAppWebView: InAppWebView) { + super(); + this.inAppWebView = inAppWebView; + } + + public nonNullSuccess(action: number): boolean { + switch (action) { + case 0: + this.inAppWebView.controller.terminateRenderProcess(); + break; + } + return false; + } + + defaultBehaviour(result: number | null) { + + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewClientCompat.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewClientCompat.ets deleted file mode 100644 index 99559e2ab482f393f77a17ca9f9f317b73145557..0000000000000000000000000000000000000000 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewClientCompat.ets +++ /dev/null @@ -1,18 +0,0 @@ -/* -* Copyright (c) 2024 Hunan OpenValley Digital Industry Development 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. -*/ - -export class InAppWebViewClientCompat{// extends WebViewClientCompat - -} \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewSettings.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewSettings.ets index ed0468cf002f9aea0da7b749bb965ccef1ac73f7..003bc328bcf2978f7c8a5d65851593e470749775 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewSettings.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewSettings.ets @@ -73,6 +73,8 @@ export default class InAppWebViewSettings implements ISettings): ISettings { let keys = settings.keys(); @@ -274,6 +276,12 @@ export default class InAppWebViewSettings implements ISettings = []; + @State cacheEnabled: boolean = true aboutToAppear(): void { this.isEnableRefresh = this.inAppWebView!.getPullToRefreshLayout().settings.enabled; + this.cacheEnabled = this.inAppWebView!.customSettings.cacheEnabled; this.startScripts = this.inAppWebView!.userContentController.getStartScripts() let context = getContext() as common.UIAbilityContext; context.eventHub.on(EventConstant.EVENT_PULL_SETREFRESHING, (refreshing : boolean) => { @@ -42,6 +44,10 @@ export struct OhosWebView { context.eventHub.on(EventConstant.EVENT_UPDATE_STARTSCRIPTS, (scripts : Array) => { this.startScripts = scripts; }); + + context.eventHub.on(EventConstant.EVENT_UPDATE_CACHEENABLE, (enable : boolean) => { + this.cacheEnabled = enable; + }); } aboutToDisappear(): void { @@ -76,58 +82,60 @@ export struct OhosWebView { controller: this.controller }) .onControllerAttached(this.inAppWebView!.onControllerAttached) - .onAlert(this.inAppWebView!.inAppWebViewChromeClient?.onAlert) - .onBeforeUnload(this.inAppWebView!.inAppWebViewChromeClient?.onBeforeUnload) - .onConfirm(this.inAppWebView!.inAppWebViewChromeClient?.onConfirm) + .onAlert(this.inAppWebView!.inAppWebViewClient?.onAlert) + .onBeforeUnload(this.inAppWebView!.inAppWebViewClient?.onBeforeUnload) + .onConfirm(this.inAppWebView!.inAppWebViewClient?.onConfirm) .onPrompt((event) => { - return this.inAppWebView!.inAppWebViewChromeClient?.onPrompt(event, this) + return this.inAppWebView!.inAppWebViewClient?.onPrompt(event, this) }) - .onConsole(this.inAppWebView!.inAppWebViewChromeClient?.onConsole) - .onDownloadStart(this.inAppWebView!.inAppWebViewChromeClient?.onDownloadStart) - .onErrorReceive(this.inAppWebView!.inAppWebViewChromeClient?.onErrorReceive) - .onHttpErrorReceive(this.inAppWebView!.inAppWebViewChromeClient?.onHttpErrorReceive) - .onPageBegin(this.inAppWebView!.inAppWebViewChromeClient?.onPageBegin) - .onPageEnd(this.inAppWebView!.inAppWebViewChromeClient?.onPageEnd) - .onProgressChange(this.inAppWebView!.inAppWebViewChromeClient?.onProgressChange) - .onTitleReceive(this.inAppWebView!.inAppWebViewChromeClient?.onTitleReceive) - .onRefreshAccessedHistory(this.inAppWebView!.inAppWebViewChromeClient?.onRefreshAccessedHistory) - .onRenderExited(this.inAppWebView!.inAppWebViewChromeClient?.onRenderExited) - .onShowFileSelector(this.inAppWebView!.inAppWebViewChromeClient?.onShowFileSelector) - .onResourceLoad(this.inAppWebView!.inAppWebViewChromeClient?.onResourceLoad) - .onScaleChange(this.inAppWebView!.inAppWebViewChromeClient?.onScaleChange) + .onConsole(this.inAppWebView!.inAppWebViewClient?.onConsole) + .onDownloadStart(this.inAppWebView!.inAppWebViewClient?.onDownloadStart) + .onErrorReceive(this.inAppWebView!.inAppWebViewClient?.onErrorReceive) + .onHttpErrorReceive(this.inAppWebView!.inAppWebViewClient?.onHttpErrorReceive) + .onPageBegin(this.inAppWebView!.inAppWebViewClient?.onPageBegin) + .onPageEnd(this.inAppWebView!.inAppWebViewClient?.onPageEnd) + .onProgressChange(this.inAppWebView!.inAppWebViewClient?.onProgressChange) + .onTitleReceive(this.inAppWebView!.inAppWebViewClient?.onTitleReceive) + .onRefreshAccessedHistory(this.inAppWebView!.inAppWebViewClient?.onRefreshAccessedHistory) + .onRenderExited(this.inAppWebView!.inAppWebViewClient?.onRenderExited) + .onShowFileSelector(this.inAppWebView!.inAppWebViewClient?.onShowFileSelector) + .onResourceLoad(this.inAppWebView!.inAppWebViewClient?.onResourceLoad) + .onScaleChange(this.inAppWebView!.inAppWebViewClient?.onScaleChange) .onInterceptRequest((event) => { - return this.inAppWebView!.inAppWebViewChromeClient?.onInterceptRequest(event) + return this.inAppWebView!.inAppWebViewClient?.onInterceptRequest(event) }) - .onHttpAuthRequest(this.inAppWebView!.inAppWebViewChromeClient?.onHttpAuthRequest) - .onSslErrorEventReceive(this.inAppWebView!.inAppWebViewChromeClient?.onSslErrorEventReceive) - .onClientAuthenticationRequest(this.inAppWebView!.inAppWebViewChromeClient?.onClientAuthenticationRequest) - .onPermissionRequest(this.inAppWebView!.inAppWebViewChromeClient?.onPermissionRequest) - .onContextMenuShow(this.inAppWebView!.inAppWebViewChromeClient?.onContextMenuShow) - .onContextMenuHide(this.inAppWebView!.inAppWebViewChromeClient?.onContextMenuHide) - .onScroll(this.inAppWebView!.inAppWebViewChromeClient?.onScroll) - .onGeolocationShow(this.inAppWebView!.inAppWebViewChromeClient?.onGeolocationShow) - .onGeolocationHide(this.inAppWebView!.inAppWebViewChromeClient?.onGeolocationHide) - .onFullScreenEnter(this.inAppWebView!.inAppWebViewChromeClient?.onFullScreenEnter) - .onFullScreenExit(this.inAppWebView!.inAppWebViewChromeClient?.onFullScreenExit) - .onWindowNew(this.inAppWebView!.inAppWebViewChromeClient?.onWindowNew) - .onWindowExit(this.inAppWebView!.inAppWebViewChromeClient?.onWindowExit) - .onSearchResultReceive(this.inAppWebView!.inAppWebViewChromeClient?.onSearchResultReceive) - .onDataResubmitted(this.inAppWebView!.inAppWebViewChromeClient?.onDataResubmitted) - .onPageVisible(this.inAppWebView!.inAppWebViewChromeClient?.onPageVisible) - .onInterceptKeyEvent(this.inAppWebView!.inAppWebViewChromeClient?.onInterceptKeyEvent) - .onTouchIconUrlReceived(this.inAppWebView!.inAppWebViewChromeClient?.onTouchIconUrlReceived) - .onFaviconReceived(this.inAppWebView!.inAppWebViewChromeClient?.onFaviconReceived) - .onAudioStateChanged(this.inAppWebView!.inAppWebViewChromeClient?.onAudioStateChanged) - .onFirstContentfulPaint(this.inAppWebView!.inAppWebViewChromeClient?.onFirstContentfulPaint) - .onLoadIntercept(this.inAppWebView!.inAppWebViewChromeClient?.onLoadIntercept) - .onOverrideUrlLoading(this.inAppWebView!.inAppWebViewChromeClient?.onOverrideUrlLoading) - .onRequestSelected(this.inAppWebView!.inAppWebViewChromeClient?.onRequestSelected) - .onScreenCaptureRequest(this.inAppWebView!.inAppWebViewChromeClient?.onScreenCaptureRequest) - .onOverScroll(this.inAppWebView!.inAppWebViewChromeClient?.onOverScroll) - .onNavigationEntryCommitted(this.inAppWebView!.inAppWebViewChromeClient?.onNavigationEntryCommitted) - .onSafeBrowsingCheckResult(this.inAppWebView!.inAppWebViewChromeClient?.onSafeBrowsingCheckResult) - .onNativeEmbedLifecycleChange(this.inAppWebView!.inAppWebViewChromeClient?.onNativeEmbedLifecycleChange) - .onNativeEmbedGestureEvent(this.inAppWebView!.inAppWebViewChromeClient?.onNativeEmbedGestureEvent) + .onHttpAuthRequest(this.inAppWebView!.inAppWebViewClient?.onHttpAuthRequest) + .onSslErrorEventReceive(this.inAppWebView!.inAppWebViewClient?.onSslErrorEventReceive) + .onClientAuthenticationRequest(this.inAppWebView!.inAppWebViewClient?.onClientAuthenticationRequest) + .onPermissionRequest(this.inAppWebView!.inAppWebViewClient?.onPermissionRequest) + .onContextMenuShow(this.inAppWebView!.inAppWebViewClient?.onContextMenuShow) + .onContextMenuHide(this.inAppWebView!.inAppWebViewClient?.onContextMenuHide) + .onScroll(this.inAppWebView!.inAppWebViewClient?.onScroll) + .onGeolocationShow(this.inAppWebView!.inAppWebViewClient?.onGeolocationShow) + .onGeolocationHide(this.inAppWebView!.inAppWebViewClient?.onGeolocationHide) + .onFullScreenEnter(this.inAppWebView!.inAppWebViewClient?.onFullScreenEnter) + .onFullScreenExit(this.inAppWebView!.inAppWebViewClient?.onFullScreenExit) + .onWindowNew(this.inAppWebView!.inAppWebViewClient?.onWindowNew) + .onWindowExit(this.inAppWebView!.inAppWebViewClient?.onWindowExit) + .onSearchResultReceive(this.inAppWebView!.inAppWebViewClient?.onSearchResultReceive) + .onDataResubmitted(this.inAppWebView!.inAppWebViewClient?.onDataResubmitted) + .onPageVisible(this.inAppWebView!.inAppWebViewClient?.onPageVisible) + .onInterceptKeyEvent(this.inAppWebView!.inAppWebViewClient?.onInterceptKeyEvent) + .onTouchIconUrlReceived(this.inAppWebView!.inAppWebViewClient?.onTouchIconUrlReceived) + .onFaviconReceived(this.inAppWebView!.inAppWebViewClient?.onFaviconReceived) + .onAudioStateChanged(this.inAppWebView!.inAppWebViewClient?.onAudioStateChanged) + .onFirstContentfulPaint(this.inAppWebView!.inAppWebViewClient?.onFirstContentfulPaint) + .onLoadIntercept(this.inAppWebView!.inAppWebViewClient?.onLoadIntercept) + .onOverrideUrlLoading(this.inAppWebView!.inAppWebViewClient?.onOverrideUrlLoading) + .onRequestSelected(this.inAppWebView!.inAppWebViewClient?.onRequestSelected) + .onScreenCaptureRequest(this.inAppWebView!.inAppWebViewClient?.onScreenCaptureRequest) + .onOverScroll(this.inAppWebView!.inAppWebViewClient?.onOverScroll) + .onNavigationEntryCommitted(this.inAppWebView!.inAppWebViewClient?.onNavigationEntryCommitted) + .onSafeBrowsingCheckResult(this.inAppWebView!.inAppWebViewClient?.onSafeBrowsingCheckResult) + .onNativeEmbedLifecycleChange(this.inAppWebView!.inAppWebViewClient?.onNativeEmbedLifecycleChange) + .onNativeEmbedGestureEvent(this.inAppWebView!.inAppWebViewClient?.onNativeEmbedGestureEvent) + .onRenderProcessNotResponding(this.inAppWebView!.inAppWebViewClient?.onRenderProcessNotResponding) + .onRenderProcessResponding(this.inAppWebView!.inAppWebViewClient?.onRenderProcessResponding) .onAreaChange(this.inAppWebView!.onAreaChange) .domStorageAccess(this.inAppWebView!.customSettings.domStorageAccess) .fileAccess(this.inAppWebView!.customSettings.fileAccess) @@ -144,7 +152,7 @@ export struct OhosWebView { .multiWindowAccess(this.inAppWebView!.customSettings.multiWindowAccess) .horizontalScrollBarAccess(this.inAppWebView!.customSettings.horizontalScrollBarAccess) .verticalScrollBarAccess(this.inAppWebView!.customSettings.verticalScrollBarAccess) - .cacheMode(this.inAppWebView!.customSettings.cacheMode) + .cacheMode(this.cacheEnabled ? this.inAppWebView!.customSettings.cacheMode : CacheMode.None) .textZoomRatio(this.inAppWebView!.customSettings.textZoomRatio) .initialScale(this.inAppWebView!.customSettings.initialScale) .blockNetwork(this.inAppWebView!.customSettings.blockNetwork) diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/web_message/WebMessageChannel.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/web_message/WebMessageChannel.ets index 82e106d3cffaa6620412caccfef2aeab370d6cd1..c4bd1cc9a67e56977b73a965a232a3555739385d 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/web_message/WebMessageChannel.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/web_message/WebMessageChannel.ets @@ -61,12 +61,12 @@ export class WebMessageChannel implements Disposable { if (webView != null) { let webMessageChannel: WebMessageChannel = this; webView.evaluateJavascript("(function() {" + - JavaScriptBridgeJS.WEB_MESSAGE_CHANNELS_VARIABLE_NAME + "['" + webMessageChannel.id + "'] = new MessageChannel();" + - "})();", null, { - onReceiveValue(value: string | null): void { - callback.onReceiveValue(webMessageChannel); - } + JavaScriptBridgeJS.WEB_MESSAGE_CHANNELS_VARIABLE_NAME + "['" + webMessageChannel.id + "'] = new MessageChannel();" + + "})();", null, { + onReceiveValue(value: string | null): void { + callback.onReceiveValue(webMessageChannel); } + } ); } else { callback.onReceiveValue(this); @@ -106,7 +106,7 @@ export class WebMessageChannel implements Disposable { let data: Any = message.getData(); try { /// 安卓端还会传入WebMessagePortCompat[]类型,目前ohos没有 - if (data != null) { + if (data != null && message.getType() == web_webview.WebMessageType.ARRAY_BUFFER) { let webMessageExt: web_webview.WebMessageExt = new web_webview.WebMessageExt() webMessageExt.setArrayBuffer(data as ArrayBuffer) webMessageExt.setType(web_webview.WebMessageType.ARRAY_BUFFER) @@ -153,14 +153,12 @@ export class WebMessageChannel implements Disposable { } public dispose(): void { - for (let i = 0; i < this.compatPorts.length; i++) { - this.compatPorts.pop(); - } if (this.channelDelegate != null) { this.channelDelegate.dispose(); this.channelDelegate = null; } - // this.compatPorts.pop(); + this.compatPorts.forEach(item => item.close()) + this.compatPorts = [] this.webView = null; } } \ No newline at end of file