From ff4b6cfc64284a4cc8c1be81e421029ea4317b15 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 18 Oct 2021 10:34:48 -0700 Subject: [PATCH 01/11] add dart files --- .../generatePigeons.sh | 5 + .../lib/src/android_webview.dart | 591 +++++++ .../lib/src/android_webview.pigeon.dart | 1464 +++++++++++++++++ .../lib/src/android_webview_api_impls.dart | 539 ++++++ .../lib/src/instance_manager.dart | 52 + .../pigeons/android_webview.dart | 168 ++ .../webview_flutter_android/pubspec.yaml | 1 + .../test/instance_manager_test.dart | 35 + 8 files changed, 2855 insertions(+) create mode 100755 packages/webview_flutter/webview_flutter_android/generatePigeons.sh create mode 100644 packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart create mode 100644 packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart create mode 100644 packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart create mode 100644 packages/webview_flutter/webview_flutter_android/lib/src/instance_manager.dart create mode 100644 packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart create mode 100644 packages/webview_flutter/webview_flutter_android/test/instance_manager_test.dart diff --git a/packages/webview_flutter/webview_flutter_android/generatePigeons.sh b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh new file mode 100755 index 000000000000..d6598017cbda --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh @@ -0,0 +1,5 @@ +flutter pub run pigeon \ +--input pigeons/android_webview.dart \ +--dart_out lib/src/android_webview.pigeon.dart \ +--java_out ./android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java \ +--java_package io.flutter.plugins.webviewflutter diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart new file mode 100644 index 000000000000..c4b0b445aa18 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart @@ -0,0 +1,591 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/widgets.dart' show AndroidViewSurface; + +import 'android_webview_api_impls.dart'; + +// TODO(bparrishMines): This can be removed once pigeon supports null values. +// Workaround to represent null Strings since pigeon doesn't support null +// values. +const String _nullStringIdentifier = ''; + +/// An Android View that displays web pages. +/// +/// **Basic usage** +/// In most cases, we recommend using a standard web browser, like Chrome, to +/// deliver content to the user. To learn more about web browsers, read the +/// guide on invoking a browser with +/// [url_launcher](https://pub.dev/packages/url_launcher). +/// +/// WebView objects allow you to display web content as part of your widget +/// layout, but lack some of the features of fully-developed browsers. A WebView +/// is useful when you need increased control over the UI and advanced +/// configuration options that will allow you to embed web pages in a +/// specially-designed environment for your app. +/// +/// To learn more about WebView and alternatives for serving web content, read +/// the documentation on +/// [Web-based content](https://developer.android.com/guide/webapps). +class WebView { + /// Constructs a new WebView. + WebView({this.useHybridComposition = false}) { + _api.createFromInstance(this); + } + + static final WebViewHostApiImpl _api = WebViewHostApiImpl(); + + WebViewClient? _currentWebViewClient; + DownloadListener? _currentDownloadListener; + Set _javaScriptChannels = {}; + + /// Whether the [WebView] will be rendered with an [AndroidViewSurface]. + /// + /// This implementation uses hybrid composition to render the WebView Widget. + /// This comes at the cost of some performance on Android versions below 10. + /// See + /// https://flutter.dev/docs/development/platform-integration/platform-views#performance + /// for more information. + /// + /// Defaults to false. + final bool useHybridComposition; + + /// The [WebSettings] object used to control the settings for this WebView. + late final WebSettings settings = WebSettings._(this); + + /// Enables debugging of web contents (HTML / CSS / JavaScript) loaded into any WebViews of this application. + /// + /// This flag can be enabled in order to facilitate debugging of web layouts + /// and JavaScript code running inside WebViews. Please refer to [WebView] + /// documentation for the debugging guide. The default is false. + static Future setWebContentsDebuggingEnabled(bool enabled) { + return _api.setWebContentsDebuggingEnabled(enabled); + } + + /// Loads the given URL with additional HTTP headers, specified as a map from name to value. + /// + /// Note that if this map contains any of the headers that are set by default + /// by this WebView, such as those controlling caching, accept types or the + /// User-Agent, their values may be overridden by this WebView's defaults. + /// + /// Also see compatibility note on [evaluateJavascript]. + Future loadUrl(String url, Map headers) { + return _api.loadUrlFromInstance(this, url, headers); + } + + /// Gets the URL for the current page. + /// + /// This is not always the same as the URL passed to + /// [WebViewClient.onPageStarted] because although the load for that URL has + /// begun, the current page may not have changed. + /// + /// Returns null if no page has been loaded. + Future getUrl() async { + final String result = await _api.getUrlFromInstance(this); + if (result == _nullStringIdentifier) return null; + return result; + } + + /// Whether this WebView has a back history item. + Future canGoBack() { + return _api.canGoBackFromInstance(this); + } + + /// Whether this WebView has a forward history item. + Future canGoForward() { + return _api.canGoForwardFromInstance(this); + } + + /// Goes back in the history of this WebView. + Future goBack() { + return _api.goBackFromInstance(this); + } + + /// Goes forward in the history of this WebView. + Future goForward() { + return _api.goForwardFromInstance(this); + } + + /// Reloads the current URL. + Future reload() { + return _api.reloadFromInstance(this); + } + + /// Clears the resource cache. + /// + /// Note that the cache is per-application, so this will clear the cache for + /// all WebViews used. + Future clearCache(bool includeDiskFiles) { + return _api.clearCacheFromInstance(this, includeDiskFiles); + } + + // TODO(bparrishMines): Update documentation once addJavascriptInterface is added. + /// Asynchronously evaluates JavaScript in the context of the currently displayed page. + /// + /// If non-null, the returned value will be any result returned from that + /// execution. + /// + /// Compatibility note. Applications targeting Android versions N or later, + /// JavaScript state from an empty WebView is no longer persisted across + /// navigations like [loadUrl]. For example, global variables and functions + /// defined before calling [loadUrl]) will not exist in the loaded page. + Future evaluateJavascript(String javascriptString) async { + final String result = await _api.evaluateJavascriptFromInstance( + this, + javascriptString, + ); + if (result == _nullStringIdentifier) return null; + return result; + } + + // TODO(bparrishMines): Update documentation when WebViewClient.onReceivedTitle is added. + /// Gets the title for the current page. + /// + /// Returns null if no page has been loaded. + Future getTitle() async { + final String result = await _api.getTitleFromInstance(this); + if (result == _nullStringIdentifier) return null; + return result; + } + + // TODO(bparrishMines): Update documentation when onScrollChanged is added. + /// Set the scrolled position of your view. + Future scrollTo(int x, int y) { + return _api.scrollToFromInstance(this, x, y); + } + + // TODO(bparrishMines): Update documentation when onScrollChanged is added. + /// Move the scrolled position of your view. + Future scrollBy(int x, int y) { + return _api.scrollByFromInstance(this, x, y); + } + + /// Return the scrolled left position of this view. + /// + /// This is the left edge of the displayed part of your view. You do not + /// need to draw any pixels farther left, since those are outside of the frame + /// of your view on screen. + Future getScrollX() { + return _api.getScrollXFromInstance(this); + } + + /// Return the scrolled top position of this view. + /// + /// This is the top edge of the displayed part of your view. You do not need + /// to draw any pixels above it, since those are outside of the frame of your + /// view on screen. + Future getScrollY() { + return _api.getScrollYFromInstance(this); + } + + /// Sets the [WebViewClient] that will receive various notifications and requests. + /// + /// This will replace the current handler. + Future setWebViewClient(WebViewClient webViewClient) async { + final WebViewClient? currentWebViewClient = _currentWebViewClient; + if (currentWebViewClient != null) { + // ignore: unawaited_futures + WebViewClient._api.disposeFromInstance(currentWebViewClient); + } + + // ignore: unawaited_futures + WebViewClient._api.createFromInstance(webViewClient); + _currentWebViewClient = webViewClient; + return _api.setWebViewClientFromInstance(this, webViewClient); + } + + /// Injects the supplied [JavascriptChannel] into this WebView. + /// + /// The object is injected into all frames of the web page, including all the + /// iframes, using the supplied name. This allows the object's methods to + /// be accessed from JavaScript. + /// + /// Note that injected objects will not appear in JavaScript until the page is + /// next (re)loaded. JavaScript should be enabled before injecting the object. + /// For example: + /// + /// ```dart + /// webview.settings.setJavaScriptEnabled(true); + /// webView.addJavascriptChannel(JavScriptChannel("injectedObject")); + /// webView.loadUrl("about:blank", {}); + /// webView.loadUrl("javascript:injectedObject.postMessage("Hello, World!")", {}); + /// ``` + /// + /// **Important** + /// * Because the object is exposed to all the frames, any frame could obtain + /// the object name and call methods on it. There is no way to tell the + /// calling frame's origin from the app side, so the app must not assume that + /// the caller is trustworthy unless the app can guarantee that no third party + /// content is ever loaded into the WebView even inside an iframe. + Future addJavaScriptChannel(JavaScriptChannel javaScriptChannel) async { + // ignore: unawaited_futures + JavaScriptChannel._api.createFromInstance(javaScriptChannel); + _javaScriptChannels.add(javaScriptChannel); + return _api.addJavaScriptChannelFromInstance(this, javaScriptChannel); + } + + /// Removes a previously injected [JavaScriptChannel] from this WebView. + /// + /// Note that the removal will not be reflected in JavaScript until the page + /// is next (re)loaded. See [addJavaScriptChannel]. + Future removeJavaScriptChannel(JavaScriptChannel javaScriptChannel) { + JavaScriptChannel._api.disposeFromInstance(javaScriptChannel); + _javaScriptChannels.remove(javaScriptChannel); + return _api.removeJavaScriptChannelFromInstance(this, javaScriptChannel); + } + + /// Registers the interface to be used when content can not be handled by the rendering engine, and should be downloaded instead. + /// + /// This will replace the current handler. + Future setDownloadListener(DownloadListener listener) { + final DownloadListener? currentDownloadListener = _currentDownloadListener; + if (currentDownloadListener != null) { + DownloadListener._api.disposeFromInstance(currentDownloadListener); + } + + DownloadListener._api.createFromInstance(listener); + _currentDownloadListener = listener; + return _api.setDownloadListenerFromInstance(this, listener); + } +} + +/// Manages settings state for a [WebView]. +/// +/// When a WebView is first created, it obtains a set of default settings. These +/// default settings will be returned from any getter call. A WebSettings object +/// obtained from [WebView.settings] is tied to the life of the WebView. If a +/// WebView has been destroyed, any method call on [WebSettings] will throw an +/// Exception. +class WebSettings { + WebSettings._(this.webView) { + _api.createFromInstance(this); + } + + /// The webView instance this is attached to. + final WebView webView; + + static final WebSettingsHostApiImpl _api = WebSettingsHostApiImpl(); + + /// Sets whether the DOM storage API is enabled. + /// + /// The default value is false. + Future setDomStorageEnabled(bool flag) { + return _api.setDomStorageEnabledFromInstance(this, flag); + } + + /// Tells JavaScript to open windows automatically. + /// + /// This applies to the JavaScript function `window.open()`. The default is + /// false. + Future setJavaScriptCanOpenWindowsAutomatically(bool flag) { + return _api.setJavaScriptCanOpenWindowsAutomaticallyFromInstance( + this, + flag, + ); + } + + // TODO(bparrishMines): Update documentation when WebChromeClient.onCreateWindow is added. + /// Sets whether the WebView should supports multiple windows. + /// + /// The default is false. + Future setSupportMultipleWindows(bool support) { + return _api.setSupportZoomFromInstance(this, support); + } + + /// Tells the WebView to enable JavaScript execution. + /// + /// The default is false. + Future setJavaScriptEnabled(bool flag) { + return _api.setJavaScriptEnabledFromInstance(this, flag); + } + + /// Sets the WebView's user-agent string. + /// + /// If the string is empty, the system default value will be used. Note that + /// starting from KITKAT Android version, changing the user-agent while + /// loading a web page causes WebView to initiate loading once again. + Future setUserAgentString(String userAgentString) { + return _api.setUserAgentStringFromInstance(this, userAgentString); + } + + /// Sets whether the WebView requires a user gesture to play media. + /// + /// The default is true. + Future setMediaPlaybackRequiresUserGesture(bool require) { + return _api.setMediaPlaybackRequiresUserGestureFromInstance(this, require); + } + + // TODO(bparrishMines): Update documentation when WebView.zoomIn and WebView.zoomOut are added. + /// Sets whether the WebView should support zooming using its on-screen zoom controls and gestures. + /// + /// The particular zoom mechanisms that should be used can be set with + /// [setBuiltInZoomControls]. + /// + /// The default is true. + Future setSupportZoom(bool support) { + return _api.setSupportZoomFromInstance(this, support); + } + + /// Sets whether the WebView loads pages in overview mode, that is, zooms out the content to fit on screen by width. + /// + /// This setting is taken into account when the content width is greater than + /// the width of the WebView control, for example, when [setUseWideViewPort] + /// is enabled. + /// + /// The default is false. + Future setLoadWithOverviewMode(bool overview) { + return _api.setLoadWithOverviewModeFromInstance(this, overview); + } + + /// Sets whether the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport. + /// + /// When the value of the setting is false, the layout width is always set to + /// the width of the WebView control in device-independent (CSS) pixels. When + /// the value is true and the page contains the viewport meta tag, the value + /// of the width specified in the tag is used. If the page does not contain + /// the tag or does not provide a width, then a wide viewport will be used. + Future setUseWideViewPort(bool use) { + return _api.setUseWideViewPortFromInstance(this, use); + } + + // TODO(bparrishMines): Update documentation when ZoomButtonsController is added. + /// Sets whether the WebView should display on-screen zoom controls when using the built-in zoom mechanisms. + /// + /// See [setBuiltInZoomControls]. The default is true. However, on-screen zoom + /// controls are deprecated in Android so it's recommended to set this to + /// false. + Future setDisplayZoomControls(bool enabled) { + return _api.setDisplayZoomControlsFromInstance(this, enabled); + } + + // TODO(bparrishMines): Update documentation when ZoomButtonsController is added. + /// Sets whether the WebView should use its built-in zoom mechanisms. + /// + /// The built-in zoom mechanisms comprise on-screen zoom controls, which are + /// displayed over the WebView's content, and the use of a pinch gesture to + /// control zooming. Whether or not these on-screen controls are displayed can + /// be set with [setDisplayZoomControls]. The default is false. + /// + /// The built-in mechanisms are the only currently supported zoom mechanisms, + /// so it is recommended that this setting is always enabled. However, + /// on-screen zoom controls are deprecated in Android so it's recommended to + /// disable [setDisplayZoomControls]. + Future setBuiltInZoomControls(bool enabled) { + return _api.setBuiltInZoomControlsFromInstance(this, enabled); + } +} + +/// Exposes a channel to receive calls from javaScript. +/// +/// See [WebView.addJavaScriptChannel]. +abstract class JavaScriptChannel { + /// Constructs a [JavaScriptChannel]. + JavaScriptChannel(this.channelName); + + static final JavaScriptChannelHostApiImpl _api = + JavaScriptChannelHostApiImpl(); + + /// Used to identify this object to receive messages from javaScript. + final String channelName; + + /// Callback method when javaScript calls `postMessage` on the object instance passed. + void postMessage(String message); +} + +/// Receive various notifications and requests for [WebView]. +abstract class WebViewClient { + /// Constructs a [WebViewClient]. + WebViewClient({this.shouldOverrideUrlLoading = true}); + + /// User authentication failed on server. + static const int errorAuthentication = 0xfffffffc; + + /// Malformed URL. + static const int errorBadUrl = 0xfffffff4; + + /// Failed to connect to the server. + static const int errorConnect = 0xfffffffa; + + /// Failed to perform SSL handshake. + static const int errorFailedSslHandshake = 0xfffffff5; + + /// Generic file error. + static const int errorFile = 0xfffffff3; + + /// File not found. + static const int errorFileNotFound = 0xfffffff2; + + /// Server or proxy hostname lookup failed. + static const int errorHostLookup = 0xfffffffe; + + /// Failed to read or write to the server. + static const int errorIO = 0xfffffff9; + + /// User authentication failed on proxy. + static const int errorProxyAuthentication = 0xfffffffb; + + /// Too many redirects. + static const int errorRedirectLoop = 0xfffffff7; + + /// Connection timed out. + static const int errorTimeout = 0xfffffff8; + + /// Too many requests during this load. + static const int errorTooManyRequests = 0xfffffff1; + + /// Generic error. + static const int errorUnknown = 0xffffffff; + + /// Resource load was canceled by Safe Browsing. + static const int errorUnsafeResource = 0xfffffff0; + + /// Unsupported authentication scheme (not basic or digest). + static const int errorUnsupportedAuthScheme = 0xfffffffd; + + /// Unsupported URI scheme. + static const int errorUnsupportedScheme = 0xfffffff6; + + static final WebViewClientHostApiImpl _api = WebViewClientHostApiImpl(); + + /// Whether loading a url should be overridden. + /// + /// In Java, `shouldOverrideUrlLoading()` and `shouldOverrideRequestLoading()` + /// callbacks must synchronously return a boolean. This sets the default + /// return value. + /// + /// Setting [shouldOverrideUrlLoading] to true causes the current [WebView] to + /// abort loading the URL, while returning false causes the [WebView] to + /// continue loading the URL as usual. [requestLoading] or [urlLoading] will + /// still be called either way. + /// + /// Defaults to true. + final bool shouldOverrideUrlLoading; + + /// Notify the host application that a page has started loading. + /// + /// This method is called once for each main frame load so a page with iframes + /// or framesets will call onPageStarted one time for the main frame. This + /// also means that [onPageStarted] will not be called when the contents of an + /// embedded frame changes, i.e. clicking a link whose target is an iframe, it + /// will also not be called for fragment navigations (navigations to + /// #fragment_id). + void onPageStarted(WebView webView, String url); + + // TODO(bparrishMines): Update documentation when WebView.postVisualStateCallback is added. + /// Notify the host application that a page has finished loading. + /// + /// This method is called only for main frame. Receiving an [onPageFinished] + /// callback does not guarantee that the next frame drawn by WebView will + /// reflect the state of the DOM at this point. + void onPageFinished(WebView webView, String url); + + /// Report web resource loading error to the host application. + /// + /// These errors usually indicate inability to connect to the server. Note + /// that unlike the deprecated version of the callback, the new version will + /// be called for any resource (iframe, image, etc.), not just for the main + /// page. Thus, it is recommended to perform minimum required work in this + /// callback. + void onReceivedRequestError( + WebView webView, + WebResourceRequest request, + WebResourceError error, + ); + + /// Report an error to the host application. + /// + /// These errors are unrecoverable (i.e. the main resource is unavailable). + /// The errorCode parameter corresponds to one of the error* constants. + @Deprecated('Only called on Android version < 23.') + void onReceivedError( + WebView webView, + int errorCode, + String description, + String failingUrl, + ); + + // TODO(bparrishMines): Update documentation once synchronous url handling is supported. + /// When a URL is about to be loaded in the current [WebView]. + /// + /// If a [WebViewClient] is not provided, by default [WebView] will ask + /// Activity Manager to choose the proper handler for the URL. If a + /// [WebViewClient] is provided, setting [shouldOverrideUrlLoading] to true + /// causes the current [WebView] to abort loading the URL, while returning + /// false causes the [WebView] to continue loading the URL as usual. + void requestLoading(WebView webView, WebResourceRequest request); + + // TODO(bparrishMines): Update documentation once synchronous url handling is supported. + /// When a URL is about to be loaded in the current [WebView]. + /// + /// If a [WebViewClient] is not provided, by default [WebView] will ask + /// Activity Manager to choose the proper handler for the URL. If a + /// [WebViewClient] is provided, setting [shouldOverrideUrlLoading] to true + /// causes the current [WebView] to abort loading the URL, while returning + /// false causes the [WebView] to continue loading the URL as usual. + void urlLoading(WebView webView, String url); +} + +/// The interface to be used when content can not be handled by the rendering engine for [WebView], and should be downloaded instead. +abstract class DownloadListener { + static final DownloadListenerHostApiImpl _api = DownloadListenerHostApiImpl(); + + /// Notify the host application that a file should be downloaded. + void onDownloadStart( + String url, + String userAgent, + String contentDisposition, + String mimetype, + int contentLength, + ); +} + +/// Encompasses parameters to the [WebViewClient.requestLoading] method. +class WebResourceRequest { + /// Constructs a [WebResourceRequest]. + WebResourceRequest({ + required this.url, + required this.isForMainFrame, + required this.isRedirect, + required this.hasGesture, + required this.method, + required this.requestHeaders, + }); + + /// Gets the URL for which the resource request was made. + final String url; + + /// Gets whether the request was made in order to fetch the main frame's document. + final isForMainFrame; + + /// Gets whether the request was a result of a server-side redirect. + /// + /// Only supported on Android version >= 24. + final bool? isRedirect; + + /// Gets whether a gesture (such as a click) was associated with the request. + final bool hasGesture; + + /// Gets the method associated with the request, for example "GET". + final String method; + + /// Gets the headers associated with the request. + final Map requestHeaders; +} + +/// Encapsulates information about errors occurred during loading of web resources. +/// +/// See [WebViewClient.onReceivedRequestError]. +class WebResourceError { + /// Constructs a [WebResourceError]. + WebResourceError({ + required this.errorCode, + required this.description, + }); + + /// The integer code of the error (e.g. [WebViewClient.errorAuthentication]. + final int errorCode; + + /// Describes the error. + final String description; +} diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart new file mode 100644 index 000000000000..930563cb2ced --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart @@ -0,0 +1,1464 @@ +// Autogenerated from Pigeon (v1.0.7), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name +// @dart = 2.12 +import 'dart:async'; +import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; + +import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; +import 'package:flutter/services.dart'; + +class WebResourceRequestData { + String? url; + bool? isForMainFrame; + bool? isRedirect; + bool? hasGesture; + String? method; + Map? requestHeaders; + + Object encode() { + final Map pigeonMap = {}; + pigeonMap['url'] = url; + pigeonMap['isForMainFrame'] = isForMainFrame; + pigeonMap['isRedirect'] = isRedirect; + pigeonMap['hasGesture'] = hasGesture; + pigeonMap['method'] = method; + pigeonMap['requestHeaders'] = requestHeaders; + return pigeonMap; + } + + static WebResourceRequestData decode(Object message) { + final Map pigeonMap = message as Map; + return WebResourceRequestData() + ..url = pigeonMap['url'] as String? + ..isForMainFrame = pigeonMap['isForMainFrame'] as bool? + ..isRedirect = pigeonMap['isRedirect'] as bool? + ..hasGesture = pigeonMap['hasGesture'] as bool? + ..method = pigeonMap['method'] as String? + ..requestHeaders = (pigeonMap['requestHeaders'] as Map?) + ?.cast(); + } +} + +class WebResourceErrorData { + int? errorCode; + String? description; + + Object encode() { + final Map pigeonMap = {}; + pigeonMap['errorCode'] = errorCode; + pigeonMap['description'] = description; + return pigeonMap; + } + + static WebResourceErrorData decode(Object message) { + final Map pigeonMap = message as Map; + return WebResourceErrorData() + ..errorCode = pigeonMap['errorCode'] as int? + ..description = pigeonMap['description'] as String?; + } +} + +class _WebViewHostApiCodec extends StandardMessageCodec { + const _WebViewHostApiCodec(); +} + +class WebViewHostApi { + /// Constructor for [WebViewHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + WebViewHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _WebViewHostApiCodec(); + + Future create(int arg_instanceId, bool arg_useHybridComposition) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.create', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_useHybridComposition]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future dispose(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.dispose', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future loadUrl(int arg_instanceId, String arg_url, + Map arg_headers) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.loadUrl', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_url, arg_headers]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future getUrl(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getUrl', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as String?)!; + } + } + + Future canGoBack(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.canGoBack', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as bool?)!; + } + } + + Future canGoForward(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.canGoForward', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as bool?)!; + } + } + + Future goBack(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.goBack', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future goForward(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.goForward', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future reload(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.reload', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future clearCache(int arg_instanceId, bool arg_includeDiskFiles) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.clearCache', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_includeDiskFiles]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future evaluateJavascript( + int arg_instanceId, String arg_javascriptString) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.evaluateJavascript', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_javascriptString]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as String?)!; + } + } + + Future getTitle(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getTitle', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as String?)!; + } + } + + Future scrollTo(int arg_instanceId, int arg_x, int arg_y) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.scrollTo', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_x, arg_y]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future scrollBy(int arg_instanceId, int arg_x, int arg_y) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.scrollBy', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_x, arg_y]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future getScrollX(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getScrollX', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as int?)!; + } + } + + Future getScrollY(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getScrollY', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as int?)!; + } + } + + Future setWebContentsDebuggingEnabled(bool arg_enabled) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_enabled]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setWebViewClient( + int arg_instanceId, int arg_webViewClientInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setWebViewClient', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_webViewClientInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future addJavaScriptChannel( + int arg_instanceId, int arg_javaScriptChannelInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_javaScriptChannelInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future removeJavaScriptChannel( + int arg_instanceId, int arg_javaScriptChannelInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_javaScriptChannelInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setDownloadListener( + int arg_instanceId, int arg_listenerInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setDownloadListener', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_listenerInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _WebSettingsHostApiCodec extends StandardMessageCodec { + const _WebSettingsHostApiCodec(); +} + +class WebSettingsHostApi { + /// Constructor for [WebSettingsHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + WebSettingsHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _WebSettingsHostApiCodec(); + + Future create(int arg_instanceId, int arg_webViewInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.create', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_webViewInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future dispose(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.dispose', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setDomStorageEnabled(int arg_instanceId, bool arg_flag) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_flag]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setJavaScriptCanOpenWindowsAutomatically( + int arg_instanceId, bool arg_flag) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_flag]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setSupportMultipleWindows( + int arg_instanceId, bool arg_support) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_support]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setJavaScriptEnabled(int arg_instanceId, bool arg_flag) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_flag]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setUserAgentString( + int arg_instanceId, String arg_userAgentString) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_userAgentString]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setMediaPlaybackRequiresUserGesture( + int arg_instanceId, bool arg_require) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_require]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setSupportZoom(int arg_instanceId, bool arg_support) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_support]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setLoadWithOverviewMode( + int arg_instanceId, bool arg_overview) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_overview]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setUseWideViewPort(int arg_instanceId, bool arg_use) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_use]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setDisplayZoomControls( + int arg_instanceId, bool arg_enabled) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_enabled]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setBuiltInZoomControls( + int arg_instanceId, bool arg_enabled) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_enabled]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _JavaScriptChannelHostApiCodec extends StandardMessageCodec { + const _JavaScriptChannelHostApiCodec(); +} + +class JavaScriptChannelHostApi { + /// Constructor for [JavaScriptChannelHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + JavaScriptChannelHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _JavaScriptChannelHostApiCodec(); + + Future create(int arg_instanceId, String arg_channelName) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.JavaScriptChannelHostApi.create', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_channelName]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future dispose(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.JavaScriptChannelHostApi.dispose', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _JavaScriptChannelFlutterApiCodec extends StandardMessageCodec { + const _JavaScriptChannelFlutterApiCodec(); +} + +abstract class JavaScriptChannelFlutterApi { + static const MessageCodec codec = + _JavaScriptChannelFlutterApiCodec(); + + void postMessage(int instanceId, String message); + static void setup(JavaScriptChannelFlutterApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.JavaScriptChannelFlutterApi.postMessage', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelFlutterApi.postMessage was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelFlutterApi.postMessage was null, expected non-null int.'); + final String? arg_message = args[1] as String?; + assert(arg_message != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelFlutterApi.postMessage was null, expected non-null String.'); + api.postMessage(arg_instanceId!, arg_message!); + return; + }); + } + } + } +} + +class _WebViewClientHostApiCodec extends StandardMessageCodec { + const _WebViewClientHostApiCodec(); +} + +class WebViewClientHostApi { + /// Constructor for [WebViewClientHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + WebViewClientHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _WebViewClientHostApiCodec(); + + Future create( + int arg_instanceId, bool arg_shouldOverrideUrlLoading) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientHostApi.create', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_shouldOverrideUrlLoading]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future dispose(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientHostApi.dispose', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _WebViewClientFlutterApiCodec extends StandardMessageCodec { + const _WebViewClientFlutterApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is WebResourceErrorData) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else if (value is WebResourceRequestData) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else if (value is WebResourceRequestData) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return WebResourceErrorData.decode(readValue(buffer)!); + + case 129: + return WebResourceRequestData.decode(readValue(buffer)!); + + case 130: + return WebResourceRequestData.decode(readValue(buffer)!); + + default: + return super.readValueOfType(type, buffer); + } + } +} + +abstract class WebViewClientFlutterApi { + static const MessageCodec codec = _WebViewClientFlutterApiCodec(); + + void onPageStarted(int instanceId, int webViewInstanceId, String url); + void onPageFinished(int instanceId, int webViewInstanceId, String url); + void onReceivedRequestError(int instanceId, int webViewInstanceId, + WebResourceRequestData request, WebResourceErrorData error); + void onReceivedError(int instanceId, int webViewInstanceId, int errorCode, + String description, String failingUrl); + void requestLoading( + int instanceId, int webViewInstanceId, WebResourceRequestData request); + void urlLoading(int instanceId, int webViewInstanceId, String url); + static void setup(WebViewClientFlutterApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientFlutterApi.onPageStarted', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageStarted was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageStarted was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageStarted was null, expected non-null int.'); + final String? arg_url = args[2] as String?; + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageStarted was null, expected non-null String.'); + api.onPageStarted(arg_instanceId!, arg_webViewInstanceId!, arg_url!); + return; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientFlutterApi.onPageFinished', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageFinished was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageFinished was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageFinished was null, expected non-null int.'); + final String? arg_url = args[2] as String?; + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageFinished was null, expected non-null String.'); + api.onPageFinished(arg_instanceId!, arg_webViewInstanceId!, arg_url!); + return; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError', + codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError was null, expected non-null int.'); + final WebResourceRequestData? arg_request = + args[2] as WebResourceRequestData?; + assert(arg_request != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError was null, expected non-null WebResourceRequestData.'); + final WebResourceErrorData? arg_error = + args[3] as WebResourceErrorData?; + assert(arg_error != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError was null, expected non-null WebResourceErrorData.'); + api.onReceivedRequestError(arg_instanceId!, arg_webViewInstanceId!, + arg_request!, arg_error!); + return; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError was null, expected non-null int.'); + final int? arg_errorCode = args[2] as int?; + assert(arg_errorCode != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError was null, expected non-null int.'); + final String? arg_description = args[3] as String?; + assert(arg_description != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError was null, expected non-null String.'); + final String? arg_failingUrl = args[4] as String?; + assert(arg_failingUrl != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError was null, expected non-null String.'); + api.onReceivedError(arg_instanceId!, arg_webViewInstanceId!, + arg_errorCode!, arg_description!, arg_failingUrl!); + return; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientFlutterApi.requestLoading', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.requestLoading was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.requestLoading was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.requestLoading was null, expected non-null int.'); + final WebResourceRequestData? arg_request = + args[2] as WebResourceRequestData?; + assert(arg_request != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.requestLoading was null, expected non-null WebResourceRequestData.'); + api.requestLoading( + arg_instanceId!, arg_webViewInstanceId!, arg_request!); + return; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientFlutterApi.urlLoading', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.urlLoading was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.urlLoading was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.urlLoading was null, expected non-null int.'); + final String? arg_url = args[2] as String?; + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.urlLoading was null, expected non-null String.'); + api.urlLoading(arg_instanceId!, arg_webViewInstanceId!, arg_url!); + return; + }); + } + } + } +} + +class _DownloadListenerHostApiCodec extends StandardMessageCodec { + const _DownloadListenerHostApiCodec(); +} + +class DownloadListenerHostApi { + /// Constructor for [DownloadListenerHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + DownloadListenerHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _DownloadListenerHostApiCodec(); + + Future create(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.DownloadListenerHostApi.create', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future dispose(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.DownloadListenerHostApi.dispose', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _DownloadListenerFlutterApiCodec extends StandardMessageCodec { + const _DownloadListenerFlutterApiCodec(); +} + +abstract class DownloadListenerFlutterApi { + static const MessageCodec codec = _DownloadListenerFlutterApiCodec(); + + void onDownloadStart(int instanceId, String url, String userAgent, + String contentDisposition, String mimetype, int contentLength); + static void setup(DownloadListenerFlutterApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart', + codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null, expected non-null int.'); + final String? arg_url = args[1] as String?; + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null, expected non-null String.'); + final String? arg_userAgent = args[2] as String?; + assert(arg_userAgent != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null, expected non-null String.'); + final String? arg_contentDisposition = args[3] as String?; + assert(arg_contentDisposition != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null, expected non-null String.'); + final String? arg_mimetype = args[4] as String?; + assert(arg_mimetype != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null, expected non-null String.'); + final int? arg_contentLength = args[5] as int?; + assert(arg_contentLength != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null, expected non-null int.'); + api.onDownloadStart(arg_instanceId!, arg_url!, arg_userAgent!, + arg_contentDisposition!, arg_mimetype!, arg_contentLength!); + return; + }); + } + } + } +} diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart new file mode 100644 index 000000000000..9582b79ab4b6 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart @@ -0,0 +1,539 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'android_webview.dart'; +import 'android_webview.pigeon.dart'; +import 'instance_manager.dart'; + +/// Host api implementation for [WebView]. +class WebViewHostApiImpl extends WebViewHostApi { + /// Constructs a [WebViewHostApiImpl]. + WebViewHostApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(WebView instance) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + return create(instanceId, instance.useHybridComposition); + } + } + + /// Helper method to convert instances ids to objects. + Future disposeFromInstance(WebView instance) async { + final int? instanceId = instanceManager.removeInstance(instance); + if (instanceId != null) { + return dispose(instanceId); + } + } + + /// Helper method to convert instances ids to objects. + Future loadUrlFromInstance( + WebView instance, + String url, + Map headers, + ) { + return loadUrl(instanceManager.getInstanceId(instance)!, url, headers); + } + + /// Helper method to convert instances ids to objects. + Future getUrlFromInstance(WebView instance) { + return getUrl(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future canGoBackFromInstance(WebView instance) { + return canGoBack(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future canGoForwardFromInstance(WebView instance) { + return canGoForward(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future goBackFromInstance(WebView instance) { + return goBack(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future goForwardFromInstance(WebView instance) { + return goForward(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future reloadFromInstance(WebView instance) { + return reload(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future clearCacheFromInstance(WebView instance, bool includeDiskFiles) { + return clearCache( + instanceManager.getInstanceId(instance)!, + includeDiskFiles, + ); + } + + /// Helper method to convert instances ids to objects. + Future evaluateJavascriptFromInstance( + WebView instance, + String javascriptString, + ) { + return evaluateJavascript( + instanceManager.getInstanceId(instance)!, javascriptString); + } + + /// Helper method to convert instances ids to objects. + Future getTitleFromInstance(WebView instance) { + return getTitle(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future scrollToFromInstance(WebView instance, int x, int y) { + return scrollTo(instanceManager.getInstanceId(instance)!, x, y); + } + + /// Helper method to convert instances ids to objects. + Future scrollByFromInstance(WebView instance, int x, int y) { + return scrollBy(instanceManager.getInstanceId(instance)!, x, y); + } + + /// Helper method to convert instances ids to objects. + Future getScrollXFromInstance(WebView instance) { + return getScrollX(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future getScrollYFromInstance(WebView instance) { + return getScrollY(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future setWebViewClientFromInstance( + WebView instance, + WebViewClient webViewClient, + ) { + return setWebViewClient( + instanceManager.getInstanceId(instance)!, + instanceManager.getInstanceId(webViewClient)!, + ); + } + + /// Helper method to convert instances ids to objects. + Future addJavaScriptChannelFromInstance( + WebView instance, + JavaScriptChannel javaScriptChannel, + ) { + return addJavaScriptChannel( + instanceManager.getInstanceId(instance)!, + instanceManager.getInstanceId(javaScriptChannel)!, + ); + } + + /// Helper method to convert instances ids to objects. + Future removeJavaScriptChannelFromInstance( + WebView instance, + JavaScriptChannel javaScriptChannel, + ) { + return removeJavaScriptChannel( + instanceManager.getInstanceId(instance)!, + instanceManager.getInstanceId(javaScriptChannel)!, + ); + } + + /// Helper method to convert instances ids to objects. + Future setDownloadListenerFromInstance( + WebView instance, + DownloadListener listener, + ) { + return setDownloadListener( + instanceManager.getInstanceId(instance)!, + instanceManager.getInstanceId(listener)!, + ); + } +} + +/// Host api implementation for [WebSettings]. +class WebSettingsHostApiImpl extends WebSettingsHostApi { + /// Constructs a [WebSettingsHostApiImpl]. + WebSettingsHostApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(WebSettings instance) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + return create( + instanceId, + instanceManager.getInstanceId(instance.webView)!, + ); + } + } + + /// Helper method to convert instances ids to objects. + Future disposeFromInstance(WebSettings instance) async { + final int? instanceId = instanceManager.removeInstance(instance); + if (instanceId != null) { + return dispose(instanceId); + } + } + + /// Helper method to convert instances ids to objects. + Future setDomStorageEnabledFromInstance( + WebSettings instance, + bool flag, + ) { + return setDomStorageEnabled(instanceManager.getInstanceId(instance)!, flag); + } + + /// Helper method to convert instances ids to objects. + Future setJavaScriptCanOpenWindowsAutomaticallyFromInstance( + WebSettings instance, + bool flag, + ) { + return setJavaScriptCanOpenWindowsAutomatically( + instanceManager.getInstanceId(instance)!, + flag, + ); + } + + /// Helper method to convert instances ids to objects. + Future setSupportMultipleWindowsFromInstance( + WebSettings instance, + bool support, + ) { + return setSupportMultipleWindows( + instanceManager.getInstanceId(instance)!, support); + } + + /// Helper method to convert instances ids to objects. + Future setJavaScriptEnabledFromInstance( + WebSettings instance, + bool flag, + ) { + return setJavaScriptCanOpenWindowsAutomatically( + instanceManager.getInstanceId(instance)!, + flag, + ); + } + + /// Helper method to convert instances ids to objects. + Future setUserAgentStringFromInstance( + WebSettings instance, + String userAgentString, + ) { + return setUserAgentString( + instanceManager.getInstanceId(instance)!, + userAgentString, + ); + } + + /// Helper method to convert instances ids to objects. + Future setMediaPlaybackRequiresUserGestureFromInstance( + WebSettings instance, + bool require, + ) { + return setMediaPlaybackRequiresUserGesture( + instanceManager.getInstanceId(instance)!, + require, + ); + } + + /// Helper method to convert instances ids to objects. + Future setSupportZoomFromInstance( + WebSettings instance, + bool support, + ) { + return setSupportZoom(instanceManager.getInstanceId(instance)!, support); + } + + /// Helper method to convert instances ids to objects. + Future setLoadWithOverviewModeFromInstance( + WebSettings instance, + bool overview, + ) { + return setLoadWithOverviewMode( + instanceManager.getInstanceId(instance)!, + overview, + ); + } + + /// Helper method to convert instances ids to objects. + Future setUseWideViewPortFromInstance( + WebSettings instance, + bool use, + ) { + return setUseWideViewPort(instanceManager.getInstanceId(instance)!, use); + } + + /// Helper method to convert instances ids to objects. + Future setDisplayZoomControlsFromInstance( + WebSettings instance, + bool enabled, + ) { + return setDisplayZoomControls( + instanceManager.getInstanceId(instance)!, + enabled, + ); + } + + /// Helper method to convert instances ids to objects. + Future setBuiltInZoomControlsFromInstance( + WebSettings instance, + bool enabled, + ) { + return setBuiltInZoomControls( + instanceManager.getInstanceId(instance)!, + enabled, + ); + } +} + +/// Host api implementation for [JavaScriptChannel]. +class JavaScriptChannelHostApiImpl extends JavaScriptChannelHostApi { + /// Constructs a [JavaScriptChannelHostApiImpl]. + JavaScriptChannelHostApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(JavaScriptChannel instance) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + return create(instanceId, instance.channelName); + } + } + + /// Helper method to convert instances ids to objects. + Future disposeFromInstance(JavaScriptChannel instance) async { + final int? instanceId = instanceManager.removeInstance(instance); + if (instanceId != null) { + return dispose(instanceId); + } + } +} + +/// Flutter api implementation for [JavaScriptChannel]. +class JavaScriptChannelFlutterApiImpl extends JavaScriptChannelFlutterApi { + /// Constructs a [JavaScriptChannelFlutterApiImpl]. + JavaScriptChannelHostApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + @override + void postMessage(int instanceId, String message) { + final JavaScriptChannel instance = + instanceManager.getInstance(instanceId) as JavaScriptChannel; + instance.postMessage(message); + } +} + +/// Host api implementation for [WebViewClient]. +class WebViewClientHostApiImpl extends WebViewClientHostApi { + /// Constructs a [WebViewClientHostApiImpl]. + WebViewClientHostApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(WebViewClient instance) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + return create(instanceId, instance.shouldOverrideUrlLoading); + } + } + + /// Helper method to convert instances ids to objects. + Future disposeFromInstance(WebViewClient instance) async { + final int? instanceId = instanceManager.removeInstance(instance); + if (instanceId != null) { + return dispose(instanceId); + } + } +} + +/// Flutter api implementation for [WebViewClient]. +class WebViewClientFlutterApiImpl extends WebViewClientFlutterApi { + /// Constructs a [WebViewClientFlutterApiImpl]. + WebViewClientFlutterApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + @override + void onPageFinished(int instanceId, int webViewInstanceId, String url) { + final WebViewClient instance = + instanceManager.getInstance(instanceId) as WebViewClient; + instance.onPageFinished( + instanceManager.getInstance(webViewInstanceId) as WebView, + url, + ); + } + + @override + void onPageStarted(int instanceId, int webViewInstanceId, String url) { + final WebViewClient instance = + instanceManager.getInstance(instanceId) as WebViewClient; + instance.onPageStarted( + instanceManager.getInstance(webViewInstanceId) as WebView, + url, + ); + } + + @override + void onReceivedError( + int instanceId, + int webViewInstanceId, + int errorCode, + String description, + String failingUrl, + ) { + final WebViewClient instance = + instanceManager.getInstance(instanceId) as WebViewClient; + instance.onReceivedError( + instanceManager.getInstance(webViewInstanceId) as WebView, + errorCode, + description, + failingUrl, + ); + } + + @override + void onReceivedRequestError( + int instanceId, + int webViewInstanceId, + WebResourceRequestData request, + WebResourceErrorData error, + ) { + final WebViewClient instance = + instanceManager.getInstance(instanceId) as WebViewClient; + instance.onReceivedRequestError( + instanceManager.getInstance(webViewInstanceId) as WebView, + WebResourceRequest( + url: request.url!, + isForMainFrame: request.isForMainFrame!, + isRedirect: request.isRedirect, + hasGesture: request.hasGesture!, + method: request.method!, + requestHeaders: request.requestHeaders!.cast(), + ), + WebResourceError( + errorCode: error.errorCode!, + description: error.description!, + ), + ); + } + + @override + void requestLoading( + int instanceId, + int webViewInstanceId, + WebResourceRequestData request, + ) { + final WebViewClient instance = + instanceManager.getInstance(instanceId) as WebViewClient; + instance.requestLoading( + instanceManager.getInstance(webViewInstanceId) as WebView, + WebResourceRequest( + url: request.url!, + isForMainFrame: request.isForMainFrame!, + isRedirect: request.isRedirect, + hasGesture: request.hasGesture!, + method: request.method!, + requestHeaders: request.requestHeaders!.cast(), + ), + ); + } + + @override + void urlLoading( + int instanceId, + int webViewInstanceId, + String url, + ) { + final WebViewClient instance = + instanceManager.getInstance(instanceId) as WebViewClient; + instance.urlLoading( + instanceManager.getInstance(webViewInstanceId) as WebView, + url, + ); + } +} + +/// Host api implementation for [DownloadListener]. +class DownloadListenerHostApiImpl extends DownloadListenerHostApi { + /// Constructs a [DownloadListenerHostApiImpl]. + DownloadListenerHostApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(DownloadListener instance) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + return create(instanceId); + } + } + + /// Helper method to convert instances ids to objects. + Future disposeFromInstance(DownloadListener instance) async { + final int? instanceId = instanceManager.removeInstance(instance); + if (instanceId != null) { + return dispose(instanceId); + } + } +} + +/// Flutter api implementation for [DownloadListener]. +class DownloadListenerFlutterApiImpl extends DownloadListenerFlutterApi { + /// Constructs a [DownloadListenerFlutterApiImpl]. + DownloadListenerFlutterApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + @override + void onDownloadStart( + int instanceId, + String url, + String userAgent, + String contentDisposition, + String mimetype, + int contentLength, + ) { + final DownloadListener instance = + instanceManager.getInstance(instanceId) as DownloadListener; + instance.onDownloadStart( + url, + userAgent, + contentDisposition, + mimetype, + contentLength, + ); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/instance_manager.dart b/packages/webview_flutter/webview_flutter_android/lib/src/instance_manager.dart new file mode 100644 index 000000000000..94d8bc3253eb --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/lib/src/instance_manager.dart @@ -0,0 +1,52 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// Maintains instances stored to communicate with java objects. +class InstanceManager { + Map _instanceIdsToInstances = {}; + Map _instancesToInstanceIds = {}; + + int _nextInstanceId = 0; + + /// Global instance of [InstanceManager]. + static final InstanceManager instance = InstanceManager(); + + /// Attempt to add a new instance. + /// + /// Returns new if [instance] has already been added. Otherwise, it is added + /// with a new instance id. + int? tryAddInstance(Object instance) { + if (_instancesToInstanceIds.containsKey(instance)) { + return null; + } + + final int instanceId = _nextInstanceId++; + _instancesToInstanceIds[instance] = instanceId; + _instanceIdsToInstances[instanceId] = instance; + return instanceId; + } + + /// Remove the instance from the manager. + /// + /// Returns null if the instance is removed. Otherwise, return the instanceId + /// of the removed instance. + int? removeInstance(Object instance) { + final int? instanceId = _instancesToInstanceIds[instance]; + if (instanceId != null) { + _instancesToInstanceIds.remove(instance); + _instanceIdsToInstances.remove(instanceId); + } + return instanceId; + } + + /// Retrieve the Object paired with instanceId. + Object? getInstance(int instanceId) { + return _instanceIdsToInstances[instanceId]; + } + + /// Retrieve the instanceId paired with instance. + int? getInstanceId(Object instance) { + return _instancesToInstanceIds[instance]; + } +} diff --git a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart new file mode 100644 index 000000000000..7efbe17861bf --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart @@ -0,0 +1,168 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:pigeon/pigeon.dart'; + +class WebResourceRequestData { + String? url; + bool? isForMainFrame; + bool? isRedirect; + bool? hasGesture; + String? method; + Map? requestHeaders; +} + +class WebResourceErrorData { + int? errorCode; + String? description; +} + +@HostApi() +abstract class WebViewHostApi { + void create(int instanceId, bool useHybridComposition); + + void dispose(int instanceId); + + void loadUrl( + int instanceId, + String url, + Map headers, + ); + + String getUrl(int instanceId); + + bool canGoBack(int instanceId); + + bool canGoForward(int instanceId); + + void goBack(int instanceId); + + void goForward(int instanceId); + + void reload(int instanceId); + + void clearCache(int instanceId, bool includeDiskFiles); + + @async + String evaluateJavascript( + int instanceId, + String javascriptString, + ); + + String getTitle(int instanceId); + + void scrollTo(int instanceId, int x, int y); + + void scrollBy(int instanceId, int x, int y); + + int getScrollX(int instanceId); + + int getScrollY(int instanceId); + + void setWebContentsDebuggingEnabled(bool enabled); + + void setWebViewClient(int instanceId, int webViewClientInstanceId); + + void addJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId); + + void removeJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId); + + void setDownloadListener(int instanceId, int listenerInstanceId); +} + +@HostApi() +abstract class WebSettingsHostApi { + void create(int instanceId, int webViewInstanceId); + + void dispose(int instanceId); + + void setDomStorageEnabled(int instanceId, bool flag); + + void setJavaScriptCanOpenWindowsAutomatically(int instanceId, bool flag); + + void setSupportMultipleWindows(int instanceId, bool support); + + void setJavaScriptEnabled(int instanceId, bool flag); + + void setUserAgentString(int instanceId, String userAgentString); + + void setMediaPlaybackRequiresUserGesture(int instanceId, bool require); + + void setSupportZoom(int instanceId, bool support); + + void setLoadWithOverviewMode(int instanceId, bool overview); + + void setUseWideViewPort(int instanceId, bool use); + + void setDisplayZoomControls(int instanceId, bool enabled); + + void setBuiltInZoomControls(int instanceId, bool enabled); +} + +@HostApi() +abstract class JavaScriptChannelHostApi { + void create(int instanceId, String channelName); + + void dispose(int instanceId); +} + +@FlutterApi() +abstract class JavaScriptChannelFlutterApi { + void postMessage(int instanceId, String message); +} + +@HostApi() +abstract class WebViewClientHostApi { + void create(int instanceId, bool shouldOverrideUrlLoading); + + void dispose(int instanceId); +} + +@FlutterApi() +abstract class WebViewClientFlutterApi { + void onPageStarted(int instanceId, int webViewInstanceId, String url); + + void onPageFinished(int instanceId, int webViewInstanceId, String url); + + void onReceivedRequestError( + int instanceId, + int webViewInstanceId, + WebResourceRequestData request, + WebResourceErrorData error, + ); + + void onReceivedError( + int instanceId, + int webViewInstanceId, + int errorCode, + String description, + String failingUrl, + ); + + void requestLoading( + int instanceId, + int webViewInstanceId, + WebResourceRequestData request, + ); + + void urlLoading(int instanceId, int webViewInstanceId, String url); +} + +@HostApi() +abstract class DownloadListenerHostApi { + void create(int instanceId); + void dispose(int instanceId); +} + +@FlutterApi() +abstract class DownloadListenerFlutterApi { + void onDownloadStart( + int instanceId, + String url, + String userAgent, + String contentDisposition, + String mimetype, + int contentLength, + ); +} diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml index 36f186087c08..04511e670d4c 100644 --- a/packages/webview_flutter/webview_flutter_android/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/pubspec.yaml @@ -27,5 +27,6 @@ dev_dependencies: sdk: flutter flutter_test: sdk: flutter + pigeon: 1.0.7 pedantic: ^1.10.0 diff --git a/packages/webview_flutter/webview_flutter_android/test/instance_manager_test.dart b/packages/webview_flutter/webview_flutter_android/test/instance_manager_test.dart new file mode 100644 index 000000000000..fd020fc362c8 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/test/instance_manager_test.dart @@ -0,0 +1,35 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:webview_flutter_android/src/instance_manager.dart'; + +void main() { + group('$InstanceManager', () { + late InstanceManager testInstanceManager; + + setUp(() { + testInstanceManager = InstanceManager(); + }); + + test('tryAddInstance', () { + final Object object = Object(); + + expect(testInstanceManager.tryAddInstance(object), 0); + expect(testInstanceManager.getInstanceId(object), 0); + expect(testInstanceManager.getInstance(0), object); + expect(testInstanceManager.tryAddInstance(object), null); + }); + + test('removeInstance', () { + final Object object = Object(); + testInstanceManager.tryAddInstance(object); + + expect(testInstanceManager.removeInstance(object), 0); + expect(testInstanceManager.getInstanceId(object), null); + expect(testInstanceManager.getInstance(0), null); + expect(testInstanceManager.removeInstance(object), null); + }); + }); +} From 4659d4d5d47888ddc8848ec1eaf795d9e0d3df23 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 18 Oct 2021 11:09:21 -0700 Subject: [PATCH 02/11] ingore deprecated and add license --- .../webview_flutter_android/generatePigeons.sh | 4 ++++ .../lib/src/android_webview.pigeon.dart | 4 ++++ .../lib/src/android_webview_api_impls.dart | 1 + 3 files changed, 9 insertions(+) diff --git a/packages/webview_flutter/webview_flutter_android/generatePigeons.sh b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh index d6598017cbda..9ddb854b21ed 100755 --- a/packages/webview_flutter/webview_flutter_android/generatePigeons.sh +++ b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh @@ -1,3 +1,7 @@ +# Copyright 2013 The Flutter Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + flutter pub run pigeon \ --input pigeons/android_webview.dart \ --dart_out lib/src/android_webview.pigeon.dart \ diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart index 930563cb2ced..206b045e900a 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + // Autogenerated from Pigeon (v1.0.7), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart index 9582b79ab4b6..af9d055216ba 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart @@ -410,6 +410,7 @@ class WebViewClientFlutterApiImpl extends WebViewClientFlutterApi { ) { final WebViewClient instance = instanceManager.getInstance(instanceId) as WebViewClient; + // ignore: deprecated_member_use_from_same_package instance.onReceivedError( instanceManager.getInstance(webViewInstanceId) as WebView, errorCode, From df0034a563e3c0249a1ed8ea7f1033759df0be95 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 18 Oct 2021 15:53:17 -0700 Subject: [PATCH 03/11] add tests --- .../generatePigeons.sh | 3 +- .../lib/src/android_webview.dart | 131 +++++++------ .../lib/src/android_webview.pigeon.dart | 4 - .../lib/src/android_webview_api_impls.dart | 27 ++- .../pigeons/android_webview.dart | 2 +- .../test/android_webview_test.dart | 178 ++++++++++++++++++ .../test/test_binary_messenger.dart | 24 +++ 7 files changed, 300 insertions(+), 69 deletions(-) create mode 100644 packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart create mode 100644 packages/webview_flutter/webview_flutter_android/test/test_binary_messenger.dart diff --git a/packages/webview_flutter/webview_flutter_android/generatePigeons.sh b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh index 9ddb854b21ed..6dab4481b600 100755 --- a/packages/webview_flutter/webview_flutter_android/generatePigeons.sh +++ b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh @@ -5,5 +5,4 @@ flutter pub run pigeon \ --input pigeons/android_webview.dart \ --dart_out lib/src/android_webview.pigeon.dart \ ---java_out ./android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java \ ---java_package io.flutter.plugins.webviewflutter +--dart_test_out test/android_webview_test.pigeon.dart diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart index c4b0b445aa18..a1ef8968c86f 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart' show AndroidViewSurface; import 'android_webview_api_impls.dart'; -// TODO(bparrishMines): This can be removed once pigeon supports null values. +// TODO(bparrishMines): This can be removed once pigeon supports null values: https://github.com/flutter/flutter/issues/59118 // Workaround to represent null Strings since pigeon doesn't support null // values. const String _nullStringIdentifier = ''; @@ -31,10 +32,12 @@ const String _nullStringIdentifier = ''; class WebView { /// Constructs a new WebView. WebView({this.useHybridComposition = false}) { - _api.createFromInstance(this); + api.createFromInstance(this); } - static final WebViewHostApiImpl _api = WebViewHostApiImpl(); + /// Pigeon Host Api implementation for [WebView]. + @visibleForTesting + static WebViewHostApiImpl api = WebViewHostApiImpl(); WebViewClient? _currentWebViewClient; DownloadListener? _currentDownloadListener; @@ -60,7 +63,7 @@ class WebView { /// and JavaScript code running inside WebViews. Please refer to [WebView] /// documentation for the debugging guide. The default is false. static Future setWebContentsDebuggingEnabled(bool enabled) { - return _api.setWebContentsDebuggingEnabled(enabled); + return api.setWebContentsDebuggingEnabled(enabled); } /// Loads the given URL with additional HTTP headers, specified as a map from name to value. @@ -71,7 +74,7 @@ class WebView { /// /// Also see compatibility note on [evaluateJavascript]. Future loadUrl(String url, Map headers) { - return _api.loadUrlFromInstance(this, url, headers); + return api.loadUrlFromInstance(this, url, headers); } /// Gets the URL for the current page. @@ -82,34 +85,34 @@ class WebView { /// /// Returns null if no page has been loaded. Future getUrl() async { - final String result = await _api.getUrlFromInstance(this); + final String result = await api.getUrlFromInstance(this); if (result == _nullStringIdentifier) return null; return result; } /// Whether this WebView has a back history item. Future canGoBack() { - return _api.canGoBackFromInstance(this); + return api.canGoBackFromInstance(this); } /// Whether this WebView has a forward history item. Future canGoForward() { - return _api.canGoForwardFromInstance(this); + return api.canGoForwardFromInstance(this); } /// Goes back in the history of this WebView. Future goBack() { - return _api.goBackFromInstance(this); + return api.goBackFromInstance(this); } /// Goes forward in the history of this WebView. Future goForward() { - return _api.goForwardFromInstance(this); + return api.goForwardFromInstance(this); } /// Reloads the current URL. Future reload() { - return _api.reloadFromInstance(this); + return api.reloadFromInstance(this); } /// Clears the resource cache. @@ -117,7 +120,7 @@ class WebView { /// Note that the cache is per-application, so this will clear the cache for /// all WebViews used. Future clearCache(bool includeDiskFiles) { - return _api.clearCacheFromInstance(this, includeDiskFiles); + return api.clearCacheFromInstance(this, includeDiskFiles); } // TODO(bparrishMines): Update documentation once addJavascriptInterface is added. @@ -131,7 +134,7 @@ class WebView { /// navigations like [loadUrl]. For example, global variables and functions /// defined before calling [loadUrl]) will not exist in the loaded page. Future evaluateJavascript(String javascriptString) async { - final String result = await _api.evaluateJavascriptFromInstance( + final String result = await api.evaluateJavascriptFromInstance( this, javascriptString, ); @@ -144,7 +147,7 @@ class WebView { /// /// Returns null if no page has been loaded. Future getTitle() async { - final String result = await _api.getTitleFromInstance(this); + final String result = await api.getTitleFromInstance(this); if (result == _nullStringIdentifier) return null; return result; } @@ -152,13 +155,13 @@ class WebView { // TODO(bparrishMines): Update documentation when onScrollChanged is added. /// Set the scrolled position of your view. Future scrollTo(int x, int y) { - return _api.scrollToFromInstance(this, x, y); + return api.scrollToFromInstance(this, x, y); } // TODO(bparrishMines): Update documentation when onScrollChanged is added. /// Move the scrolled position of your view. Future scrollBy(int x, int y) { - return _api.scrollByFromInstance(this, x, y); + return api.scrollByFromInstance(this, x, y); } /// Return the scrolled left position of this view. @@ -167,7 +170,7 @@ class WebView { /// need to draw any pixels farther left, since those are outside of the frame /// of your view on screen. Future getScrollX() { - return _api.getScrollXFromInstance(this); + return api.getScrollXFromInstance(this); } /// Return the scrolled top position of this view. @@ -176,23 +179,26 @@ class WebView { /// to draw any pixels above it, since those are outside of the frame of your /// view on screen. Future getScrollY() { - return _api.getScrollYFromInstance(this); + return api.getScrollYFromInstance(this); } /// Sets the [WebViewClient] that will receive various notifications and requests. /// /// This will replace the current handler. - Future setWebViewClient(WebViewClient webViewClient) async { + Future setWebViewClient(WebViewClient webViewClient) { final WebViewClient? currentWebViewClient = _currentWebViewClient; + + if (webViewClient == currentWebViewClient) { + return Future.value(); + } + if (currentWebViewClient != null) { - // ignore: unawaited_futures - WebViewClient._api.disposeFromInstance(currentWebViewClient); + WebViewClient.api.disposeFromInstance(currentWebViewClient); } - // ignore: unawaited_futures - WebViewClient._api.createFromInstance(webViewClient); + WebViewClient.api.createFromInstance(webViewClient); _currentWebViewClient = webViewClient; - return _api.setWebViewClientFromInstance(this, webViewClient); + return api.setWebViewClientFromInstance(this, webViewClient); } /// Injects the supplied [JavascriptChannel] into this WebView. @@ -218,11 +224,10 @@ class WebView { /// calling frame's origin from the app side, so the app must not assume that /// the caller is trustworthy unless the app can guarantee that no third party /// content is ever loaded into the WebView even inside an iframe. - Future addJavaScriptChannel(JavaScriptChannel javaScriptChannel) async { - // ignore: unawaited_futures - JavaScriptChannel._api.createFromInstance(javaScriptChannel); + Future addJavaScriptChannel(JavaScriptChannel javaScriptChannel) { + JavaScriptChannel.api.createFromInstance(javaScriptChannel); _javaScriptChannels.add(javaScriptChannel); - return _api.addJavaScriptChannelFromInstance(this, javaScriptChannel); + return api.addJavaScriptChannelFromInstance(this, javaScriptChannel); } /// Removes a previously injected [JavaScriptChannel] from this WebView. @@ -230,9 +235,9 @@ class WebView { /// Note that the removal will not be reflected in JavaScript until the page /// is next (re)loaded. See [addJavaScriptChannel]. Future removeJavaScriptChannel(JavaScriptChannel javaScriptChannel) { - JavaScriptChannel._api.disposeFromInstance(javaScriptChannel); _javaScriptChannels.remove(javaScriptChannel); - return _api.removeJavaScriptChannelFromInstance(this, javaScriptChannel); + api.removeJavaScriptChannelFromInstance(this, javaScriptChannel); + return JavaScriptChannel.api.disposeFromInstance(javaScriptChannel); } /// Registers the interface to be used when content can not be handled by the rendering engine, and should be downloaded instead. @@ -240,13 +245,18 @@ class WebView { /// This will replace the current handler. Future setDownloadListener(DownloadListener listener) { final DownloadListener? currentDownloadListener = _currentDownloadListener; + + if (listener == currentDownloadListener) { + return Future.value(); + } + if (currentDownloadListener != null) { - DownloadListener._api.disposeFromInstance(currentDownloadListener); + DownloadListener.api.disposeFromInstance(currentDownloadListener); } - DownloadListener._api.createFromInstance(listener); + DownloadListener.api.createFromInstance(listener); _currentDownloadListener = listener; - return _api.setDownloadListenerFromInstance(this, listener); + return api.setDownloadListenerFromInstance(this, listener); } } @@ -259,19 +269,21 @@ class WebView { /// Exception. class WebSettings { WebSettings._(this.webView) { - _api.createFromInstance(this); + api.createFromInstance(this); } /// The webView instance this is attached to. final WebView webView; - static final WebSettingsHostApiImpl _api = WebSettingsHostApiImpl(); + /// Pigeon Host Api implementation for [WebSettings]. + @visibleForTesting + static WebSettingsHostApiImpl api = WebSettingsHostApiImpl(); /// Sets whether the DOM storage API is enabled. /// /// The default value is false. Future setDomStorageEnabled(bool flag) { - return _api.setDomStorageEnabledFromInstance(this, flag); + return api.setDomStorageEnabledFromInstance(this, flag); } /// Tells JavaScript to open windows automatically. @@ -279,7 +291,7 @@ class WebSettings { /// This applies to the JavaScript function `window.open()`. The default is /// false. Future setJavaScriptCanOpenWindowsAutomatically(bool flag) { - return _api.setJavaScriptCanOpenWindowsAutomaticallyFromInstance( + return api.setJavaScriptCanOpenWindowsAutomaticallyFromInstance( this, flag, ); @@ -290,14 +302,14 @@ class WebSettings { /// /// The default is false. Future setSupportMultipleWindows(bool support) { - return _api.setSupportZoomFromInstance(this, support); + return api.setSupportZoomFromInstance(this, support); } /// Tells the WebView to enable JavaScript execution. /// /// The default is false. Future setJavaScriptEnabled(bool flag) { - return _api.setJavaScriptEnabledFromInstance(this, flag); + return api.setJavaScriptEnabledFromInstance(this, flag); } /// Sets the WebView's user-agent string. @@ -306,14 +318,14 @@ class WebSettings { /// starting from KITKAT Android version, changing the user-agent while /// loading a web page causes WebView to initiate loading once again. Future setUserAgentString(String userAgentString) { - return _api.setUserAgentStringFromInstance(this, userAgentString); + return api.setUserAgentStringFromInstance(this, userAgentString); } /// Sets whether the WebView requires a user gesture to play media. /// /// The default is true. Future setMediaPlaybackRequiresUserGesture(bool require) { - return _api.setMediaPlaybackRequiresUserGestureFromInstance(this, require); + return api.setMediaPlaybackRequiresUserGestureFromInstance(this, require); } // TODO(bparrishMines): Update documentation when WebView.zoomIn and WebView.zoomOut are added. @@ -324,7 +336,7 @@ class WebSettings { /// /// The default is true. Future setSupportZoom(bool support) { - return _api.setSupportZoomFromInstance(this, support); + return api.setSupportZoomFromInstance(this, support); } /// Sets whether the WebView loads pages in overview mode, that is, zooms out the content to fit on screen by width. @@ -335,7 +347,7 @@ class WebSettings { /// /// The default is false. Future setLoadWithOverviewMode(bool overview) { - return _api.setLoadWithOverviewModeFromInstance(this, overview); + return api.setLoadWithOverviewModeFromInstance(this, overview); } /// Sets whether the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport. @@ -346,7 +358,7 @@ class WebSettings { /// of the width specified in the tag is used. If the page does not contain /// the tag or does not provide a width, then a wide viewport will be used. Future setUseWideViewPort(bool use) { - return _api.setUseWideViewPortFromInstance(this, use); + return api.setUseWideViewPortFromInstance(this, use); } // TODO(bparrishMines): Update documentation when ZoomButtonsController is added. @@ -356,7 +368,7 @@ class WebSettings { /// controls are deprecated in Android so it's recommended to set this to /// false. Future setDisplayZoomControls(bool enabled) { - return _api.setDisplayZoomControlsFromInstance(this, enabled); + return api.setDisplayZoomControlsFromInstance(this, enabled); } // TODO(bparrishMines): Update documentation when ZoomButtonsController is added. @@ -372,7 +384,7 @@ class WebSettings { /// on-screen zoom controls are deprecated in Android so it's recommended to /// disable [setDisplayZoomControls]. Future setBuiltInZoomControls(bool enabled) { - return _api.setBuiltInZoomControlsFromInstance(this, enabled); + return api.setBuiltInZoomControlsFromInstance(this, enabled); } } @@ -383,14 +395,15 @@ abstract class JavaScriptChannel { /// Constructs a [JavaScriptChannel]. JavaScriptChannel(this.channelName); - static final JavaScriptChannelHostApiImpl _api = - JavaScriptChannelHostApiImpl(); + /// Pigeon Host Api implementation for [JavaScriptChannel]. + @visibleForTesting + static JavaScriptChannelHostApiImpl api = JavaScriptChannelHostApiImpl(); /// Used to identify this object to receive messages from javaScript. final String channelName; /// Callback method when javaScript calls `postMessage` on the object instance passed. - void postMessage(String message); + void postMessage(String message) {} } /// Receive various notifications and requests for [WebView]. @@ -446,7 +459,9 @@ abstract class WebViewClient { /// Unsupported URI scheme. static const int errorUnsupportedScheme = 0xfffffff6; - static final WebViewClientHostApiImpl _api = WebViewClientHostApiImpl(); + /// Pigeon Host Api implementation for [WebViewClient]. + @visibleForTesting + static WebViewClientHostApiImpl api = WebViewClientHostApiImpl(); /// Whether loading a url should be overridden. /// @@ -470,7 +485,7 @@ abstract class WebViewClient { /// embedded frame changes, i.e. clicking a link whose target is an iframe, it /// will also not be called for fragment navigations (navigations to /// #fragment_id). - void onPageStarted(WebView webView, String url); + void onPageStarted(WebView webView, String url) {} // TODO(bparrishMines): Update documentation when WebView.postVisualStateCallback is added. /// Notify the host application that a page has finished loading. @@ -478,7 +493,7 @@ abstract class WebViewClient { /// This method is called only for main frame. Receiving an [onPageFinished] /// callback does not guarantee that the next frame drawn by WebView will /// reflect the state of the DOM at this point. - void onPageFinished(WebView webView, String url); + void onPageFinished(WebView webView, String url) {} /// Report web resource loading error to the host application. /// @@ -491,7 +506,7 @@ abstract class WebViewClient { WebView webView, WebResourceRequest request, WebResourceError error, - ); + ) {} /// Report an error to the host application. /// @@ -503,7 +518,7 @@ abstract class WebViewClient { int errorCode, String description, String failingUrl, - ); + ) {} // TODO(bparrishMines): Update documentation once synchronous url handling is supported. /// When a URL is about to be loaded in the current [WebView]. @@ -513,7 +528,7 @@ abstract class WebViewClient { /// [WebViewClient] is provided, setting [shouldOverrideUrlLoading] to true /// causes the current [WebView] to abort loading the URL, while returning /// false causes the [WebView] to continue loading the URL as usual. - void requestLoading(WebView webView, WebResourceRequest request); + void requestLoading(WebView webView, WebResourceRequest request) {} // TODO(bparrishMines): Update documentation once synchronous url handling is supported. /// When a URL is about to be loaded in the current [WebView]. @@ -523,12 +538,14 @@ abstract class WebViewClient { /// [WebViewClient] is provided, setting [shouldOverrideUrlLoading] to true /// causes the current [WebView] to abort loading the URL, while returning /// false causes the [WebView] to continue loading the URL as usual. - void urlLoading(WebView webView, String url); + void urlLoading(WebView webView, String url) {} } /// The interface to be used when content can not be handled by the rendering engine for [WebView], and should be downloaded instead. abstract class DownloadListener { - static final DownloadListenerHostApiImpl _api = DownloadListenerHostApiImpl(); + /// Pigeon Host Api implementation for [DownloadListener]. + @visibleForTesting + static DownloadListenerHostApiImpl api = DownloadListenerHostApiImpl(); /// Notify the host application that a file should be downloaded. void onDownloadStart( diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart index 206b045e900a..930563cb2ced 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart @@ -1,7 +1,3 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - // Autogenerated from Pigeon (v1.0.7), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart index af9d055216ba..121f24b827d9 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:flutter/services.dart'; + import 'android_webview.dart'; import 'android_webview.pigeon.dart'; import 'instance_manager.dart'; @@ -9,7 +11,10 @@ import 'instance_manager.dart'; /// Host api implementation for [WebView]. class WebViewHostApiImpl extends WebViewHostApi { /// Constructs a [WebViewHostApiImpl]. - WebViewHostApiImpl({InstanceManager? instanceManager}) { + WebViewHostApiImpl({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : super(binaryMessenger: binaryMessenger) { this.instanceManager = instanceManager ?? InstanceManager.instance; } @@ -161,7 +166,10 @@ class WebViewHostApiImpl extends WebViewHostApi { /// Host api implementation for [WebSettings]. class WebSettingsHostApiImpl extends WebSettingsHostApi { /// Constructs a [WebSettingsHostApiImpl]. - WebSettingsHostApiImpl({InstanceManager? instanceManager}) { + WebSettingsHostApiImpl({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : super(binaryMessenger: binaryMessenger) { this.instanceManager = instanceManager ?? InstanceManager.instance; } @@ -301,7 +309,10 @@ class WebSettingsHostApiImpl extends WebSettingsHostApi { /// Host api implementation for [JavaScriptChannel]. class JavaScriptChannelHostApiImpl extends JavaScriptChannelHostApi { /// Constructs a [JavaScriptChannelHostApiImpl]. - JavaScriptChannelHostApiImpl({InstanceManager? instanceManager}) { + JavaScriptChannelHostApiImpl({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : super(binaryMessenger: binaryMessenger) { this.instanceManager = instanceManager ?? InstanceManager.instance; } @@ -346,7 +357,10 @@ class JavaScriptChannelFlutterApiImpl extends JavaScriptChannelFlutterApi { /// Host api implementation for [WebViewClient]. class WebViewClientHostApiImpl extends WebViewClientHostApi { /// Constructs a [WebViewClientHostApiImpl]. - WebViewClientHostApiImpl({InstanceManager? instanceManager}) { + WebViewClientHostApiImpl({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : super(binaryMessenger: binaryMessenger) { this.instanceManager = instanceManager ?? InstanceManager.instance; } @@ -484,7 +498,10 @@ class WebViewClientFlutterApiImpl extends WebViewClientFlutterApi { /// Host api implementation for [DownloadListener]. class DownloadListenerHostApiImpl extends DownloadListenerHostApi { /// Constructs a [DownloadListenerHostApiImpl]. - DownloadListenerHostApiImpl({InstanceManager? instanceManager}) { + DownloadListenerHostApiImpl({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : super(binaryMessenger: binaryMessenger) { this.instanceManager = instanceManager ?? InstanceManager.instance; } diff --git a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart index 7efbe17861bf..7aae9da25968 100644 --- a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart +++ b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart @@ -18,7 +18,7 @@ class WebResourceErrorData { String? description; } -@HostApi() +@HostApi(dartHostTestHandler: 'TestWebViewHostApi') abstract class WebViewHostApi { void create(int instanceId, bool useHybridComposition); diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart new file mode 100644 index 000000000000..eaea437f679b --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart @@ -0,0 +1,178 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:webview_flutter_android/src/android_webview.dart'; +import 'package:webview_flutter_android/src/android_webview_api_impls.dart'; +import 'package:webview_flutter_android/src/instance_manager.dart'; + +import 'test_binary_messenger.dart'; + +void main() { + group('Android WebView', () { + group('$WebView', () { + setUp(() { + WebView.api = WebViewHostApiImpl( + instanceManager: InstanceManager(), + binaryMessenger: TestBinaryMessenger(), + ); + }); + + tearDownAll(() { + WebView.api = WebViewHostApiImpl(); + }); + + test('create', () { + final WebView webView = WebView(); + expect(WebView.api.instanceManager.getInstanceId(webView), isNotNull); + }); + }); + + group('$WebSettings', () { + setUp(() { + final InstanceManager instanceManager = InstanceManager(); + final TestBinaryMessenger binaryMessenger = TestBinaryMessenger(); + WebView.api = WebViewHostApiImpl( + instanceManager: instanceManager, + binaryMessenger: binaryMessenger, + ); + WebSettings.api = WebSettingsHostApiImpl( + instanceManager: instanceManager, + binaryMessenger: binaryMessenger, + ); + }); + + test('create', () { + final WebView webView = WebView(); + final WebSettings webSettings = webView.settings; + expect( + WebSettings.api.instanceManager.getInstanceId(webSettings), + isNotNull, + ); + }); + }); + + group('$JavaScriptChannel', () { + setUp(() { + final InstanceManager instanceManager = InstanceManager(); + final TestBinaryMessenger binaryMessenger = TestBinaryMessenger(); + WebView.api = WebViewHostApiImpl( + instanceManager: instanceManager, + binaryMessenger: binaryMessenger, + ); + JavaScriptChannel.api = JavaScriptChannelHostApiImpl( + instanceManager: instanceManager, + binaryMessenger: binaryMessenger, + ); + }); + + test('create', () { + final WebView webView = WebView(); + final JavaScriptChannel channel = TestJavaScriptChannel('myChannel'); + + webView.addJavaScriptChannel(channel); + expect( + JavaScriptChannel.api.instanceManager.getInstanceId(channel), + isNotNull, + ); + + webView.removeJavaScriptChannel(channel); + expect( + JavaScriptChannel.api.instanceManager.getInstanceId(channel), + isNull, + ); + }); + }); + + group('$WebViewClient', () { + setUp(() { + final InstanceManager instanceManager = InstanceManager(); + final TestBinaryMessenger binaryMessenger = TestBinaryMessenger(); + WebView.api = WebViewHostApiImpl( + instanceManager: instanceManager, + binaryMessenger: binaryMessenger, + ); + WebViewClient.api = WebViewClientHostApiImpl( + instanceManager: instanceManager, + binaryMessenger: binaryMessenger, + ); + }); + + test('create', () { + final WebView webView = WebView(); + final WebViewClient webViewClient1 = TestWebViewClient(); + final WebViewClient webViewClient2 = TestWebViewClient(); + + webView.setWebViewClient(webViewClient1); + expect( + WebViewClient.api.instanceManager.getInstanceId(webViewClient1), + isNotNull, + ); + + webView.setWebViewClient(webViewClient2); + expect( + WebViewClient.api.instanceManager.getInstanceId(webViewClient1), + isNull, + ); + }); + }); + + group('$DownloadListener', () { + setUp(() { + final InstanceManager instanceManager = InstanceManager(); + final TestBinaryMessenger binaryMessenger = TestBinaryMessenger(); + WebView.api = WebViewHostApiImpl( + instanceManager: instanceManager, + binaryMessenger: binaryMessenger, + ); + DownloadListener.api = DownloadListenerHostApiImpl( + instanceManager: instanceManager, + binaryMessenger: binaryMessenger, + ); + }); + + test('create', () { + final WebView webView = WebView(); + final DownloadListener downloadListener1 = TestDownloadListener(); + final DownloadListener downloadListener2 = TestDownloadListener(); + + webView.setDownloadListener(downloadListener1); + expect( + DownloadListener.api.instanceManager.getInstanceId(downloadListener1), + isNotNull, + ); + + webView.setDownloadListener(downloadListener2); + expect( + DownloadListener.api.instanceManager.getInstanceId(downloadListener1), + isNull, + ); + }); + }); + }); +} + +class TestJavaScriptChannel extends JavaScriptChannel { + TestJavaScriptChannel(String channelName) : super(channelName); + + @override + void postMessage(String message) { + // Do nothing. + } +} + +class TestWebViewClient extends WebViewClient {} + +class TestDownloadListener extends DownloadListener { + @override + void onDownloadStart( + String url, + String userAgent, + String contentDisposition, + String mimetype, + int contentLength, + ) { + // Do nothing. + } +} diff --git a/packages/webview_flutter/webview_flutter_android/test/test_binary_messenger.dart b/packages/webview_flutter/webview_flutter_android/test/test_binary_messenger.dart new file mode 100644 index 000000000000..c6e983ccd066 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/test/test_binary_messenger.dart @@ -0,0 +1,24 @@ +import 'dart:ui'; + +import 'package:flutter/services.dart'; + +class TestBinaryMessenger implements BinaryMessenger { + @override + Future handlePlatformMessage( + String channel, + ByteData? data, + PlatformMessageResponseCallback? callback, + ) async { + // Do nothing. + } + + @override + Future? send(String channel, ByteData? message) async { + return StandardMessageCodec().encodeMessage({}); + } + + @override + void setMessageHandler(String channel, MessageHandler? handler) { + // Do nothing. + } +} From cf1529c8bbb9d07c71ad71df4fcd55ff80ec1e76 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 18 Oct 2021 15:55:39 -0700 Subject: [PATCH 04/11] add license --- .../webview_flutter_android/test/test_binary_messenger.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/webview_flutter/webview_flutter_android/test/test_binary_messenger.dart b/packages/webview_flutter/webview_flutter_android/test/test_binary_messenger.dart index c6e983ccd066..1aac4d25d251 100644 --- a/packages/webview_flutter/webview_flutter_android/test/test_binary_messenger.dart +++ b/packages/webview_flutter/webview_flutter_android/test/test_binary_messenger.dart @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:ui'; import 'package:flutter/services.dart'; From e5ecf8b775e9614a0878877cbc981a30fbe0f236 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 18 Oct 2021 16:29:53 -0700 Subject: [PATCH 05/11] license again --- .../lib/src/android_webview.pigeon.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart index 930563cb2ced..206b045e900a 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + // Autogenerated from Pigeon (v1.0.7), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name From ef3e70230f4db0b2339fa03889936166495304a7 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 18 Oct 2021 17:10:25 -0700 Subject: [PATCH 06/11] remove test file --- .../webview_flutter/webview_flutter_android/generatePigeons.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_android/generatePigeons.sh b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh index 6dab4481b600..5a009c780505 100755 --- a/packages/webview_flutter/webview_flutter_android/generatePigeons.sh +++ b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh @@ -4,5 +4,4 @@ flutter pub run pigeon \ --input pigeons/android_webview.dart \ ---dart_out lib/src/android_webview.pigeon.dart \ ---dart_test_out test/android_webview_test.pigeon.dart +--dart_out lib/src/android_webview.pigeon.dart From 5010487f53e3b8cdfc39a453ad75f83eae81a8e8 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 19 Oct 2021 14:10:36 -0700 Subject: [PATCH 07/11] use generated flutter api for testing --- .../generatePigeons.sh | 3 +- .../pigeons/android_webview.dart | 8 +- .../test/android_webview.pigeon.dart | 799 ++++++++++++++++++ .../test/android_webview_test.dart | 214 ++++- 4 files changed, 982 insertions(+), 42 deletions(-) create mode 100644 packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart diff --git a/packages/webview_flutter/webview_flutter_android/generatePigeons.sh b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh index 5a009c780505..d866473636cc 100755 --- a/packages/webview_flutter/webview_flutter_android/generatePigeons.sh +++ b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh @@ -4,4 +4,5 @@ flutter pub run pigeon \ --input pigeons/android_webview.dart \ ---dart_out lib/src/android_webview.pigeon.dart +--dart_out lib/src/android_webview.pigeon.dart \ +--dart_test_out test/android_webview.pigeon.dart diff --git a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart index 7aae9da25968..3c9202bddcdf 100644 --- a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart +++ b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart @@ -71,7 +71,7 @@ abstract class WebViewHostApi { void setDownloadListener(int instanceId, int listenerInstanceId); } -@HostApi() +@HostApi(dartHostTestHandler: 'TestWebSettingsHostApi') abstract class WebSettingsHostApi { void create(int instanceId, int webViewInstanceId); @@ -100,7 +100,7 @@ abstract class WebSettingsHostApi { void setBuiltInZoomControls(int instanceId, bool enabled); } -@HostApi() +@HostApi(dartHostTestHandler:'TestJavaScriptChannelHostApi') abstract class JavaScriptChannelHostApi { void create(int instanceId, String channelName); @@ -112,7 +112,7 @@ abstract class JavaScriptChannelFlutterApi { void postMessage(int instanceId, String message); } -@HostApi() +@HostApi(dartHostTestHandler: 'TestWebViewClientHostApi') abstract class WebViewClientHostApi { void create(int instanceId, bool shouldOverrideUrlLoading); @@ -149,7 +149,7 @@ abstract class WebViewClientFlutterApi { void urlLoading(int instanceId, int webViewInstanceId, String url); } -@HostApi() +@HostApi(dartHostTestHandler: 'TestDownloadListenerHostApi') abstract class DownloadListenerHostApi { void create(int instanceId); void dispose(int instanceId); diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart new file mode 100644 index 000000000000..e4fa4b8eb86c --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart @@ -0,0 +1,799 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Autogenerated from Pigeon (v1.0.7), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import +// @dart = 2.12 +import 'dart:async'; +import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; +import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../lib/src/android_webview.pigeon.dart'; + +class _TestWebViewHostApiCodec extends StandardMessageCodec { + const _TestWebViewHostApiCodec(); +} +abstract class TestWebViewHostApi { + static const MessageCodec codec = _TestWebViewHostApiCodec(); + + void create(int instanceId, bool useHybridComposition); + void dispose(int instanceId); + void loadUrl(int instanceId, String url, Map headers); + String getUrl(int instanceId); + bool canGoBack(int instanceId); + bool canGoForward(int instanceId); + void goBack(int instanceId); + void goForward(int instanceId); + void reload(int instanceId); + void clearCache(int instanceId, bool includeDiskFiles); + Future evaluateJavascript(int instanceId, String javascriptString); + String getTitle(int instanceId); + void scrollTo(int instanceId, int x, int y); + void scrollBy(int instanceId, int x, int y); + int getScrollX(int instanceId); + int getScrollY(int instanceId); + void setWebContentsDebuggingEnabled(bool enabled); + void setWebViewClient(int instanceId, int webViewClientInstanceId); + void addJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId); + void removeJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId); + void setDownloadListener(int instanceId, int listenerInstanceId); + static void setup(TestWebViewHostApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.create', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.create was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.create was null, expected non-null int.'); + final bool? arg_useHybridComposition = args[1] as bool?; + assert(arg_useHybridComposition != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.create was null, expected non-null bool.'); + api.create(arg_instanceId!, arg_useHybridComposition!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.dispose', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.dispose was null, expected non-null int.'); + api.dispose(arg_instanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.loadUrl', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null, expected non-null int.'); + final String? arg_url = args[1] as String?; + assert(arg_url != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null, expected non-null String.'); + final Map? arg_headers = args[2] as Map?; + assert(arg_headers != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null, expected non-null Map.'); + api.loadUrl(arg_instanceId!, arg_url!, arg_headers!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getUrl', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getUrl was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getUrl was null, expected non-null int.'); + final String output = api.getUrl(arg_instanceId!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.canGoBack', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoBack was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoBack was null, expected non-null int.'); + final bool output = api.canGoBack(arg_instanceId!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.canGoForward', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoForward was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoForward was null, expected non-null int.'); + final bool output = api.canGoForward(arg_instanceId!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.goBack', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.goBack was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.goBack was null, expected non-null int.'); + api.goBack(arg_instanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.goForward', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.goForward was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.goForward was null, expected non-null int.'); + api.goForward(arg_instanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.reload', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.reload was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.reload was null, expected non-null int.'); + api.reload(arg_instanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.clearCache', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.clearCache was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.clearCache was null, expected non-null int.'); + final bool? arg_includeDiskFiles = args[1] as bool?; + assert(arg_includeDiskFiles != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.clearCache was null, expected non-null bool.'); + api.clearCache(arg_instanceId!, arg_includeDiskFiles!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.evaluateJavascript', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.evaluateJavascript was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.evaluateJavascript was null, expected non-null int.'); + final String? arg_javascriptString = args[1] as String?; + assert(arg_javascriptString != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.evaluateJavascript was null, expected non-null String.'); + final String output = await api.evaluateJavascript(arg_instanceId!, arg_javascriptString!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getTitle', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getTitle was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getTitle was null, expected non-null int.'); + final String output = api.getTitle(arg_instanceId!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.scrollTo', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null, expected non-null int.'); + final int? arg_x = args[1] as int?; + assert(arg_x != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null, expected non-null int.'); + final int? arg_y = args[2] as int?; + assert(arg_y != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null, expected non-null int.'); + api.scrollTo(arg_instanceId!, arg_x!, arg_y!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.scrollBy', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null, expected non-null int.'); + final int? arg_x = args[1] as int?; + assert(arg_x != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null, expected non-null int.'); + final int? arg_y = args[2] as int?; + assert(arg_y != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null, expected non-null int.'); + api.scrollBy(arg_instanceId!, arg_x!, arg_y!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getScrollX', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollX was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollX was null, expected non-null int.'); + final int output = api.getScrollX(arg_instanceId!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getScrollY', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollY was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollY was null, expected non-null int.'); + final int output = api.getScrollY(arg_instanceId!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled was null.'); + final List args = (message as List?)!; + final bool? arg_enabled = args[0] as bool?; + assert(arg_enabled != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled was null, expected non-null bool.'); + api.setWebContentsDebuggingEnabled(arg_enabled!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setWebViewClient', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebViewClient was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebViewClient was null, expected non-null int.'); + final int? arg_webViewClientInstanceId = args[1] as int?; + assert(arg_webViewClientInstanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebViewClient was null, expected non-null int.'); + api.setWebViewClient(arg_instanceId!, arg_webViewClientInstanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel was null, expected non-null int.'); + final int? arg_javaScriptChannelInstanceId = args[1] as int?; + assert(arg_javaScriptChannelInstanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel was null, expected non-null int.'); + api.addJavaScriptChannel(arg_instanceId!, arg_javaScriptChannelInstanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel was null, expected non-null int.'); + final int? arg_javaScriptChannelInstanceId = args[1] as int?; + assert(arg_javaScriptChannelInstanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel was null, expected non-null int.'); + api.removeJavaScriptChannel(arg_instanceId!, arg_javaScriptChannelInstanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setDownloadListener', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setDownloadListener was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setDownloadListener was null, expected non-null int.'); + final int? arg_listenerInstanceId = args[1] as int?; + assert(arg_listenerInstanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setDownloadListener was null, expected non-null int.'); + api.setDownloadListener(arg_instanceId!, arg_listenerInstanceId!); + return {}; + }); + } + } + } +} + +class _TestWebSettingsHostApiCodec extends StandardMessageCodec { + const _TestWebSettingsHostApiCodec(); +} +abstract class TestWebSettingsHostApi { + static const MessageCodec codec = _TestWebSettingsHostApiCodec(); + + void create(int instanceId, int webViewInstanceId); + void dispose(int instanceId); + void setDomStorageEnabled(int instanceId, bool flag); + void setJavaScriptCanOpenWindowsAutomatically(int instanceId, bool flag); + void setSupportMultipleWindows(int instanceId, bool support); + void setJavaScriptEnabled(int instanceId, bool flag); + void setUserAgentString(int instanceId, String userAgentString); + void setMediaPlaybackRequiresUserGesture(int instanceId, bool require); + void setSupportZoom(int instanceId, bool support); + void setLoadWithOverviewMode(int instanceId, bool overview); + void setUseWideViewPort(int instanceId, bool use); + void setDisplayZoomControls(int instanceId, bool enabled); + void setBuiltInZoomControls(int instanceId, bool enabled); + static void setup(TestWebSettingsHostApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.create', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.create was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.create was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.create was null, expected non-null int.'); + api.create(arg_instanceId!, arg_webViewInstanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.dispose', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.dispose was null, expected non-null int.'); + api.dispose(arg_instanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled was null, expected non-null int.'); + final bool? arg_flag = args[1] as bool?; + assert(arg_flag != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled was null, expected non-null bool.'); + api.setDomStorageEnabled(arg_instanceId!, arg_flag!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically was null, expected non-null int.'); + final bool? arg_flag = args[1] as bool?; + assert(arg_flag != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically was null, expected non-null bool.'); + api.setJavaScriptCanOpenWindowsAutomatically(arg_instanceId!, arg_flag!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows was null, expected non-null int.'); + final bool? arg_support = args[1] as bool?; + assert(arg_support != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows was null, expected non-null bool.'); + api.setSupportMultipleWindows(arg_instanceId!, arg_support!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled was null, expected non-null int.'); + final bool? arg_flag = args[1] as bool?; + assert(arg_flag != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled was null, expected non-null bool.'); + api.setJavaScriptEnabled(arg_instanceId!, arg_flag!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString was null, expected non-null int.'); + final String? arg_userAgentString = args[1] as String?; + assert(arg_userAgentString != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString was null, expected non-null String.'); + api.setUserAgentString(arg_instanceId!, arg_userAgentString!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture was null, expected non-null int.'); + final bool? arg_require = args[1] as bool?; + assert(arg_require != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture was null, expected non-null bool.'); + api.setMediaPlaybackRequiresUserGesture(arg_instanceId!, arg_require!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom was null, expected non-null int.'); + final bool? arg_support = args[1] as bool?; + assert(arg_support != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom was null, expected non-null bool.'); + api.setSupportZoom(arg_instanceId!, arg_support!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode was null, expected non-null int.'); + final bool? arg_overview = args[1] as bool?; + assert(arg_overview != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode was null, expected non-null bool.'); + api.setLoadWithOverviewMode(arg_instanceId!, arg_overview!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort was null, expected non-null int.'); + final bool? arg_use = args[1] as bool?; + assert(arg_use != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort was null, expected non-null bool.'); + api.setUseWideViewPort(arg_instanceId!, arg_use!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls was null, expected non-null int.'); + final bool? arg_enabled = args[1] as bool?; + assert(arg_enabled != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls was null, expected non-null bool.'); + api.setDisplayZoomControls(arg_instanceId!, arg_enabled!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls was null, expected non-null int.'); + final bool? arg_enabled = args[1] as bool?; + assert(arg_enabled != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls was null, expected non-null bool.'); + api.setBuiltInZoomControls(arg_instanceId!, arg_enabled!); + return {}; + }); + } + } + } +} + +class _TestJavaScriptChannelHostApiCodec extends StandardMessageCodec { + const _TestJavaScriptChannelHostApiCodec(); +} +abstract class TestJavaScriptChannelHostApi { + static const MessageCodec codec = _TestJavaScriptChannelHostApiCodec(); + + void create(int instanceId, String channelName); + void dispose(int instanceId); + static void setup(TestJavaScriptChannelHostApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.JavaScriptChannelHostApi.create', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.create was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.create was null, expected non-null int.'); + final String? arg_channelName = args[1] as String?; + assert(arg_channelName != null, 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.create was null, expected non-null String.'); + api.create(arg_instanceId!, arg_channelName!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.JavaScriptChannelHostApi.dispose', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.dispose was null, expected non-null int.'); + api.dispose(arg_instanceId!); + return {}; + }); + } + } + } +} + +class _TestWebViewClientHostApiCodec extends StandardMessageCodec { + const _TestWebViewClientHostApiCodec(); +} +abstract class TestWebViewClientHostApi { + static const MessageCodec codec = _TestWebViewClientHostApiCodec(); + + void create(int instanceId, bool shouldOverrideUrlLoading); + void dispose(int instanceId); + static void setup(TestWebViewClientHostApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientHostApi.create', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewClientHostApi.create was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewClientHostApi.create was null, expected non-null int.'); + final bool? arg_shouldOverrideUrlLoading = args[1] as bool?; + assert(arg_shouldOverrideUrlLoading != null, 'Argument for dev.flutter.pigeon.WebViewClientHostApi.create was null, expected non-null bool.'); + api.create(arg_instanceId!, arg_shouldOverrideUrlLoading!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientHostApi.dispose', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.WebViewClientHostApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewClientHostApi.dispose was null, expected non-null int.'); + api.dispose(arg_instanceId!); + return {}; + }); + } + } + } +} + +class _TestDownloadListenerHostApiCodec extends StandardMessageCodec { + const _TestDownloadListenerHostApiCodec(); +} +abstract class TestDownloadListenerHostApi { + static const MessageCodec codec = _TestDownloadListenerHostApiCodec(); + + void create(int instanceId); + void dispose(int instanceId); + static void setup(TestDownloadListenerHostApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.DownloadListenerHostApi.create', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.create was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.create was null, expected non-null int.'); + api.create(arg_instanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.DownloadListenerHostApi.dispose', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.dispose was null, expected non-null int.'); + api.dispose(arg_instanceId!); + return {}; + }); + } + } + } +} diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart index eaea437f679b..b3d0e998ce84 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart @@ -7,20 +7,19 @@ import 'package:webview_flutter_android/src/android_webview.dart'; import 'package:webview_flutter_android/src/android_webview_api_impls.dart'; import 'package:webview_flutter_android/src/instance_manager.dart'; -import 'test_binary_messenger.dart'; +import 'android_webview.pigeon.dart'; void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + group('Android WebView', () { group('$WebView', () { - setUp(() { - WebView.api = WebViewHostApiImpl( - instanceManager: InstanceManager(), - binaryMessenger: TestBinaryMessenger(), - ); + setUpAll(() { + TestWebViewHostApi.setup(TestWebViewHostApiImpl()); }); - tearDownAll(() { - WebView.api = WebViewHostApiImpl(); + setUp(() { + WebView.api = WebViewHostApiImpl(instanceManager: InstanceManager()); }); test('create', () { @@ -30,16 +29,16 @@ void main() { }); group('$WebSettings', () { + setUpAll(() { + TestWebViewHostApi.setup(TestWebViewHostApiImpl()); + TestWebSettingsHostApi.setup(TestWebSettingsHostApiImpl()); + }); + setUp(() { final InstanceManager instanceManager = InstanceManager(); - final TestBinaryMessenger binaryMessenger = TestBinaryMessenger(); - WebView.api = WebViewHostApiImpl( - instanceManager: instanceManager, - binaryMessenger: binaryMessenger, - ); + WebView.api = WebViewHostApiImpl(instanceManager: instanceManager); WebSettings.api = WebSettingsHostApiImpl( instanceManager: instanceManager, - binaryMessenger: binaryMessenger, ); }); @@ -54,16 +53,16 @@ void main() { }); group('$JavaScriptChannel', () { + setUpAll(() { + TestWebViewHostApi.setup(TestWebViewHostApiImpl()); + TestJavaScriptChannelHostApi.setup(TestJavaScriptChannelHostApiImpl()); + }); + setUp(() { final InstanceManager instanceManager = InstanceManager(); - final TestBinaryMessenger binaryMessenger = TestBinaryMessenger(); - WebView.api = WebViewHostApiImpl( - instanceManager: instanceManager, - binaryMessenger: binaryMessenger, - ); + WebView.api = WebViewHostApiImpl(instanceManager: instanceManager); JavaScriptChannel.api = JavaScriptChannelHostApiImpl( instanceManager: instanceManager, - binaryMessenger: binaryMessenger, ); }); @@ -86,16 +85,16 @@ void main() { }); group('$WebViewClient', () { + setUpAll(() { + TestWebViewHostApi.setup(TestWebViewHostApiImpl()); + TestWebViewClientHostApi.setup(TestWebViewClientHostApiImpl()); + }); + setUp(() { final InstanceManager instanceManager = InstanceManager(); - final TestBinaryMessenger binaryMessenger = TestBinaryMessenger(); - WebView.api = WebViewHostApiImpl( - instanceManager: instanceManager, - binaryMessenger: binaryMessenger, - ); + WebView.api = WebViewHostApiImpl(instanceManager: instanceManager); WebViewClient.api = WebViewClientHostApiImpl( instanceManager: instanceManager, - binaryMessenger: binaryMessenger, ); }); @@ -119,16 +118,16 @@ void main() { }); group('$DownloadListener', () { + setUpAll(() { + TestWebViewHostApi.setup(TestWebViewHostApiImpl()); + TestDownloadListenerHostApi.setup(TestDownloadListenerHostApiImpl()); + }); + setUp(() { final InstanceManager instanceManager = InstanceManager(); - final TestBinaryMessenger binaryMessenger = TestBinaryMessenger(); - WebView.api = WebViewHostApiImpl( - instanceManager: instanceManager, - binaryMessenger: binaryMessenger, - ); + WebView.api = WebViewHostApiImpl(instanceManager: instanceManager); DownloadListener.api = DownloadListenerHostApiImpl( instanceManager: instanceManager, - binaryMessenger: binaryMessenger, ); }); @@ -157,9 +156,7 @@ class TestJavaScriptChannel extends JavaScriptChannel { TestJavaScriptChannel(String channelName) : super(channelName); @override - void postMessage(String message) { - // Do nothing. - } + void postMessage(String message) {} } class TestWebViewClient extends WebViewClient {} @@ -172,7 +169,150 @@ class TestDownloadListener extends DownloadListener { String contentDisposition, String mimetype, int contentLength, - ) { - // Do nothing. + ) {} +} + +class TestWebViewHostApiImpl extends TestWebViewHostApi { + @override + void addJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId) {} + + @override + bool canGoBack(int instanceId) { + throw UnimplementedError(); + } + + @override + bool canGoForward(int instanceId) { + throw UnimplementedError(); + } + + @override + void clearCache(int instanceId, bool includeDiskFiles) {} + + @override + void create(int instanceId, bool useHybridComposition) {} + + @override + void dispose(int instanceId) {} + + @override + Future evaluateJavascript(int instanceId, String javascriptString) { + throw UnimplementedError(); + } + + @override + int getScrollX(int instanceId) { + throw UnimplementedError(); + } + + @override + int getScrollY(int instanceId) { + throw UnimplementedError(); + } + + @override + String getTitle(int instanceId) { + throw UnimplementedError(); + } + + @override + String getUrl(int instanceId) { + throw UnimplementedError(); } + + @override + void goBack(int instanceId) {} + + @override + void goForward(int instanceId) {} + + @override + void loadUrl(int instanceId, String url, Map headers) {} + + @override + void reload(int instanceId) {} + + @override + void removeJavaScriptChannel( + int instanceId, int javaScriptChannelInstanceId) {} + + @override + void scrollBy(int instanceId, int x, int y) {} + + @override + void scrollTo(int instanceId, int x, int y) {} + + @override + void setDownloadListener(int instanceId, int listenerInstanceId) {} + + @override + void setWebContentsDebuggingEnabled(bool enabled) {} + + @override + void setWebViewClient(int instanceId, int webViewClientInstanceId) {} +} + +class TestWebSettingsHostApiImpl extends TestWebSettingsHostApi { + @override + void create(int instanceId, int webViewInstanceId) {} + + @override + void dispose(int instanceId) {} + + @override + void setBuiltInZoomControls(int instanceId, bool enabled) {} + + @override + void setDisplayZoomControls(int instanceId, bool enabled) {} + + @override + void setDomStorageEnabled(int instanceId, bool flag) {} + + @override + void setJavaScriptCanOpenWindowsAutomatically(int instanceId, bool flag) {} + + @override + void setJavaScriptEnabled(int instanceId, bool flag) {} + + @override + void setLoadWithOverviewMode(int instanceId, bool overview) {} + + @override + void setMediaPlaybackRequiresUserGesture(int instanceId, bool require) {} + + @override + void setSupportMultipleWindows(int instanceId, bool support) {} + + @override + void setSupportZoom(int instanceId, bool support) {} + + @override + void setUseWideViewPort(int instanceId, bool use) {} + + @override + void setUserAgentString(int instanceId, String userAgentString) {} +} + +class TestJavaScriptChannelHostApiImpl extends TestJavaScriptChannelHostApi { + @override + void create(int instanceId, String channelName) {} + + @override + void dispose(int instanceId) {} +} + +class TestWebViewClientHostApiImpl extends TestWebViewClientHostApi { + @override + void create(int instanceId, bool shouldOverrideUrlLoading) {} + + @override + void dispose(int instanceId) {} +} + +class TestDownloadListenerHostApiImpl extends TestDownloadListenerHostApi { + @override + void create(int instanceId) {} + + @override + void dispose(int instanceId) {} } From 2e1b590f02c1aa41e04018d7a50403e5225f14c9 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 19 Oct 2021 14:52:19 -0700 Subject: [PATCH 08/11] formatting and remove circle reference --- .../lib/src/android_webview.dart | 14 +- .../lib/src/android_webview_api_impls.dart | 4 +- .../pigeons/android_webview.dart | 2 +- .../test/android_webview.pigeon.dart | 371 ++++++++++++------ .../test/android_webview_test.dart | 2 +- 5 files changed, 261 insertions(+), 132 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart index a1ef8968c86f..a7984054fe06 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart @@ -55,7 +55,7 @@ class WebView { final bool useHybridComposition; /// The [WebSettings] object used to control the settings for this WebView. - late final WebSettings settings = WebSettings._(this); + late final WebSettings settings = WebSettings(this); /// Enables debugging of web contents (HTML / CSS / JavaScript) loaded into any WebViews of this application. /// @@ -268,13 +268,15 @@ class WebView { /// WebView has been destroyed, any method call on [WebSettings] will throw an /// Exception. class WebSettings { - WebSettings._(this.webView) { - api.createFromInstance(this); + /// Constructs a [WebSettings]. + /// + /// This constructor is only used for testing. An instance should be obtained + /// with [WebView.settings]. + @visibleForTesting + WebSettings(WebView webView) { + api.createFromInstance(this, webView); } - /// The webView instance this is attached to. - final WebView webView; - /// Pigeon Host Api implementation for [WebSettings]. @visibleForTesting static WebSettingsHostApiImpl api = WebSettingsHostApiImpl(); diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart index 121f24b827d9..83621e02cb16 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart @@ -177,12 +177,12 @@ class WebSettingsHostApiImpl extends WebSettingsHostApi { late final InstanceManager instanceManager; /// Helper method to convert instances ids to objects. - Future createFromInstance(WebSettings instance) async { + Future createFromInstance(WebSettings instance, WebView webView) async { final int? instanceId = instanceManager.tryAddInstance(instance); if (instanceId != null) { return create( instanceId, - instanceManager.getInstanceId(instance.webView)!, + instanceManager.getInstanceId(webView)!, ); } } diff --git a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart index 3c9202bddcdf..375f3ced67f2 100644 --- a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart +++ b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart @@ -100,7 +100,7 @@ abstract class WebSettingsHostApi { void setBuiltInZoomControls(int instanceId, bool enabled); } -@HostApi(dartHostTestHandler:'TestJavaScriptChannelHostApi') +@HostApi(dartHostTestHandler: 'TestJavaScriptChannelHostApi') abstract class JavaScriptChannelHostApi { void create(int instanceId, String channelName); diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart index e4fa4b8eb86c..9f6996950b3f 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart @@ -17,6 +17,7 @@ import '../lib/src/android_webview.pigeon.dart'; class _TestWebViewHostApiCodec extends StandardMessageCodec { const _TestWebViewHostApiCodec(); } + abstract class TestWebViewHostApi { static const MessageCodec codec = _TestWebViewHostApiCodec(); @@ -49,12 +50,15 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.create was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.create was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.create was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.create was null, expected non-null int.'); final bool? arg_useHybridComposition = args[1] as bool?; - assert(arg_useHybridComposition != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.create was null, expected non-null bool.'); + assert(arg_useHybridComposition != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.create was null, expected non-null bool.'); api.create(arg_instanceId!, arg_useHybridComposition!); return {}; }); @@ -67,10 +71,12 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.dispose was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.dispose was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.dispose was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.dispose was null, expected non-null int.'); api.dispose(arg_instanceId!); return {}; }); @@ -83,14 +89,19 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null, expected non-null int.'); final String? arg_url = args[1] as String?; - assert(arg_url != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null, expected non-null String.'); - final Map? arg_headers = args[2] as Map?; - assert(arg_headers != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null, expected non-null Map.'); + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null, expected non-null String.'); + final Map? arg_headers = + args[2] as Map?; + assert(arg_headers != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null, expected non-null Map.'); api.loadUrl(arg_instanceId!, arg_url!, arg_headers!); return {}; }); @@ -103,10 +114,12 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getUrl was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getUrl was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getUrl was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getUrl was null, expected non-null int.'); final String output = api.getUrl(arg_instanceId!); return {'result': output}; }); @@ -119,10 +132,12 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoBack was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoBack was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoBack was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoBack was null, expected non-null int.'); final bool output = api.canGoBack(arg_instanceId!); return {'result': output}; }); @@ -135,10 +150,12 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoForward was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoForward was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoForward was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoForward was null, expected non-null int.'); final bool output = api.canGoForward(arg_instanceId!); return {'result': output}; }); @@ -151,10 +168,12 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.goBack was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.goBack was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.goBack was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.goBack was null, expected non-null int.'); api.goBack(arg_instanceId!); return {}; }); @@ -167,10 +186,12 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.goForward was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.goForward was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.goForward was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.goForward was null, expected non-null int.'); api.goForward(arg_instanceId!); return {}; }); @@ -183,10 +204,12 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.reload was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.reload was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.reload was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.reload was null, expected non-null int.'); api.reload(arg_instanceId!); return {}; }); @@ -199,12 +222,15 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.clearCache was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.clearCache was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.clearCache was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.clearCache was null, expected non-null int.'); final bool? arg_includeDiskFiles = args[1] as bool?; - assert(arg_includeDiskFiles != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.clearCache was null, expected non-null bool.'); + assert(arg_includeDiskFiles != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.clearCache was null, expected non-null bool.'); api.clearCache(arg_instanceId!, arg_includeDiskFiles!); return {}; }); @@ -217,13 +243,17 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.evaluateJavascript was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.evaluateJavascript was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.evaluateJavascript was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.evaluateJavascript was null, expected non-null int.'); final String? arg_javascriptString = args[1] as String?; - assert(arg_javascriptString != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.evaluateJavascript was null, expected non-null String.'); - final String output = await api.evaluateJavascript(arg_instanceId!, arg_javascriptString!); + assert(arg_javascriptString != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.evaluateJavascript was null, expected non-null String.'); + final String output = await api.evaluateJavascript( + arg_instanceId!, arg_javascriptString!); return {'result': output}; }); } @@ -235,10 +265,12 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getTitle was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getTitle was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getTitle was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getTitle was null, expected non-null int.'); final String output = api.getTitle(arg_instanceId!); return {'result': output}; }); @@ -251,14 +283,18 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null, expected non-null int.'); final int? arg_x = args[1] as int?; - assert(arg_x != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null, expected non-null int.'); + assert(arg_x != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null, expected non-null int.'); final int? arg_y = args[2] as int?; - assert(arg_y != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null, expected non-null int.'); + assert(arg_y != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null, expected non-null int.'); api.scrollTo(arg_instanceId!, arg_x!, arg_y!); return {}; }); @@ -271,14 +307,18 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null, expected non-null int.'); final int? arg_x = args[1] as int?; - assert(arg_x != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null, expected non-null int.'); + assert(arg_x != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null, expected non-null int.'); final int? arg_y = args[2] as int?; - assert(arg_y != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null, expected non-null int.'); + assert(arg_y != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null, expected non-null int.'); api.scrollBy(arg_instanceId!, arg_x!, arg_y!); return {}; }); @@ -291,10 +331,12 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollX was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollX was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollX was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollX was null, expected non-null int.'); final int output = api.getScrollX(arg_instanceId!); return {'result': output}; }); @@ -307,10 +349,12 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollY was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollY was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollY was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollY was null, expected non-null int.'); final int output = api.getScrollY(arg_instanceId!); return {'result': output}; }); @@ -318,15 +362,18 @@ abstract class TestWebViewHostApi { } { const BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled', codec); + 'dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled', + codec); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled was null.'); final List args = (message as List?)!; final bool? arg_enabled = args[0] as bool?; - assert(arg_enabled != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled was null, expected non-null bool.'); + assert(arg_enabled != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled was null, expected non-null bool.'); api.setWebContentsDebuggingEnabled(arg_enabled!); return {}; }); @@ -339,12 +386,15 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebViewClient was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebViewClient was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebViewClient was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebViewClient was null, expected non-null int.'); final int? arg_webViewClientInstanceId = args[1] as int?; - assert(arg_webViewClientInstanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebViewClient was null, expected non-null int.'); + assert(arg_webViewClientInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebViewClient was null, expected non-null int.'); api.setWebViewClient(arg_instanceId!, arg_webViewClientInstanceId!); return {}; }); @@ -357,13 +407,17 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel was null, expected non-null int.'); final int? arg_javaScriptChannelInstanceId = args[1] as int?; - assert(arg_javaScriptChannelInstanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel was null, expected non-null int.'); - api.addJavaScriptChannel(arg_instanceId!, arg_javaScriptChannelInstanceId!); + assert(arg_javaScriptChannelInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel was null, expected non-null int.'); + api.addJavaScriptChannel( + arg_instanceId!, arg_javaScriptChannelInstanceId!); return {}; }); } @@ -375,13 +429,17 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel was null, expected non-null int.'); final int? arg_javaScriptChannelInstanceId = args[1] as int?; - assert(arg_javaScriptChannelInstanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel was null, expected non-null int.'); - api.removeJavaScriptChannel(arg_instanceId!, arg_javaScriptChannelInstanceId!); + assert(arg_javaScriptChannelInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel was null, expected non-null int.'); + api.removeJavaScriptChannel( + arg_instanceId!, arg_javaScriptChannelInstanceId!); return {}; }); } @@ -393,12 +451,15 @@ abstract class TestWebViewHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setDownloadListener was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setDownloadListener was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setDownloadListener was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setDownloadListener was null, expected non-null int.'); final int? arg_listenerInstanceId = args[1] as int?; - assert(arg_listenerInstanceId != null, 'Argument for dev.flutter.pigeon.WebViewHostApi.setDownloadListener was null, expected non-null int.'); + assert(arg_listenerInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setDownloadListener was null, expected non-null int.'); api.setDownloadListener(arg_instanceId!, arg_listenerInstanceId!); return {}; }); @@ -410,6 +471,7 @@ abstract class TestWebViewHostApi { class _TestWebSettingsHostApiCodec extends StandardMessageCodec { const _TestWebSettingsHostApiCodec(); } + abstract class TestWebSettingsHostApi { static const MessageCodec codec = _TestWebSettingsHostApiCodec(); @@ -434,12 +496,15 @@ abstract class TestWebSettingsHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.create was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.create was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.create was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.create was null, expected non-null int.'); final int? arg_webViewInstanceId = args[1] as int?; - assert(arg_webViewInstanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.create was null, expected non-null int.'); + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.create was null, expected non-null int.'); api.create(arg_instanceId!, arg_webViewInstanceId!); return {}; }); @@ -452,10 +517,12 @@ abstract class TestWebSettingsHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.dispose was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.dispose was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.dispose was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.dispose was null, expected non-null int.'); api.dispose(arg_instanceId!); return {}; }); @@ -468,12 +535,15 @@ abstract class TestWebSettingsHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled was null, expected non-null int.'); final bool? arg_flag = args[1] as bool?; - assert(arg_flag != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled was null, expected non-null bool.'); + assert(arg_flag != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled was null, expected non-null bool.'); api.setDomStorageEnabled(arg_instanceId!, arg_flag!); return {}; }); @@ -481,35 +551,44 @@ abstract class TestWebSettingsHostApi { } { const BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically', codec); + 'dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically', + codec); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically was null, expected non-null int.'); final bool? arg_flag = args[1] as bool?; - assert(arg_flag != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically was null, expected non-null bool.'); - api.setJavaScriptCanOpenWindowsAutomatically(arg_instanceId!, arg_flag!); + assert(arg_flag != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically was null, expected non-null bool.'); + api.setJavaScriptCanOpenWindowsAutomatically( + arg_instanceId!, arg_flag!); return {}; }); } } { const BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows', codec); + 'dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows', + codec); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows was null, expected non-null int.'); final bool? arg_support = args[1] as bool?; - assert(arg_support != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows was null, expected non-null bool.'); + assert(arg_support != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows was null, expected non-null bool.'); api.setSupportMultipleWindows(arg_instanceId!, arg_support!); return {}; }); @@ -522,12 +601,15 @@ abstract class TestWebSettingsHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled was null, expected non-null int.'); final bool? arg_flag = args[1] as bool?; - assert(arg_flag != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled was null, expected non-null bool.'); + assert(arg_flag != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled was null, expected non-null bool.'); api.setJavaScriptEnabled(arg_instanceId!, arg_flag!); return {}; }); @@ -540,12 +622,15 @@ abstract class TestWebSettingsHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString was null, expected non-null int.'); final String? arg_userAgentString = args[1] as String?; - assert(arg_userAgentString != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString was null, expected non-null String.'); + assert(arg_userAgentString != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString was null, expected non-null String.'); api.setUserAgentString(arg_instanceId!, arg_userAgentString!); return {}; }); @@ -553,18 +638,23 @@ abstract class TestWebSettingsHostApi { } { const BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture', codec); + 'dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture', + codec); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture was null, expected non-null int.'); final bool? arg_require = args[1] as bool?; - assert(arg_require != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture was null, expected non-null bool.'); - api.setMediaPlaybackRequiresUserGesture(arg_instanceId!, arg_require!); + assert(arg_require != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture was null, expected non-null bool.'); + api.setMediaPlaybackRequiresUserGesture( + arg_instanceId!, arg_require!); return {}; }); } @@ -576,12 +666,15 @@ abstract class TestWebSettingsHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom was null, expected non-null int.'); final bool? arg_support = args[1] as bool?; - assert(arg_support != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom was null, expected non-null bool.'); + assert(arg_support != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom was null, expected non-null bool.'); api.setSupportZoom(arg_instanceId!, arg_support!); return {}; }); @@ -589,17 +682,21 @@ abstract class TestWebSettingsHostApi { } { const BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode', codec); + 'dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode', + codec); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode was null, expected non-null int.'); final bool? arg_overview = args[1] as bool?; - assert(arg_overview != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode was null, expected non-null bool.'); + assert(arg_overview != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode was null, expected non-null bool.'); api.setLoadWithOverviewMode(arg_instanceId!, arg_overview!); return {}; }); @@ -612,12 +709,15 @@ abstract class TestWebSettingsHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort was null, expected non-null int.'); final bool? arg_use = args[1] as bool?; - assert(arg_use != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort was null, expected non-null bool.'); + assert(arg_use != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort was null, expected non-null bool.'); api.setUseWideViewPort(arg_instanceId!, arg_use!); return {}; }); @@ -625,17 +725,21 @@ abstract class TestWebSettingsHostApi { } { const BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls', codec); + 'dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls', + codec); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls was null, expected non-null int.'); final bool? arg_enabled = args[1] as bool?; - assert(arg_enabled != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls was null, expected non-null bool.'); + assert(arg_enabled != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls was null, expected non-null bool.'); api.setDisplayZoomControls(arg_instanceId!, arg_enabled!); return {}; }); @@ -643,17 +747,21 @@ abstract class TestWebSettingsHostApi { } { const BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls', codec); + 'dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls', + codec); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls was null, expected non-null int.'); final bool? arg_enabled = args[1] as bool?; - assert(arg_enabled != null, 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls was null, expected non-null bool.'); + assert(arg_enabled != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls was null, expected non-null bool.'); api.setBuiltInZoomControls(arg_instanceId!, arg_enabled!); return {}; }); @@ -665,8 +773,10 @@ abstract class TestWebSettingsHostApi { class _TestJavaScriptChannelHostApiCodec extends StandardMessageCodec { const _TestJavaScriptChannelHostApiCodec(); } + abstract class TestJavaScriptChannelHostApi { - static const MessageCodec codec = _TestJavaScriptChannelHostApiCodec(); + static const MessageCodec codec = + _TestJavaScriptChannelHostApiCodec(); void create(int instanceId, String channelName); void dispose(int instanceId); @@ -678,12 +788,15 @@ abstract class TestJavaScriptChannelHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.create was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.create was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.create was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.create was null, expected non-null int.'); final String? arg_channelName = args[1] as String?; - assert(arg_channelName != null, 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.create was null, expected non-null String.'); + assert(arg_channelName != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.create was null, expected non-null String.'); api.create(arg_instanceId!, arg_channelName!); return {}; }); @@ -696,10 +809,12 @@ abstract class TestJavaScriptChannelHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.dispose was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.dispose was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.dispose was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.dispose was null, expected non-null int.'); api.dispose(arg_instanceId!); return {}; }); @@ -711,6 +826,7 @@ abstract class TestJavaScriptChannelHostApi { class _TestWebViewClientHostApiCodec extends StandardMessageCodec { const _TestWebViewClientHostApiCodec(); } + abstract class TestWebViewClientHostApi { static const MessageCodec codec = _TestWebViewClientHostApiCodec(); @@ -724,12 +840,15 @@ abstract class TestWebViewClientHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewClientHostApi.create was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientHostApi.create was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewClientHostApi.create was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientHostApi.create was null, expected non-null int.'); final bool? arg_shouldOverrideUrlLoading = args[1] as bool?; - assert(arg_shouldOverrideUrlLoading != null, 'Argument for dev.flutter.pigeon.WebViewClientHostApi.create was null, expected non-null bool.'); + assert(arg_shouldOverrideUrlLoading != null, + 'Argument for dev.flutter.pigeon.WebViewClientHostApi.create was null, expected non-null bool.'); api.create(arg_instanceId!, arg_shouldOverrideUrlLoading!); return {}; }); @@ -742,10 +861,12 @@ abstract class TestWebViewClientHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.WebViewClientHostApi.dispose was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientHostApi.dispose was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WebViewClientHostApi.dispose was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientHostApi.dispose was null, expected non-null int.'); api.dispose(arg_instanceId!); return {}; }); @@ -757,8 +878,10 @@ abstract class TestWebViewClientHostApi { class _TestDownloadListenerHostApiCodec extends StandardMessageCodec { const _TestDownloadListenerHostApiCodec(); } + abstract class TestDownloadListenerHostApi { - static const MessageCodec codec = _TestDownloadListenerHostApiCodec(); + static const MessageCodec codec = + _TestDownloadListenerHostApiCodec(); void create(int instanceId); void dispose(int instanceId); @@ -770,10 +893,12 @@ abstract class TestDownloadListenerHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.create was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.create was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.create was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.create was null, expected non-null int.'); api.create(arg_instanceId!); return {}; }); @@ -786,10 +911,12 @@ abstract class TestDownloadListenerHostApi { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.dispose was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.dispose was null.'); final List args = (message as List?)!; final int? arg_instanceId = args[0] as int?; - assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.dispose was null, expected non-null int.'); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.dispose was null, expected non-null int.'); api.dispose(arg_instanceId!); return {}; }); diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart index b3d0e998ce84..2373ec0d1bfc 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart @@ -44,7 +44,7 @@ void main() { test('create', () { final WebView webView = WebView(); - final WebSettings webSettings = webView.settings; + final WebSettings webSettings = WebSettings(webView); expect( WebSettings.api.instanceManager.getInstanceId(webSettings), isNotNull, From 916ca2a7c6fc0800752c3e635969e4591fafc482 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 19 Oct 2021 14:59:53 -0700 Subject: [PATCH 09/11] add avoid_relative_lib_imports to generated test file --- .../webview_flutter_android/test/android_webview.pigeon.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart index 9f6996950b3f..821dacebd2ed 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart @@ -4,7 +4,7 @@ // Autogenerated from Pigeon (v1.0.7), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, avoid_relative_lib_imports // @dart = 2.12 import 'dart:async'; import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; From 484cce06740919353118186b8beade5f86c84b58 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 19 Oct 2021 15:17:27 -0700 Subject: [PATCH 10/11] remove unused file --- .../test/test_binary_messenger.dart | 28 ------------------- 1 file changed, 28 deletions(-) delete mode 100644 packages/webview_flutter/webview_flutter_android/test/test_binary_messenger.dart diff --git a/packages/webview_flutter/webview_flutter_android/test/test_binary_messenger.dart b/packages/webview_flutter/webview_flutter_android/test/test_binary_messenger.dart deleted file mode 100644 index 1aac4d25d251..000000000000 --- a/packages/webview_flutter/webview_flutter_android/test/test_binary_messenger.dart +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:ui'; - -import 'package:flutter/services.dart'; - -class TestBinaryMessenger implements BinaryMessenger { - @override - Future handlePlatformMessage( - String channel, - ByteData? data, - PlatformMessageResponseCallback? callback, - ) async { - // Do nothing. - } - - @override - Future? send(String channel, ByteData? message) async { - return StandardMessageCodec().encodeMessage({}); - } - - @override - void setMessageHandler(String channel, MessageHandler? handler) { - // Do nothing. - } -} From 3713204d00167f1e7d14646a90e4be711714baee Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 25 Oct 2021 23:47:04 -0700 Subject: [PATCH 11/11] add webchromeclient --- .../lib/src/android_webview.dart | 38 +++++ .../lib/src/android_webview.pigeon.dart | 133 ++++++++++++++++++ .../lib/src/android_webview_api_impls.dart | 65 +++++++++ .../pigeons/android_webview.dart | 13 ++ .../test/android_webview.pigeon.dart | 74 ++++++++++ .../test/android_webview_test.dart | 55 ++++++++ 6 files changed, 378 insertions(+) diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart index a7984054fe06..1ddd6f3d9f0f 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart @@ -41,6 +41,7 @@ class WebView { WebViewClient? _currentWebViewClient; DownloadListener? _currentDownloadListener; + WebChromeClient? _currentWebChromeClient; Set _javaScriptChannels = {}; /// Whether the [WebView] will be rendered with an [AndroidViewSurface]. @@ -258,6 +259,33 @@ class WebView { _currentDownloadListener = listener; return api.setDownloadListenerFromInstance(this, listener); } + + /// Sets the chrome handler. + /// + /// This is an implementation of [WebChromeClient] for use in handling + /// JavaScript dialogs, favicons, titles, and the progress. This will replace + /// the current handler. + Future setWebChromeClient(WebChromeClient client) { + final WebChromeClient? currentWebChromeClient = _currentWebChromeClient; + + if (client == currentWebChromeClient) { + return Future.value(); + } + + if (currentWebChromeClient != null) { + WebChromeClient.api.disposeFromInstance(currentWebChromeClient); + } + + final WebViewClient? currentWebViewClient = _currentWebViewClient; + assert( + currentWebViewClient != null, + "Can't set a WebChromeClient without setting a WebViewClient first.", + ); + + WebChromeClient.api.createFromInstance(client, currentWebViewClient!); + _currentWebChromeClient = client; + return api.setWebChromeClientFromInstance(this, client); + } } /// Manages settings state for a [WebView]. @@ -559,6 +587,16 @@ abstract class DownloadListener { ); } +/// Handles JavaScript dialogs, favicons, titles, and the progress for [WebView]. +abstract class WebChromeClient { + /// Pigeon Host Api implementation for [WebChromeClient]. + @visibleForTesting + static WebChromeClientHostApiImpl api = WebChromeClientHostApiImpl(); + + /// Notify the host application that a file should be downloaded. + void onProgressChanged(WebView webView, int progress); +} + /// Encompasses parameters to the [WebViewClient.requestLoading] method. class WebResourceRequest { /// Constructs a [WebResourceRequest]. diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart index 206b045e900a..81ec7c7bf80e 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart @@ -617,6 +617,33 @@ class WebViewHostApi { return; } } + + Future setWebChromeClient( + int arg_instanceId, int arg_clientInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setWebChromeClient', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_clientInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } } class _WebSettingsHostApiCodec extends StandardMessageCodec { @@ -1466,3 +1493,109 @@ abstract class DownloadListenerFlutterApi { } } } + +class _WebChromeClientHostApiCodec extends StandardMessageCodec { + const _WebChromeClientHostApiCodec(); +} + +class WebChromeClientHostApi { + /// Constructor for [WebChromeClientHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + WebChromeClientHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _WebChromeClientHostApiCodec(); + + Future create( + int arg_instanceId, int arg_webViewClientInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebChromeClientHostApi.create', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_webViewClientInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future dispose(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebChromeClientHostApi.dispose', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _WebChromeClientFlutterApiCodec extends StandardMessageCodec { + const _WebChromeClientFlutterApiCodec(); +} + +abstract class WebChromeClientFlutterApi { + static const MessageCodec codec = _WebChromeClientFlutterApiCodec(); + + void onProgressChanged(int instanceId, int webViewInstanceId, int progress); + static void setup(WebChromeClientFlutterApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebChromeClientFlutterApi.onProgressChanged', + codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebChromeClientFlutterApi.onProgressChanged was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebChromeClientFlutterApi.onProgressChanged was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebChromeClientFlutterApi.onProgressChanged was null, expected non-null int.'); + final int? arg_progress = args[2] as int?; + assert(arg_progress != null, + 'Argument for dev.flutter.pigeon.WebChromeClientFlutterApi.onProgressChanged was null, expected non-null int.'); + api.onProgressChanged( + arg_instanceId!, arg_webViewInstanceId!, arg_progress!); + return; + }); + } + } + } +} diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart index 83621e02cb16..f909e49bd802 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart @@ -161,6 +161,17 @@ class WebViewHostApiImpl extends WebViewHostApi { instanceManager.getInstanceId(listener)!, ); } + + /// Helper method to convert instances ids to objects. + Future setWebChromeClientFromInstance( + WebView instance, + WebChromeClient client, + ) { + return setWebChromeClient( + instanceManager.getInstanceId(instance)!, + instanceManager.getInstanceId(client)!, + ); + } } /// Host api implementation for [WebSettings]. @@ -555,3 +566,57 @@ class DownloadListenerFlutterApiImpl extends DownloadListenerFlutterApi { ); } } + +/// Host api implementation for [DownloadListener]. +class WebChromeClientHostApiImpl extends WebChromeClientHostApi { + /// Constructs a [WebChromeClientHostApiImpl]. + WebChromeClientHostApiImpl({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : super(binaryMessenger: binaryMessenger) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance( + WebChromeClient instance, + WebViewClient webViewClient, + ) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + return create(instanceId, instanceManager.getInstanceId(webViewClient)!); + } + } + + /// Helper method to convert instances ids to objects. + Future disposeFromInstance(WebChromeClient instance) async { + final int? instanceId = instanceManager.removeInstance(instance); + if (instanceId != null) { + return dispose(instanceId); + } + } +} + +/// Flutter api implementation for [DownloadListener]. +class WebChromeClientFlutterApiImpl extends WebChromeClientFlutterApi { + /// Constructs a [DownloadListenerFlutterApiImpl]. + WebChromeClientFlutterApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + @override + void onProgressChanged(int instanceId, int webViewInstanceId, int progress) { + final WebChromeClient instance = + instanceManager.getInstance(instanceId) as WebChromeClient; + instance.onProgressChanged( + instanceManager.getInstance(webViewInstanceId) as WebView, + progress, + ); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart index 375f3ced67f2..1877c1b91feb 100644 --- a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart +++ b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart @@ -69,6 +69,8 @@ abstract class WebViewHostApi { void removeJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId); void setDownloadListener(int instanceId, int listenerInstanceId); + + void setWebChromeClient(int instanceId, int clientInstanceId); } @HostApi(dartHostTestHandler: 'TestWebSettingsHostApi') @@ -166,3 +168,14 @@ abstract class DownloadListenerFlutterApi { int contentLength, ); } + +@HostApi(dartHostTestHandler: 'TestWebChromeClientHostApi') +abstract class WebChromeClientHostApi { + void create(int instanceId, int webViewClientInstanceId); + void dispose(int instanceId); +} + +@FlutterApi() +abstract class WebChromeClientFlutterApi { + void onProgressChanged(int instanceId, int webViewInstanceId, int progress); +} diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart index 821dacebd2ed..70aa53ca2610 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart @@ -42,6 +42,7 @@ abstract class TestWebViewHostApi { void addJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId); void removeJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId); void setDownloadListener(int instanceId, int listenerInstanceId); + void setWebChromeClient(int instanceId, int clientInstanceId); static void setup(TestWebViewHostApi? api) { { const BasicMessageChannel channel = BasicMessageChannel( @@ -465,6 +466,27 @@ abstract class TestWebViewHostApi { }); } } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setWebChromeClient', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebChromeClient was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebChromeClient was null, expected non-null int.'); + final int? arg_clientInstanceId = args[1] as int?; + assert(arg_clientInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebChromeClient was null, expected non-null int.'); + api.setWebChromeClient(arg_instanceId!, arg_clientInstanceId!); + return {}; + }); + } + } } } @@ -924,3 +946,55 @@ abstract class TestDownloadListenerHostApi { } } } + +class _TestWebChromeClientHostApiCodec extends StandardMessageCodec { + const _TestWebChromeClientHostApiCodec(); +} + +abstract class TestWebChromeClientHostApi { + static const MessageCodec codec = _TestWebChromeClientHostApiCodec(); + + void create(int instanceId, int webViewClientInstanceId); + void dispose(int instanceId); + static void setup(TestWebChromeClientHostApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebChromeClientHostApi.create', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebChromeClientHostApi.create was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebChromeClientHostApi.create was null, expected non-null int.'); + final int? arg_webViewClientInstanceId = args[1] as int?; + assert(arg_webViewClientInstanceId != null, + 'Argument for dev.flutter.pigeon.WebChromeClientHostApi.create was null, expected non-null int.'); + api.create(arg_instanceId!, arg_webViewClientInstanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebChromeClientHostApi.dispose', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebChromeClientHostApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebChromeClientHostApi.dispose was null, expected non-null int.'); + api.dispose(arg_instanceId!); + return {}; + }); + } + } + } +} diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart index 2373ec0d1bfc..462670abdb83 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart @@ -149,6 +149,45 @@ void main() { ); }); }); + + group('$WebChromeClient', () { + setUpAll(() { + TestWebViewHostApi.setup(TestWebViewHostApiImpl()); + TestWebViewClientHostApi.setup(TestWebViewClientHostApiImpl()); + TestWebChromeClientHostApi.setup(TestWebChromeClientHostApiImpl()); + }); + + setUp(() { + final InstanceManager instanceManager = InstanceManager(); + WebView.api = WebViewHostApiImpl(instanceManager: instanceManager); + WebViewClient.api = WebViewClientHostApiImpl( + instanceManager: instanceManager, + ); + WebChromeClient.api = WebChromeClientHostApiImpl( + instanceManager: instanceManager, + ); + }); + + test('create', () { + final WebView webView = WebView(); + webView.setWebViewClient(TestWebViewClient()); + + final WebChromeClient webChromeClient1 = TestWebChromeClient(); + final WebChromeClient webChromeClient2 = TestWebChromeClient(); + + webView.setWebChromeClient(webChromeClient1); + expect( + WebChromeClient.api.instanceManager.getInstanceId(webChromeClient1), + isNotNull, + ); + + webView.setWebChromeClient(webChromeClient2); + expect( + WebChromeClient.api.instanceManager.getInstanceId(webChromeClient1), + isNull, + ); + }); + }); }); } @@ -172,6 +211,11 @@ class TestDownloadListener extends DownloadListener { ) {} } +class TestWebChromeClient extends WebChromeClient { + @override + void onProgressChanged(WebView webView, int progress) {} +} + class TestWebViewHostApiImpl extends TestWebViewHostApi { @override void addJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId) {} @@ -250,6 +294,9 @@ class TestWebViewHostApiImpl extends TestWebViewHostApi { @override void setWebViewClient(int instanceId, int webViewClientInstanceId) {} + + @override + void setWebChromeClient(int instanceId, int clientInstanceId) {} } class TestWebSettingsHostApiImpl extends TestWebSettingsHostApi { @@ -316,3 +363,11 @@ class TestDownloadListenerHostApiImpl extends TestDownloadListenerHostApi { @override void dispose(int instanceId) {} } + +class TestWebChromeClientHostApiImpl extends TestWebChromeClientHostApi { + @override + void create(int instanceId, int webViewClientInstanceId) {} + + @override + void dispose(int instanceId) {} +}