[webview_flutter] Proof of concept web implementation (#4594)

Initial proof of concept implementation of flutter_webview for the web.
diff --git a/packages/webview_flutter/webview_flutter_web/AUTHORS b/packages/webview_flutter/webview_flutter_web/AUTHORS
new file mode 100644
index 0000000..05432a7
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/AUTHORS
@@ -0,0 +1,8 @@
+# Below is a list of people and organizations that have contributed
+# to the Flutter project. Names should be added to the list like so:
+#
+#   Name/Organization <email address>
+
+Google Inc.
+Bodhi Mulders <info@bemacized.net>
+
diff --git a/packages/webview_flutter/webview_flutter_web/CHANGELOG.md b/packages/webview_flutter/webview_flutter_web/CHANGELOG.md
new file mode 100644
index 0000000..11cfeda
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/CHANGELOG.md
@@ -0,0 +1,4 @@
+## 0.1.0
+
+*  First web implementation for webview_flutter
+
diff --git a/packages/webview_flutter/webview_flutter_web/LICENSE b/packages/webview_flutter/webview_flutter_web/LICENSE
new file mode 100644
index 0000000..7713090
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2013 The Flutter Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/packages/webview_flutter/webview_flutter_web/README.md b/packages/webview_flutter/webview_flutter_web/README.md
new file mode 100644
index 0000000..9e7e1c6
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/README.md
@@ -0,0 +1,20 @@
+# webview\_flutter\_web
+
+This is an implementation of the [`webview_flutter`](https://pub.dev/packages/webview_flutter) plugin for web.
+
+It is currently severely limited and doesn't implement most of the available functionality.
+The following functionality is currently available:
+
+- `loadUrl` (Without headers)
+- `requestUrl`
+- `loadHTMLString` (Without `baseUrl`)
+- Setting the `initialUrl` through `CreationParams`.
+
+Nothing else is currently supported.
+
+## Usage
+
+### Depend on the package
+
+This package is not an endorsed implementation of the `webview_flutter` plugin yet, so you'll need to
+[add it explicitly](https://pub.dev/packages/webview_flutter_web/install).
\ No newline at end of file
diff --git a/packages/webview_flutter/webview_flutter_web/example/.metadata b/packages/webview_flutter/webview_flutter_web/example/.metadata
new file mode 100644
index 0000000..da83b1a
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/.metadata
@@ -0,0 +1,8 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+  revision: 1e5cb2d87f8542f9fbbd0f22d528823274be0acb
+  channel: master
diff --git a/packages/webview_flutter/webview_flutter_web/example/README.md b/packages/webview_flutter/webview_flutter_web/example/README.md
new file mode 100644
index 0000000..850ee74
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/README.md
@@ -0,0 +1,8 @@
+# webview_flutter_example
+
+Demonstrates how to use the webview_flutter plugin.
+
+## Getting Started
+
+For help getting started with Flutter, view our online
+[documentation](https://flutter.dev/).
diff --git a/packages/webview_flutter/webview_flutter_web/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_web/example/integration_test/webview_flutter_test.dart
new file mode 100644
index 0000000..232ecdd
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/integration_test/webview_flutter_test.dart
@@ -0,0 +1,72 @@
+// 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:async';
+import 'dart:html' as html;
+
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+import 'package:webview_flutter_web_example/web_view.dart';
+
+void main() {
+  IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+  // URLs to navigate to in tests. These need to be URLs that we are confident will
+  // always be accessible, and won't do redirection. (E.g., just
+  // 'https://www.google.com/' will sometimes redirect traffic that looks
+  // like it's coming from a bot, which is true of these tests).
+  const String primaryUrl = 'https://flutter.dev/';
+  const String secondaryUrl = 'https://www.google.com/robots.txt';
+
+  testWidgets('initialUrl', (WidgetTester tester) async {
+    final Completer<WebViewController> controllerCompleter =
+        Completer<WebViewController>();
+    await tester.pumpWidget(
+      Directionality(
+        textDirection: TextDirection.ltr,
+        child: WebView(
+          key: GlobalKey(),
+          initialUrl: primaryUrl,
+          onWebViewCreated: (WebViewController controller) {
+            controllerCompleter.complete(controller);
+          },
+        ),
+      ),
+    );
+    await controllerCompleter.future;
+
+    // Assert an iframe has been rendered to the DOM with the correct src attribute.
+    final html.IFrameElement? element =
+        html.document.querySelector('iframe') as html.IFrameElement?;
+    expect(element, isNotNull);
+    expect(element!.src, primaryUrl);
+  });
+
+  testWidgets('loadUrl', (WidgetTester tester) async {
+    final Completer<WebViewController> controllerCompleter =
+        Completer<WebViewController>();
+    await tester.pumpWidget(
+      Directionality(
+        textDirection: TextDirection.ltr,
+        child: WebView(
+          key: GlobalKey(),
+          initialUrl: primaryUrl,
+          onWebViewCreated: (WebViewController controller) {
+            controllerCompleter.complete(controller);
+          },
+        ),
+      ),
+    );
+    final WebViewController controller = await controllerCompleter.future;
+    await controller.loadUrl(secondaryUrl);
+
+    // Assert an iframe has been rendered to the DOM with the correct src attribute.
+    final html.IFrameElement? element =
+        html.document.querySelector('iframe') as html.IFrameElement?;
+    expect(element, isNotNull);
+    expect(element!.src, secondaryUrl);
+  });
+}
diff --git a/packages/webview_flutter/webview_flutter_web/example/lib/main.dart b/packages/webview_flutter/webview_flutter_web/example/lib/main.dart
new file mode 100644
index 0000000..9cf412d
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/lib/main.dart
@@ -0,0 +1,93 @@
+// 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.
+
+// ignore_for_file: public_member_api_docs
+
+import 'dart:async';
+import 'dart:typed_data';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';
+
+import 'web_view.dart';
+
+void main() {
+  runApp(const MaterialApp(home: _WebViewExample()));
+}
+
+class _WebViewExample extends StatefulWidget {
+  const _WebViewExample({Key? key}) : super(key: key);
+
+  @override
+  _WebViewExampleState createState() => _WebViewExampleState();
+}
+
+class _WebViewExampleState extends State<_WebViewExample> {
+  final Completer<WebViewController> _controller =
+      Completer<WebViewController>();
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        title: const Text('Flutter WebView example'),
+        actions: <Widget>[
+          _SampleMenu(_controller.future),
+        ],
+      ),
+      body: WebView(
+        initialUrl: 'https://flutter.dev',
+        onWebViewCreated: (WebViewController controller) {
+          _controller.complete(controller);
+        },
+      ),
+    );
+  }
+}
+
+enum _MenuOptions {
+  doPostRequest,
+}
+
+class _SampleMenu extends StatelessWidget {
+  const _SampleMenu(this.controller);
+
+  final Future<WebViewController> controller;
+
+  @override
+  Widget build(BuildContext context) {
+    return FutureBuilder<WebViewController>(
+      future: controller,
+      builder:
+          (BuildContext context, AsyncSnapshot<WebViewController> controller) {
+        return PopupMenuButton<_MenuOptions>(
+          onSelected: (_MenuOptions value) {
+            switch (value) {
+              case _MenuOptions.doPostRequest:
+                _onDoPostRequest(controller.data!, context);
+                break;
+            }
+          },
+          itemBuilder: (BuildContext context) => <PopupMenuItem<_MenuOptions>>[
+            const PopupMenuItem<_MenuOptions>(
+              value: _MenuOptions.doPostRequest,
+              child: Text('Post Request'),
+            ),
+          ],
+        );
+      },
+    );
+  }
+
+  Future<void> _onDoPostRequest(
+      WebViewController controller, BuildContext context) async {
+    final WebViewRequest request = WebViewRequest(
+      uri: Uri.parse('https://httpbin.org/post'),
+      method: WebViewRequestMethod.post,
+      headers: <String, String>{'foo': 'bar', 'Content-Type': 'text/plain'},
+      body: Uint8List.fromList('Test Body'.codeUnits),
+    );
+    await controller.loadRequest(request);
+  }
+}
diff --git a/packages/webview_flutter/webview_flutter_web/example/lib/web_view.dart b/packages/webview_flutter/webview_flutter_web/example/lib/web_view.dart
new file mode 100644
index 0000000..787b016
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/lib/web_view.dart
@@ -0,0 +1,385 @@
+// 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:async';
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';
+import 'package:webview_flutter_web/webview_flutter_web.dart';
+
+/// Optional callback invoked when a web view is first created. [controller] is
+/// the [WebViewController] for the created web view.
+typedef WebViewCreatedCallback = void Function(WebViewController controller);
+
+/// A web view widget for showing html content.
+///
+/// The [WebView] widget wraps around the [WebWebViewPlatform].
+///
+/// The [WebView] widget is controlled using the [WebViewController] which is
+/// provided through the `onWebViewCreated` callback.
+///
+/// In this example project it's main purpose is to facilitate integration
+/// testing of the `webview_flutter_web` package.
+class WebView extends StatefulWidget {
+  /// Creates a new web view.
+  ///
+  /// The web view can be controlled using a `WebViewController` that is passed to the
+  /// `onWebViewCreated` callback once the web view is created.
+  const WebView({
+    Key? key,
+    this.onWebViewCreated,
+    this.initialUrl,
+  }) : super(key: key);
+
+  /// The WebView platform that's used by this WebView.
+  ///
+  /// The default value is [WebWebViewPlatform].
+  /// This property can be set to use a custom platform implementation for WebViews.
+  /// Setting `platform` doesn't affect [WebView]s that were already created.
+  static WebViewPlatform platform = WebWebViewPlatform();
+
+  /// If not null invoked once the web view is created.
+  final WebViewCreatedCallback? onWebViewCreated;
+
+  /// The initial URL to load.
+  final String? initialUrl;
+
+  @override
+  _WebViewState createState() => _WebViewState();
+}
+
+class _WebViewState extends State<WebView> {
+  final Completer<WebViewController> _controller =
+      Completer<WebViewController>();
+  late final _PlatformCallbacksHandler _platformCallbacksHandler;
+
+  @override
+  void initState() {
+    super.initState();
+    _platformCallbacksHandler = _PlatformCallbacksHandler();
+  }
+
+  @override
+  void didUpdateWidget(WebView oldWidget) {
+    super.didUpdateWidget(oldWidget);
+    _controller.future.then((WebViewController controller) {
+      controller.updateWidget(widget);
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return WebView.platform.build(
+      context: context,
+      onWebViewPlatformCreated:
+          (WebViewPlatformController? webViewPlatformController) {
+        final WebViewController controller = WebViewController(
+          widget,
+          webViewPlatformController!,
+        );
+        _controller.complete(controller);
+
+        if (widget.onWebViewCreated != null) {
+          widget.onWebViewCreated!(controller);
+        }
+      },
+      webViewPlatformCallbacksHandler: _platformCallbacksHandler,
+      creationParams: CreationParams(
+        initialUrl: widget.initialUrl,
+        webSettings: _webSettingsFromWidget(widget),
+      ),
+      javascriptChannelRegistry:
+          JavascriptChannelRegistry(<JavascriptChannel>{}),
+    );
+  }
+}
+
+class _PlatformCallbacksHandler implements WebViewPlatformCallbacksHandler {
+  _PlatformCallbacksHandler();
+
+  @override
+  FutureOr<bool> onNavigationRequest(
+      {required String url, required bool isForMainFrame}) {
+    throw UnimplementedError();
+  }
+
+  @override
+  void onPageFinished(String url) {}
+
+  @override
+  void onPageStarted(String url) {}
+
+  @override
+  void onProgress(int progress) {}
+
+  @override
+  void onWebResourceError(WebResourceError error) {}
+}
+
+/// Controls a [WebView].
+///
+/// A [WebViewController] instance can be obtained by setting the [WebView.onWebViewCreated]
+/// callback for a [WebView] widget.
+class WebViewController {
+  /// Creates a [WebViewController] which can be used to control the provided
+  /// [WebView] widget.
+  WebViewController(
+    this._widget,
+    this._webViewPlatformController,
+  ) : assert(_webViewPlatformController != null) {
+    _settings = _webSettingsFromWidget(_widget);
+  }
+
+  final WebViewPlatformController _webViewPlatformController;
+
+  late WebSettings _settings;
+
+  WebView _widget;
+
+  /// Loads the specified URL.
+  ///
+  /// If `headers` is not null and the URL is an HTTP URL, the key value paris in `headers` will
+  /// be added as key value pairs of HTTP headers for the request.
+  ///
+  /// `url` must not be null.
+  ///
+  /// Throws an ArgumentError if `url` is not a valid URL string.
+  Future<void> loadUrl(
+    String url, {
+    Map<String, String>? headers,
+  }) async {
+    assert(url != null);
+    _validateUrlString(url);
+    return _webViewPlatformController.loadUrl(url, headers);
+  }
+
+  /// Loads a page by making the specified request.
+  Future<void> loadRequest(WebViewRequest request) async {
+    return _webViewPlatformController.loadRequest(request);
+  }
+
+  /// Accessor to the current URL that the WebView is displaying.
+  ///
+  /// If [WebView.initialUrl] was never specified, returns `null`.
+  /// Note that this operation is asynchronous, and it is possible that the
+  /// current URL changes again by the time this function returns (in other
+  /// words, by the time this future completes, the WebView may be displaying a
+  /// different URL).
+  Future<String?> currentUrl() {
+    return _webViewPlatformController.currentUrl();
+  }
+
+  /// Checks whether there's a back history item.
+  ///
+  /// Note that this operation is asynchronous, and it is possible that the "canGoBack" state has
+  /// changed by the time the future completed.
+  Future<bool> canGoBack() {
+    return _webViewPlatformController.canGoBack();
+  }
+
+  /// Checks whether there's a forward history item.
+  ///
+  /// Note that this operation is asynchronous, and it is possible that the "canGoForward" state has
+  /// changed by the time the future completed.
+  Future<bool> canGoForward() {
+    return _webViewPlatformController.canGoForward();
+  }
+
+  /// Goes back in the history of this WebView.
+  ///
+  /// If there is no back history item this is a no-op.
+  Future<void> goBack() {
+    return _webViewPlatformController.goBack();
+  }
+
+  /// Goes forward in the history of this WebView.
+  ///
+  /// If there is no forward history item this is a no-op.
+  Future<void> goForward() {
+    return _webViewPlatformController.goForward();
+  }
+
+  /// Reloads the current URL.
+  Future<void> reload() {
+    return _webViewPlatformController.reload();
+  }
+
+  /// Clears all caches used by the [WebView].
+  ///
+  /// The following caches are cleared:
+  ///	1. Browser HTTP Cache.
+  ///	2. [Cache API](https://developers.google.com/web/fundamentals/instant-and-offline/web-storage/cache-api) caches.
+  ///    These are not yet supported in iOS WkWebView. Service workers tend to use this cache.
+  ///	3. Application cache.
+  ///	4. Local Storage.
+  ///
+  /// Note: Calling this method also triggers a reload.
+  Future<void> clearCache() async {
+    await _webViewPlatformController.clearCache();
+    return reload();
+  }
+
+  /// Update the widget managed by the [WebViewController].
+  Future<void> updateWidget(WebView widget) async {
+    _widget = widget;
+    await _updateSettings(_webSettingsFromWidget(widget));
+  }
+
+  Future<void> _updateSettings(WebSettings newSettings) {
+    final WebSettings update =
+        _clearUnchangedWebSettings(_settings, newSettings);
+    _settings = newSettings;
+    return _webViewPlatformController.updateSettings(update);
+  }
+
+  @visibleForTesting
+  // ignore: public_member_api_docs
+  Future<String> evaluateJavascript(String javascriptString) {
+    if (_settings.javascriptMode == JavascriptMode.disabled) {
+      return Future<String>.error(FlutterError(
+          'JavaScript mode must be enabled/unrestricted when calling evaluateJavascript.'));
+    }
+    return _webViewPlatformController.evaluateJavascript(javascriptString);
+  }
+
+  /// Runs the given JavaScript in the context of the current page.
+  /// If you are looking for the result, use [runJavascriptReturningResult] instead.
+  /// The Future completes with an error if a JavaScript error occurred.
+  ///
+  /// When running JavaScript in a [WebView], it is best practice to wait for
+  //  the [WebView.onPageFinished] callback. This guarantees all the JavaScript
+  //  embedded in the main frame HTML has been loaded.
+  Future<void> runJavascript(String javaScriptString) {
+    if (_settings.javascriptMode == JavascriptMode.disabled) {
+      return Future<void>.error(FlutterError(
+          'Javascript mode must be enabled/unrestricted when calling runJavascript.'));
+    }
+    return _webViewPlatformController.runJavascript(javaScriptString);
+  }
+
+  /// Runs the given JavaScript in the context of the current page, and returns the result.
+  ///
+  /// Returns the evaluation result as a JSON formatted string.
+  /// The Future completes with an error if a JavaScript error occurred.
+  ///
+  /// When evaluating JavaScript in a [WebView], it is best practice to wait for
+  /// the [WebView.onPageFinished] callback. This guarantees all the JavaScript
+  /// embedded in the main frame HTML has been loaded.
+  Future<String> runJavascriptReturningResult(String javaScriptString) {
+    if (_settings.javascriptMode == JavascriptMode.disabled) {
+      return Future<String>.error(FlutterError(
+          'Javascript mode must be enabled/unrestricted when calling runJavascriptReturningResult.'));
+    }
+    return _webViewPlatformController
+        .runJavascriptReturningResult(javaScriptString);
+  }
+
+  /// Returns the title of the currently loaded page.
+  Future<String?> getTitle() {
+    return _webViewPlatformController.getTitle();
+  }
+
+  /// Sets the WebView's content scroll position.
+  ///
+  /// The parameters `x` and `y` specify the scroll position in WebView pixels.
+  Future<void> scrollTo(int x, int y) {
+    return _webViewPlatformController.scrollTo(x, y);
+  }
+
+  /// Move the scrolled position of this view.
+  ///
+  /// The parameters `x` and `y` specify the amount of WebView pixels to scroll by horizontally and vertically respectively.
+  Future<void> scrollBy(int x, int y) {
+    return _webViewPlatformController.scrollBy(x, y);
+  }
+
+  /// Return the horizontal scroll position, in WebView pixels, of this view.
+  ///
+  /// Scroll position is measured from left.
+  Future<int> getScrollX() {
+    return _webViewPlatformController.getScrollX();
+  }
+
+  /// Return the vertical scroll position, in WebView pixels, of this view.
+  ///
+  /// Scroll position is measured from top.
+  Future<int> getScrollY() {
+    return _webViewPlatformController.getScrollY();
+  }
+
+  // This method assumes that no fields in `currentValue` are null.
+  WebSettings _clearUnchangedWebSettings(
+      WebSettings currentValue, WebSettings newValue) {
+    assert(currentValue.javascriptMode != null);
+    assert(currentValue.hasNavigationDelegate != null);
+    assert(currentValue.hasProgressTracking != null);
+    assert(currentValue.debuggingEnabled != null);
+    assert(currentValue.userAgent != null);
+    assert(newValue.javascriptMode != null);
+    assert(newValue.hasNavigationDelegate != null);
+    assert(newValue.debuggingEnabled != null);
+    assert(newValue.userAgent != null);
+    assert(newValue.zoomEnabled != null);
+
+    JavascriptMode? javascriptMode;
+    bool? hasNavigationDelegate;
+    bool? hasProgressTracking;
+    bool? debuggingEnabled;
+    WebSetting<String?> userAgent = const WebSetting<String?>.absent();
+    bool? zoomEnabled;
+    if (currentValue.javascriptMode != newValue.javascriptMode) {
+      javascriptMode = newValue.javascriptMode;
+    }
+    if (currentValue.hasNavigationDelegate != newValue.hasNavigationDelegate) {
+      hasNavigationDelegate = newValue.hasNavigationDelegate;
+    }
+    if (currentValue.hasProgressTracking != newValue.hasProgressTracking) {
+      hasProgressTracking = newValue.hasProgressTracking;
+    }
+    if (currentValue.debuggingEnabled != newValue.debuggingEnabled) {
+      debuggingEnabled = newValue.debuggingEnabled;
+    }
+    if (currentValue.userAgent != newValue.userAgent) {
+      userAgent = newValue.userAgent;
+    }
+    if (currentValue.zoomEnabled != newValue.zoomEnabled) {
+      zoomEnabled = newValue.zoomEnabled;
+    }
+
+    return WebSettings(
+      javascriptMode: javascriptMode,
+      hasNavigationDelegate: hasNavigationDelegate,
+      hasProgressTracking: hasProgressTracking,
+      debuggingEnabled: debuggingEnabled,
+      userAgent: userAgent,
+      zoomEnabled: zoomEnabled,
+    );
+  }
+
+  // Throws an ArgumentError if `url` is not a valid URL string.
+  void _validateUrlString(String url) {
+    try {
+      final Uri uri = Uri.parse(url);
+      if (uri.scheme.isEmpty) {
+        throw ArgumentError('Missing scheme in URL string: "$url"');
+      }
+    } on FormatException catch (e) {
+      throw ArgumentError(e);
+    }
+  }
+}
+
+WebSettings _webSettingsFromWidget(WebView widget) {
+  return WebSettings(
+    javascriptMode: JavascriptMode.unrestricted,
+    hasNavigationDelegate: false,
+    hasProgressTracking: false,
+    debuggingEnabled: false,
+    gestureNavigationEnabled: false,
+    allowsInlineMediaPlayback: true,
+    userAgent: const WebSetting<String?>.of(''),
+    zoomEnabled: false,
+  );
+}
diff --git a/packages/webview_flutter/webview_flutter_web/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_web/example/pubspec.yaml
new file mode 100644
index 0000000..a98df79
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/pubspec.yaml
@@ -0,0 +1,32 @@
+name: webview_flutter_web_example
+description: Demonstrates how to use the webview_flutter_web plugin.
+publish_to: none
+
+environment:
+  sdk: ">=2.14.0 <3.0.0"
+
+dependencies:
+  flutter:
+    sdk: flutter
+  flutter_web_plugins:
+    sdk: flutter
+  webview_flutter_web:
+    # When depending on this package from a real application you should use:
+    #   webview_flutter_web: ^x.y.z
+    # See https://dart.dev/tools/pub/dependencies#version-constraints
+    # The example app is bundled with the plugin so we use a path dependency on
+    # the parent directory to use the current plugin's version.
+    path: ../
+
+dev_dependencies:
+  espresso: ^0.1.0+2
+  flutter_driver:
+    sdk: flutter
+  flutter_test:
+    sdk: flutter
+  integration_test:
+    sdk: flutter
+  pedantic: ^1.10.0
+
+flutter:
+  uses-material-design: true
diff --git a/packages/webview_flutter/webview_flutter_web/example/test_driver/integration_test.dart b/packages/webview_flutter/webview_flutter_web/example/test_driver/integration_test.dart
new file mode 100644
index 0000000..4f10f2a
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/test_driver/integration_test.dart
@@ -0,0 +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 'package:integration_test/integration_test_driver.dart';
+
+Future<void> main() => integrationDriver();
diff --git a/packages/webview_flutter/webview_flutter_web/example/web/favicon.png b/packages/webview_flutter/webview_flutter_web/example/web/favicon.png
new file mode 100644
index 0000000..8aaa46a
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/web/favicon.png
Binary files differ
diff --git a/packages/webview_flutter/webview_flutter_web/example/web/icons/Icon-192.png b/packages/webview_flutter/webview_flutter_web/example/web/icons/Icon-192.png
new file mode 100644
index 0000000..b749bfe
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/web/icons/Icon-192.png
Binary files differ
diff --git a/packages/webview_flutter/webview_flutter_web/example/web/icons/Icon-512.png b/packages/webview_flutter/webview_flutter_web/example/web/icons/Icon-512.png
new file mode 100644
index 0000000..88cfd48
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/web/icons/Icon-512.png
Binary files differ
diff --git a/packages/webview_flutter/webview_flutter_web/example/web/icons/Icon-maskable-192.png b/packages/webview_flutter/webview_flutter_web/example/web/icons/Icon-maskable-192.png
new file mode 100644
index 0000000..eb9b4d7
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/web/icons/Icon-maskable-192.png
Binary files differ
diff --git a/packages/webview_flutter/webview_flutter_web/example/web/icons/Icon-maskable-512.png b/packages/webview_flutter/webview_flutter_web/example/web/icons/Icon-maskable-512.png
new file mode 100644
index 0000000..d69c566
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/web/icons/Icon-maskable-512.png
Binary files differ
diff --git a/packages/webview_flutter/webview_flutter_web/example/web/index.html b/packages/webview_flutter/webview_flutter_web/example/web/index.html
new file mode 100644
index 0000000..8b8b5bf
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/web/index.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<!-- 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. -->
+<html>
+<head>
+  <!--
+    If you are serving your web app in a path other than the root, change the
+    href value below to reflect the base path you are serving from.
+
+    The path provided below has to start and end with a slash "/" in order for
+    it to work correctly.
+
+    For more details:
+    * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
+
+    This is a placeholder for base href that will be replaced by the value of
+    the `--base-href` argument provided to `flutter build`.
+  -->
+  <base href="$FLUTTER_BASE_HREF">
+
+  <meta charset="UTF-8">
+  <meta content="IE=Edge" http-equiv="X-UA-Compatible">
+  <meta name="description" content="webview_flutter_web Example">
+
+  <!-- iOS meta tags & icons -->
+  <meta name="apple-mobile-web-app-capable" content="yes">
+  <meta name="apple-mobile-web-app-status-bar-style" content="black">
+  <meta name="apple-mobile-web-app-title" content="example">
+  <link rel="apple-touch-icon" href="icons/Icon-192.png">
+
+  <title>webview_flutter_web Example</title>
+  <link rel="manifest" href="manifest.json">
+</head>
+<body>
+  <!-- This script installs service_worker.js to provide PWA functionality to
+       application. For more information, see:
+       https://developers.google.com/web/fundamentals/primers/service-workers -->
+  <script>
+    var serviceWorkerVersion = null;
+    var scriptLoaded = false;
+    function loadMainDartJs() {
+      if (scriptLoaded) {
+        return;
+      }
+      scriptLoaded = true;
+      var scriptTag = document.createElement('script');
+      scriptTag.src = 'main.dart.js';
+      scriptTag.type = 'application/javascript';
+      document.body.append(scriptTag);
+    }
+
+    if ('serviceWorker' in navigator) {
+      // Service workers are supported. Use them.
+      window.addEventListener('load', function () {
+        // Wait for registration to finish before dropping the <script> tag.
+        // Otherwise, the browser will load the script multiple times,
+        // potentially different versions.
+        var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
+        navigator.serviceWorker.register(serviceWorkerUrl)
+          .then((reg) => {
+            function waitForActivation(serviceWorker) {
+              serviceWorker.addEventListener('statechange', () => {
+                if (serviceWorker.state == 'activated') {
+                  console.log('Installed new service worker.');
+                  loadMainDartJs();
+                }
+              });
+            }
+            if (!reg.active && (reg.installing || reg.waiting)) {
+              // No active web worker and we have installed or are installing
+              // one for the first time. Simply wait for it to activate.
+              waitForActivation(reg.installing || reg.waiting);
+            } else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
+              // When the app updates the serviceWorkerVersion changes, so we
+              // need to ask the service worker to update.
+              console.log('New service worker available.');
+              reg.update();
+              waitForActivation(reg.installing);
+            } else {
+              // Existing service worker is still good.
+              console.log('Loading app from service worker.');
+              loadMainDartJs();
+            }
+          });
+
+        // If service worker doesn't succeed in a reasonable amount of time,
+        // fallback to plaint <script> tag.
+        setTimeout(() => {
+          if (!scriptLoaded) {
+            console.warn(
+              'Failed to load app from service worker. Falling back to plain <script> tag.',
+            );
+            loadMainDartJs();
+          }
+        }, 4000);
+      });
+    } else {
+      // Service workers not supported. Just drop the <script> tag.
+      loadMainDartJs();
+    }
+  </script>
+</body>
+</html>
diff --git a/packages/webview_flutter/webview_flutter_web/example/web/manifest.json b/packages/webview_flutter/webview_flutter_web/example/web/manifest.json
new file mode 100644
index 0000000..1124a93
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/example/web/manifest.json
@@ -0,0 +1,35 @@
+{
+    "name": "webview_flutter_web Example",
+    "short_name": "example",
+    "start_url": ".",
+    "display": "standalone",
+    "background_color": "#0175C2",
+    "theme_color": "#0175C2",
+    "description": "A new Flutter project.",
+    "orientation": "portrait-primary",
+    "prefer_related_applications": false,
+    "icons": [
+        {
+            "src": "icons/Icon-192.png",
+            "sizes": "192x192",
+            "type": "image/png"
+        },
+        {
+            "src": "icons/Icon-512.png",
+            "sizes": "512x512",
+            "type": "image/png"
+        },
+        {
+            "src": "icons/Icon-maskable-192.png",
+            "sizes": "192x192",
+            "type": "image/png",
+            "purpose": "maskable"
+        },
+        {
+            "src": "icons/Icon-maskable-512.png",
+            "sizes": "512x512",
+            "type": "image/png",
+            "purpose": "maskable"
+        }
+    ]
+}
diff --git a/packages/webview_flutter/webview_flutter_web/lib/shims/dart_ui.dart b/packages/webview_flutter/webview_flutter_web/lib/shims/dart_ui.dart
new file mode 100644
index 0000000..1724dd6
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/lib/shims/dart_ui.dart
@@ -0,0 +1,10 @@
+// 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.
+
+/// This file shims dart:ui in web-only scenarios, getting rid of the need to
+/// suppress analyzer warnings.
+
+// TODO(BeMacized): Remove this file once web-only dart:ui APIs,
+// are exposed from a dedicated place. flutter/flutter#55000
+export 'dart_ui_fake.dart' if (dart.library.html) 'dart_ui_real.dart';
diff --git a/packages/webview_flutter/webview_flutter_web/lib/shims/dart_ui_fake.dart b/packages/webview_flutter/webview_flutter_web/lib/shims/dart_ui_fake.dart
new file mode 100644
index 0000000..8757ca2
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/lib/shims/dart_ui_fake.dart
@@ -0,0 +1,33 @@
+// 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:html' as html;
+
+// Fake interface for the logic that this package needs from (web-only) dart:ui.
+// This is conditionally exported so the analyzer sees these methods as available.
+
+// ignore_for_file: avoid_classes_with_only_static_members
+// ignore_for_file: camel_case_types
+
+/// Shim for web_ui engine.PlatformViewRegistry
+/// https://github.com/flutter/engine/blob/master/lib/web_ui/lib/ui.dart#L62
+class platformViewRegistry {
+  /// Shim for registerViewFactory
+  /// https://github.com/flutter/engine/blob/master/lib/web_ui/lib/ui.dart#L72
+  static bool registerViewFactory(
+      String viewTypeId, html.Element Function(int viewId) viewFactory) {
+    return false;
+  }
+}
+
+/// Shim for web_ui engine.AssetManager.
+/// https://github.com/flutter/engine/blob/master/lib/web_ui/lib/src/engine/assets.dart#L12
+class webOnlyAssetManager {
+  /// Shim for getAssetUrl.
+  /// https://github.com/flutter/engine/blob/master/lib/web_ui/lib/src/engine/assets.dart#L45
+  static String getAssetUrl(String asset) => '';
+}
+
+/// Signature of callbacks that have no arguments and return no data.
+typedef VoidCallback = void Function();
diff --git a/packages/webview_flutter/webview_flutter_web/lib/shims/dart_ui_real.dart b/packages/webview_flutter/webview_flutter_web/lib/shims/dart_ui_real.dart
new file mode 100644
index 0000000..276b768
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/lib/shims/dart_ui_real.dart
@@ -0,0 +1,5 @@
+// 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.
+
+export 'dart:ui';
diff --git a/packages/webview_flutter/webview_flutter_web/lib/webview_flutter_web.dart b/packages/webview_flutter/webview_flutter_web/lib/webview_flutter_web.dart
new file mode 100644
index 0000000..aa427eb
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/lib/webview_flutter_web.dart
@@ -0,0 +1,278 @@
+// 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:async';
+import 'dart:html';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/gestures.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_web_plugins/flutter_web_plugins.dart';
+import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';
+import 'shims/dart_ui.dart' as ui;
+
+/// Builds an iframe based WebView.
+///
+/// This is used as the default implementation for [WebView.platform] on web.
+class WebWebViewPlatform implements WebViewPlatform {
+  /// Constructs a new instance of [WebWebViewPlatform].
+  WebWebViewPlatform() {
+    ui.platformViewRegistry.registerViewFactory(
+        'webview-iframe',
+        (int viewId) => IFrameElement()
+          ..id = 'webview-$viewId'
+          ..width = '100%'
+          ..height = '100%'
+          ..style.border = 'none');
+  }
+
+  @override
+  Widget build({
+    required BuildContext context,
+    required CreationParams creationParams,
+    required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
+    required JavascriptChannelRegistry? javascriptChannelRegistry,
+    WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
+    Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers,
+  }) {
+    return HtmlElementView(
+      viewType: 'webview-iframe',
+      onPlatformViewCreated: (int viewId) {
+        if (onWebViewPlatformCreated == null) {
+          return;
+        }
+        final IFrameElement element =
+            document.getElementById('webview-$viewId')! as IFrameElement;
+        if (creationParams.initialUrl != null) {
+          element.src = creationParams.initialUrl;
+        }
+        onWebViewPlatformCreated(WebWebViewPlatformController(
+          element,
+        ));
+      },
+    );
+  }
+
+  @override
+  Future<bool> clearCookies() async => false;
+
+  /// Gets called when the plugin is registered.
+  static void registerWith(Registrar registrar) {}
+}
+
+/// Implementation of [WebViewPlatformController] for web.
+class WebWebViewPlatformController implements WebViewPlatformController {
+  /// Constructs a [WebWebViewPlatformController].
+  WebWebViewPlatformController(this._element);
+
+  final IFrameElement _element;
+  HttpRequestFactory _httpRequestFactory = HttpRequestFactory();
+
+  /// Setter for setting the HttpRequestFactory, for testing purposes.
+  @visibleForTesting
+  set httpRequestFactory(HttpRequestFactory factory) {
+    _httpRequestFactory = factory;
+  }
+
+  @override
+  Future<void> addJavascriptChannels(Set<String> javascriptChannelNames) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<bool> canGoBack() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<bool> canGoForward() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> clearCache() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<String?> currentUrl() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<String> evaluateJavascript(String javascript) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<int> getScrollX() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<int> getScrollY() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<String?> getTitle() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> goBack() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> goForward() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> loadUrl(String url, Map<String, String>? headers) async {
+    _element.src = url;
+  }
+
+  @override
+  Future<void> reload() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> removeJavascriptChannels(Set<String> javascriptChannelNames) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> runJavascript(String javascript) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<String> runJavascriptReturningResult(String javascript) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> scrollBy(int x, int y) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> scrollTo(int x, int y) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> updateSettings(WebSettings setting) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> loadFile(String absoluteFilePath) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> loadHtmlString(
+    String html, {
+    String? baseUrl,
+  }) async {
+    _element.src = 'data:text/html,' + Uri.encodeFull(html);
+  }
+
+  @override
+  Future<void> loadRequest(WebViewRequest request) async {
+    if (!request.uri.hasScheme) {
+      throw ArgumentError('WebViewRequest#uri is required to have a scheme.');
+    }
+    final HttpRequest httpReq = await _httpRequestFactory.request(
+        request.uri.toString(),
+        method: request.method.serialize(),
+        requestHeaders: request.headers,
+        sendData: request.body);
+    final String contentType =
+        httpReq.getResponseHeader('content-type') ?? 'text/html';
+    _element.src =
+        'data:$contentType,' + Uri.encodeFull(httpReq.responseText ?? '');
+  }
+
+  @override
+  Future<void> loadFlutterAsset(String key) {
+    throw UnimplementedError();
+  }
+}
+
+/// Factory class for creating [HttpRequest] instances.
+class HttpRequestFactory {
+  /// Creates and sends a URL request for the specified [url].
+  ///
+  /// By default `request` will perform an HTTP GET request, but a different
+  /// method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the
+  /// [method] parameter. (See also [HttpRequest.postFormData] for `POST`
+  /// requests only.
+  ///
+  /// The Future is completed when the response is available.
+  ///
+  /// If specified, `sendData` will send data in the form of a [ByteBuffer],
+  /// [Blob], [Document], [String], or [FormData] along with the HttpRequest.
+  ///
+  /// If specified, [responseType] sets the desired response format for the
+  /// request. By default it is [String], but can also be 'arraybuffer', 'blob',
+  /// 'document', 'json', or 'text'. See also [HttpRequest.responseType]
+  /// for more information.
+  ///
+  /// The [withCredentials] parameter specified that credentials such as a cookie
+  /// (already) set in the header or
+  /// [authorization headers](http://tools.ietf.org/html/rfc1945#section-10.2)
+  /// should be specified for the request. Details to keep in mind when using
+  /// credentials:
+  ///
+  /// /// Using credentials is only useful for cross-origin requests.
+  /// /// The `Access-Control-Allow-Origin` header of `url` cannot contain a wildcard (///).
+  /// /// The `Access-Control-Allow-Credentials` header of `url` must be set to true.
+  /// /// If `Access-Control-Expose-Headers` has not been set to true, only a subset of all the response headers will be returned when calling [getAllResponseHeaders].
+  ///
+  /// The following is equivalent to the [getString] sample above:
+  ///
+  ///     var name = Uri.encodeQueryComponent('John');
+  ///     var id = Uri.encodeQueryComponent('42');
+  ///     HttpRequest.request('users.json?name=$name&id=$id')
+  ///       .then((HttpRequest resp) {
+  ///         // Do something with the response.
+  ///     });
+  ///
+  /// Here's an example of submitting an entire form with [FormData].
+  ///
+  ///     var myForm = querySelector('form#myForm');
+  ///     var data = new FormData(myForm);
+  ///     HttpRequest.request('/submit', method: 'POST', sendData: data)
+  ///       .then((HttpRequest resp) {
+  ///         // Do something with the response.
+  ///     });
+  ///
+  /// Note that requests for file:// URIs are only supported by Chrome extensions
+  /// with appropriate permissions in their manifest. Requests to file:// URIs
+  /// will also never fail- the Future will always complete successfully, even
+  /// when the file cannot be found.
+  ///
+  /// See also: [authorization headers](http://en.wikipedia.org/wiki/Basic_access_authentication).
+  Future<HttpRequest> request(String url,
+      {String? method,
+      bool? withCredentials,
+      String? responseType,
+      String? mimeType,
+      Map<String, String>? requestHeaders,
+      dynamic sendData,
+      void onProgress(ProgressEvent e)?}) {
+    return HttpRequest.request(url,
+        method: method,
+        withCredentials: withCredentials,
+        responseType: responseType,
+        mimeType: mimeType,
+        requestHeaders: requestHeaders,
+        sendData: sendData,
+        onProgress: onProgress);
+  }
+}
diff --git a/packages/webview_flutter/webview_flutter_web/pubspec.yaml b/packages/webview_flutter/webview_flutter_web/pubspec.yaml
new file mode 100644
index 0000000..3b24476
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/pubspec.yaml
@@ -0,0 +1,32 @@
+name: webview_flutter_web
+description: A Flutter plugin that provides a WebView widget on web.
+repository: https://github.com/flutter/plugins/tree/master/packages/webview_flutter/webview_flutter_web
+issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
+version: 0.1.0
+
+environment:
+  sdk: ">=2.14.0 <3.0.0"
+  flutter: ">=2.5.0"
+
+flutter:
+  plugin:
+    implements: webview_flutter
+    platforms:
+      web:
+        pluginClass: WebWebViewPlatform
+        fileName: webview_flutter_web.dart
+
+dependencies:
+  flutter:
+    sdk: flutter
+  flutter_web_plugins:
+    sdk: flutter
+  webview_flutter_platform_interface: ^1.8.0
+
+dev_dependencies:
+  build_runner: ^2.1.5
+  flutter_driver:
+    sdk: flutter
+  flutter_test:
+    sdk: flutter
+  mockito: ^5.0.0
diff --git a/packages/webview_flutter/webview_flutter_web/test/webview_flutter_web_test.dart b/packages/webview_flutter/webview_flutter_web/test/webview_flutter_web_test.dart
new file mode 100644
index 0000000..90e2ea4
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/test/webview_flutter_web_test.dart
@@ -0,0 +1,130 @@
+// 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:html';
+import 'dart:typed_data';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:mockito/annotations.dart';
+import 'package:mockito/mockito.dart';
+import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';
+import 'package:webview_flutter_web/webview_flutter_web.dart';
+import './webview_flutter_web_test.mocks.dart';
+
+@GenerateMocks(<Type>[
+  IFrameElement,
+  BuildContext,
+  CreationParams,
+  WebViewPlatformCallbacksHandler,
+  HttpRequestFactory,
+  HttpRequest,
+])
+void main() {
+  TestWidgetsFlutterBinding.ensureInitialized();
+
+  group('WebWebViewPlatform', () {
+    test('build returns a HtmlElementView', () {
+      // Setup
+      final WebWebViewPlatform platform = WebWebViewPlatform();
+      // Run
+      final Widget widget = platform.build(
+        context: MockBuildContext(),
+        creationParams: CreationParams(),
+        webViewPlatformCallbacksHandler: MockWebViewPlatformCallbacksHandler(),
+        javascriptChannelRegistry: null,
+      );
+      // Verify
+      expect(widget, isA<HtmlElementView>());
+    });
+  });
+
+  group('WebWebViewPlatformController', () {
+    test('loadUrl sets url on iframe src attribute', () {
+      // Setup
+      final MockIFrameElement mockElement = MockIFrameElement();
+      final WebWebViewPlatformController controller =
+          WebWebViewPlatformController(
+        mockElement,
+      );
+      // Run
+      controller.loadUrl('test url', null);
+      // Verify
+      verify(mockElement.src = 'test url');
+    });
+
+    test('loadHtmlString loads html into iframe', () {
+      // Setup
+      final MockIFrameElement mockElement = MockIFrameElement();
+      final WebWebViewPlatformController controller =
+          WebWebViewPlatformController(
+        mockElement,
+      );
+      // Run
+      controller.loadHtmlString('test html');
+      // Verify
+      verify(mockElement.src = 'data:text/html,' + Uri.encodeFull('test html'));
+    });
+
+    group('loadRequest', () {
+      test('loadRequest throws ArgumentError on missing scheme', () {
+        // Setup
+        final MockIFrameElement mockElement = MockIFrameElement();
+        final WebWebViewPlatformController controller =
+            WebWebViewPlatformController(
+          mockElement,
+        );
+        // Run & Verify
+        expect(
+            () async => await controller.loadRequest(
+                  WebViewRequest(
+                    uri: Uri.parse('flutter.dev'),
+                    method: WebViewRequestMethod.get,
+                  ),
+                ),
+            throwsA(const TypeMatcher<ArgumentError>()));
+      });
+
+      test('loadRequest makes request and loads response into iframe',
+          () async {
+        // Setup
+        final MockIFrameElement mockElement = MockIFrameElement();
+        final WebWebViewPlatformController controller =
+            WebWebViewPlatformController(
+          mockElement,
+        );
+        final MockHttpRequest mockHttpRequest = MockHttpRequest();
+        when(mockHttpRequest.getResponseHeader('content-type'))
+            .thenReturn('text/plain');
+        when(mockHttpRequest.responseText).thenReturn('test data');
+        final MockHttpRequestFactory mockHttpRequestFactory =
+            MockHttpRequestFactory();
+        when(mockHttpRequestFactory.request(
+          any,
+          method: anyNamed('method'),
+          requestHeaders: anyNamed('requestHeaders'),
+          sendData: anyNamed('sendData'),
+        )).thenAnswer((_) => Future<HttpRequest>.value(mockHttpRequest));
+        controller.httpRequestFactory = mockHttpRequestFactory;
+        // Run
+        await controller.loadRequest(
+          WebViewRequest(
+              uri: Uri.parse('https://flutter.dev'),
+              method: WebViewRequestMethod.post,
+              body: Uint8List.fromList('test body'.codeUnits),
+              headers: <String, String>{'Foo': 'Bar'}),
+        );
+        // Verify
+        verify(mockHttpRequestFactory.request(
+          'https://flutter.dev',
+          method: 'post',
+          requestHeaders: <String, String>{'Foo': 'Bar'},
+          sendData: Uint8List.fromList('test body'.codeUnits),
+        ));
+        verify(
+            mockElement.src = 'data:text/plain,' + Uri.encodeFull('test data'));
+      });
+    });
+  });
+}
diff --git a/packages/webview_flutter/webview_flutter_web/test/webview_flutter_web_test.mocks.dart b/packages/webview_flutter/webview_flutter_web/test/webview_flutter_web_test.mocks.dart
new file mode 100644
index 0000000..2507cd2
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_web/test/webview_flutter_web_test.mocks.dart
@@ -0,0 +1,1285 @@
+// 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.
+
+// Mocks generated by Mockito 5.0.16 from annotations
+// in webview_flutter_web/test/webview_flutter_web_test.dart.
+// Do not manually edit this file.
+
+import 'dart:async' as _i6;
+import 'dart:html' as _i2;
+import 'dart:math' as _i3;
+
+import 'package:flutter/foundation.dart' as _i5;
+import 'package:flutter/widgets.dart' as _i4;
+import 'package:mockito/mockito.dart' as _i1;
+import 'package:webview_flutter_platform_interface/src/types/auto_media_playback_policy.dart'
+    as _i8;
+import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i7;
+import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart'
+    as _i9;
+import 'package:webview_flutter_web/webview_flutter_web.dart' as _i10;
+
+// ignore_for_file: avoid_redundant_argument_values
+// ignore_for_file: avoid_setters_without_getters
+// ignore_for_file: comment_references
+// ignore_for_file: implementation_imports
+// ignore_for_file: invalid_use_of_visible_for_testing_member
+// ignore_for_file: prefer_const_constructors
+// ignore_for_file: unnecessary_parenthesis
+// ignore_for_file: camel_case_types
+
+class _FakeCssClassSet_0 extends _i1.Fake implements _i2.CssClassSet {}
+
+class _FakeRectangle_1<T extends num> extends _i1.Fake
+    implements _i3.Rectangle<T> {}
+
+class _FakeCssRect_2 extends _i1.Fake implements _i2.CssRect {}
+
+class _FakePoint_3<T extends num> extends _i1.Fake implements _i3.Point<T> {}
+
+class _FakeElementEvents_4 extends _i1.Fake implements _i2.ElementEvents {}
+
+class _FakeCssStyleDeclaration_5 extends _i1.Fake
+    implements _i2.CssStyleDeclaration {}
+
+class _FakeElementStream_6<T extends _i2.Event> extends _i1.Fake
+    implements _i2.ElementStream<T> {}
+
+class _FakeElementList_7<T extends _i2.Element> extends _i1.Fake
+    implements _i2.ElementList<T> {}
+
+class _FakeScrollState_8 extends _i1.Fake implements _i2.ScrollState {}
+
+class _FakeAnimation_9 extends _i1.Fake implements _i2.Animation {}
+
+class _FakeElement_10 extends _i1.Fake implements _i2.Element {}
+
+class _FakeShadowRoot_11 extends _i1.Fake implements _i2.ShadowRoot {}
+
+class _FakeDocumentFragment_12 extends _i1.Fake
+    implements _i2.DocumentFragment {}
+
+class _FakeNode_13 extends _i1.Fake implements _i2.Node {}
+
+class _FakeWidget_14 extends _i1.Fake implements _i4.Widget {
+  @override
+  String toString({_i5.DiagnosticLevel? minLevel = _i5.DiagnosticLevel.info}) =>
+      super.toString();
+}
+
+class _FakeInheritedWidget_15 extends _i1.Fake implements _i4.InheritedWidget {
+  @override
+  String toString({_i5.DiagnosticLevel? minLevel = _i5.DiagnosticLevel.info}) =>
+      super.toString();
+}
+
+class _FakeDiagnosticsNode_16 extends _i1.Fake implements _i5.DiagnosticsNode {
+  @override
+  String toString(
+          {_i5.TextTreeConfiguration? parentConfiguration,
+          _i5.DiagnosticLevel? minLevel = _i5.DiagnosticLevel.info}) =>
+      super.toString();
+}
+
+class _FakeHttpRequest_17 extends _i1.Fake implements _i2.HttpRequest {}
+
+class _FakeHttpRequestUpload_18 extends _i1.Fake
+    implements _i2.HttpRequestUpload {}
+
+class _FakeEvents_19 extends _i1.Fake implements _i2.Events {}
+
+/// A class which mocks [IFrameElement].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockIFrameElement extends _i1.Mock implements _i2.IFrameElement {
+  MockIFrameElement() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  set allow(String? value) =>
+      super.noSuchMethod(Invocation.setter(#allow, value),
+          returnValueForMissingStub: null);
+  @override
+  set allowFullscreen(bool? value) =>
+      super.noSuchMethod(Invocation.setter(#allowFullscreen, value),
+          returnValueForMissingStub: null);
+  @override
+  set allowPaymentRequest(bool? value) =>
+      super.noSuchMethod(Invocation.setter(#allowPaymentRequest, value),
+          returnValueForMissingStub: null);
+  @override
+  set csp(String? value) => super.noSuchMethod(Invocation.setter(#csp, value),
+      returnValueForMissingStub: null);
+  @override
+  set height(String? value) =>
+      super.noSuchMethod(Invocation.setter(#height, value),
+          returnValueForMissingStub: null);
+  @override
+  set name(String? value) => super.noSuchMethod(Invocation.setter(#name, value),
+      returnValueForMissingStub: null);
+  @override
+  set referrerPolicy(String? value) =>
+      super.noSuchMethod(Invocation.setter(#referrerPolicy, value),
+          returnValueForMissingStub: null);
+  @override
+  set src(String? value) => super.noSuchMethod(Invocation.setter(#src, value),
+      returnValueForMissingStub: null);
+  @override
+  set srcdoc(String? value) =>
+      super.noSuchMethod(Invocation.setter(#srcdoc, value),
+          returnValueForMissingStub: null);
+  @override
+  set width(String? value) =>
+      super.noSuchMethod(Invocation.setter(#width, value),
+          returnValueForMissingStub: null);
+  @override
+  set nonce(String? value) =>
+      super.noSuchMethod(Invocation.setter(#nonce, value),
+          returnValueForMissingStub: null);
+  @override
+  Map<String, String> get attributes =>
+      (super.noSuchMethod(Invocation.getter(#attributes),
+          returnValue: <String, String>{}) as Map<String, String>);
+  @override
+  set attributes(Map<String, String>? value) =>
+      super.noSuchMethod(Invocation.setter(#attributes, value),
+          returnValueForMissingStub: null);
+  @override
+  List<_i2.Element> get children =>
+      (super.noSuchMethod(Invocation.getter(#children),
+          returnValue: <_i2.Element>[]) as List<_i2.Element>);
+  @override
+  set children(List<_i2.Element>? value) =>
+      super.noSuchMethod(Invocation.setter(#children, value),
+          returnValueForMissingStub: null);
+  @override
+  _i2.CssClassSet get classes =>
+      (super.noSuchMethod(Invocation.getter(#classes),
+          returnValue: _FakeCssClassSet_0()) as _i2.CssClassSet);
+  @override
+  set classes(Iterable<String>? value) =>
+      super.noSuchMethod(Invocation.setter(#classes, value),
+          returnValueForMissingStub: null);
+  @override
+  Map<String, String> get dataset =>
+      (super.noSuchMethod(Invocation.getter(#dataset),
+          returnValue: <String, String>{}) as Map<String, String>);
+  @override
+  set dataset(Map<String, String>? value) =>
+      super.noSuchMethod(Invocation.setter(#dataset, value),
+          returnValueForMissingStub: null);
+  @override
+  _i3.Rectangle<num> get client =>
+      (super.noSuchMethod(Invocation.getter(#client),
+          returnValue: _FakeRectangle_1<num>()) as _i3.Rectangle<num>);
+  @override
+  _i3.Rectangle<num> get offset =>
+      (super.noSuchMethod(Invocation.getter(#offset),
+          returnValue: _FakeRectangle_1<num>()) as _i3.Rectangle<num>);
+  @override
+  String get localName =>
+      (super.noSuchMethod(Invocation.getter(#localName), returnValue: '')
+          as String);
+  @override
+  _i2.CssRect get contentEdge =>
+      (super.noSuchMethod(Invocation.getter(#contentEdge),
+          returnValue: _FakeCssRect_2()) as _i2.CssRect);
+  @override
+  _i2.CssRect get paddingEdge =>
+      (super.noSuchMethod(Invocation.getter(#paddingEdge),
+          returnValue: _FakeCssRect_2()) as _i2.CssRect);
+  @override
+  _i2.CssRect get borderEdge =>
+      (super.noSuchMethod(Invocation.getter(#borderEdge),
+          returnValue: _FakeCssRect_2()) as _i2.CssRect);
+  @override
+  _i2.CssRect get marginEdge =>
+      (super.noSuchMethod(Invocation.getter(#marginEdge),
+          returnValue: _FakeCssRect_2()) as _i2.CssRect);
+  @override
+  _i3.Point<num> get documentOffset =>
+      (super.noSuchMethod(Invocation.getter(#documentOffset),
+          returnValue: _FakePoint_3<num>()) as _i3.Point<num>);
+  @override
+  set innerHtml(String? html) =>
+      super.noSuchMethod(Invocation.setter(#innerHtml, html),
+          returnValueForMissingStub: null);
+  @override
+  String get innerText =>
+      (super.noSuchMethod(Invocation.getter(#innerText), returnValue: '')
+          as String);
+  @override
+  set innerText(String? value) =>
+      super.noSuchMethod(Invocation.setter(#innerText, value),
+          returnValueForMissingStub: null);
+  @override
+  _i2.ElementEvents get on => (super.noSuchMethod(Invocation.getter(#on),
+      returnValue: _FakeElementEvents_4()) as _i2.ElementEvents);
+  @override
+  int get offsetHeight =>
+      (super.noSuchMethod(Invocation.getter(#offsetHeight), returnValue: 0)
+          as int);
+  @override
+  int get offsetLeft =>
+      (super.noSuchMethod(Invocation.getter(#offsetLeft), returnValue: 0)
+          as int);
+  @override
+  int get offsetTop =>
+      (super.noSuchMethod(Invocation.getter(#offsetTop), returnValue: 0)
+          as int);
+  @override
+  int get offsetWidth =>
+      (super.noSuchMethod(Invocation.getter(#offsetWidth), returnValue: 0)
+          as int);
+  @override
+  int get scrollHeight =>
+      (super.noSuchMethod(Invocation.getter(#scrollHeight), returnValue: 0)
+          as int);
+  @override
+  int get scrollLeft =>
+      (super.noSuchMethod(Invocation.getter(#scrollLeft), returnValue: 0)
+          as int);
+  @override
+  set scrollLeft(int? value) =>
+      super.noSuchMethod(Invocation.setter(#scrollLeft, value),
+          returnValueForMissingStub: null);
+  @override
+  int get scrollTop =>
+      (super.noSuchMethod(Invocation.getter(#scrollTop), returnValue: 0)
+          as int);
+  @override
+  set scrollTop(int? value) =>
+      super.noSuchMethod(Invocation.setter(#scrollTop, value),
+          returnValueForMissingStub: null);
+  @override
+  int get scrollWidth =>
+      (super.noSuchMethod(Invocation.getter(#scrollWidth), returnValue: 0)
+          as int);
+  @override
+  String get contentEditable =>
+      (super.noSuchMethod(Invocation.getter(#contentEditable), returnValue: '')
+          as String);
+  @override
+  set contentEditable(String? value) =>
+      super.noSuchMethod(Invocation.setter(#contentEditable, value),
+          returnValueForMissingStub: null);
+  @override
+  set dir(String? value) => super.noSuchMethod(Invocation.setter(#dir, value),
+      returnValueForMissingStub: null);
+  @override
+  bool get draggable =>
+      (super.noSuchMethod(Invocation.getter(#draggable), returnValue: false)
+          as bool);
+  @override
+  set draggable(bool? value) =>
+      super.noSuchMethod(Invocation.setter(#draggable, value),
+          returnValueForMissingStub: null);
+  @override
+  bool get hidden =>
+      (super.noSuchMethod(Invocation.getter(#hidden), returnValue: false)
+          as bool);
+  @override
+  set hidden(bool? value) =>
+      super.noSuchMethod(Invocation.setter(#hidden, value),
+          returnValueForMissingStub: null);
+  @override
+  set inert(bool? value) => super.noSuchMethod(Invocation.setter(#inert, value),
+      returnValueForMissingStub: null);
+  @override
+  set inputMode(String? value) =>
+      super.noSuchMethod(Invocation.setter(#inputMode, value),
+          returnValueForMissingStub: null);
+  @override
+  set lang(String? value) => super.noSuchMethod(Invocation.setter(#lang, value),
+      returnValueForMissingStub: null);
+  @override
+  set spellcheck(bool? value) =>
+      super.noSuchMethod(Invocation.setter(#spellcheck, value),
+          returnValueForMissingStub: null);
+  @override
+  _i2.CssStyleDeclaration get style => (super.noSuchMethod(
+      Invocation.getter(#style),
+      returnValue: _FakeCssStyleDeclaration_5()) as _i2.CssStyleDeclaration);
+  @override
+  set tabIndex(int? value) =>
+      super.noSuchMethod(Invocation.setter(#tabIndex, value),
+          returnValueForMissingStub: null);
+  @override
+  set title(String? value) =>
+      super.noSuchMethod(Invocation.setter(#title, value),
+          returnValueForMissingStub: null);
+  @override
+  set translate(bool? value) =>
+      super.noSuchMethod(Invocation.setter(#translate, value),
+          returnValueForMissingStub: null);
+  @override
+  String get className =>
+      (super.noSuchMethod(Invocation.getter(#className), returnValue: '')
+          as String);
+  @override
+  set className(String? value) =>
+      super.noSuchMethod(Invocation.setter(#className, value),
+          returnValueForMissingStub: null);
+  @override
+  int get clientHeight =>
+      (super.noSuchMethod(Invocation.getter(#clientHeight), returnValue: 0)
+          as int);
+  @override
+  int get clientWidth =>
+      (super.noSuchMethod(Invocation.getter(#clientWidth), returnValue: 0)
+          as int);
+  @override
+  String get id =>
+      (super.noSuchMethod(Invocation.getter(#id), returnValue: '') as String);
+  @override
+  set id(String? value) => super.noSuchMethod(Invocation.setter(#id, value),
+      returnValueForMissingStub: null);
+  @override
+  set slot(String? value) => super.noSuchMethod(Invocation.setter(#slot, value),
+      returnValueForMissingStub: null);
+  @override
+  String get tagName =>
+      (super.noSuchMethod(Invocation.getter(#tagName), returnValue: '')
+          as String);
+  @override
+  _i2.ElementStream<_i2.Event> get onAbort =>
+      (super.noSuchMethod(Invocation.getter(#onAbort),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onBeforeCopy =>
+      (super.noSuchMethod(Invocation.getter(#onBeforeCopy),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onBeforeCut =>
+      (super.noSuchMethod(Invocation.getter(#onBeforeCut),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onBeforePaste =>
+      (super.noSuchMethod(Invocation.getter(#onBeforePaste),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onBlur =>
+      (super.noSuchMethod(Invocation.getter(#onBlur),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onCanPlay =>
+      (super.noSuchMethod(Invocation.getter(#onCanPlay),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onCanPlayThrough =>
+      (super.noSuchMethod(Invocation.getter(#onCanPlayThrough),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onChange =>
+      (super.noSuchMethod(Invocation.getter(#onChange),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onClick =>
+      (super.noSuchMethod(Invocation.getter(#onClick),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onContextMenu =>
+      (super.noSuchMethod(Invocation.getter(#onContextMenu),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.ClipboardEvent> get onCopy =>
+      (super.noSuchMethod(Invocation.getter(#onCopy),
+              returnValue: _FakeElementStream_6<_i2.ClipboardEvent>())
+          as _i2.ElementStream<_i2.ClipboardEvent>);
+  @override
+  _i2.ElementStream<_i2.ClipboardEvent> get onCut =>
+      (super.noSuchMethod(Invocation.getter(#onCut),
+              returnValue: _FakeElementStream_6<_i2.ClipboardEvent>())
+          as _i2.ElementStream<_i2.ClipboardEvent>);
+  @override
+  _i2.ElementStream<_i2.Event> get onDoubleClick =>
+      (super.noSuchMethod(Invocation.getter(#onDoubleClick),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onDrag =>
+      (super.noSuchMethod(Invocation.getter(#onDrag),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onDragEnd =>
+      (super.noSuchMethod(Invocation.getter(#onDragEnd),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onDragEnter =>
+      (super.noSuchMethod(Invocation.getter(#onDragEnter),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onDragLeave =>
+      (super.noSuchMethod(Invocation.getter(#onDragLeave),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onDragOver =>
+      (super.noSuchMethod(Invocation.getter(#onDragOver),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onDragStart =>
+      (super.noSuchMethod(Invocation.getter(#onDragStart),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onDrop =>
+      (super.noSuchMethod(Invocation.getter(#onDrop),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.Event> get onDurationChange =>
+      (super.noSuchMethod(Invocation.getter(#onDurationChange),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onEmptied =>
+      (super.noSuchMethod(Invocation.getter(#onEmptied),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onEnded =>
+      (super.noSuchMethod(Invocation.getter(#onEnded),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onError =>
+      (super.noSuchMethod(Invocation.getter(#onError),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onFocus =>
+      (super.noSuchMethod(Invocation.getter(#onFocus),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onInput =>
+      (super.noSuchMethod(Invocation.getter(#onInput),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onInvalid =>
+      (super.noSuchMethod(Invocation.getter(#onInvalid),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.KeyboardEvent> get onKeyDown =>
+      (super.noSuchMethod(Invocation.getter(#onKeyDown),
+              returnValue: _FakeElementStream_6<_i2.KeyboardEvent>())
+          as _i2.ElementStream<_i2.KeyboardEvent>);
+  @override
+  _i2.ElementStream<_i2.KeyboardEvent> get onKeyPress =>
+      (super.noSuchMethod(Invocation.getter(#onKeyPress),
+              returnValue: _FakeElementStream_6<_i2.KeyboardEvent>())
+          as _i2.ElementStream<_i2.KeyboardEvent>);
+  @override
+  _i2.ElementStream<_i2.KeyboardEvent> get onKeyUp =>
+      (super.noSuchMethod(Invocation.getter(#onKeyUp),
+              returnValue: _FakeElementStream_6<_i2.KeyboardEvent>())
+          as _i2.ElementStream<_i2.KeyboardEvent>);
+  @override
+  _i2.ElementStream<_i2.Event> get onLoad =>
+      (super.noSuchMethod(Invocation.getter(#onLoad),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onLoadedData =>
+      (super.noSuchMethod(Invocation.getter(#onLoadedData),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onLoadedMetadata =>
+      (super.noSuchMethod(Invocation.getter(#onLoadedMetadata),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onMouseDown =>
+      (super.noSuchMethod(Invocation.getter(#onMouseDown),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onMouseEnter =>
+      (super.noSuchMethod(Invocation.getter(#onMouseEnter),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onMouseLeave =>
+      (super.noSuchMethod(Invocation.getter(#onMouseLeave),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onMouseMove =>
+      (super.noSuchMethod(Invocation.getter(#onMouseMove),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onMouseOut =>
+      (super.noSuchMethod(Invocation.getter(#onMouseOut),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onMouseOver =>
+      (super.noSuchMethod(Invocation.getter(#onMouseOver),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.MouseEvent> get onMouseUp =>
+      (super.noSuchMethod(Invocation.getter(#onMouseUp),
+              returnValue: _FakeElementStream_6<_i2.MouseEvent>())
+          as _i2.ElementStream<_i2.MouseEvent>);
+  @override
+  _i2.ElementStream<_i2.WheelEvent> get onMouseWheel =>
+      (super.noSuchMethod(Invocation.getter(#onMouseWheel),
+              returnValue: _FakeElementStream_6<_i2.WheelEvent>())
+          as _i2.ElementStream<_i2.WheelEvent>);
+  @override
+  _i2.ElementStream<_i2.ClipboardEvent> get onPaste =>
+      (super.noSuchMethod(Invocation.getter(#onPaste),
+              returnValue: _FakeElementStream_6<_i2.ClipboardEvent>())
+          as _i2.ElementStream<_i2.ClipboardEvent>);
+  @override
+  _i2.ElementStream<_i2.Event> get onPause =>
+      (super.noSuchMethod(Invocation.getter(#onPause),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onPlay =>
+      (super.noSuchMethod(Invocation.getter(#onPlay),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onPlaying =>
+      (super.noSuchMethod(Invocation.getter(#onPlaying),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onRateChange =>
+      (super.noSuchMethod(Invocation.getter(#onRateChange),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onReset =>
+      (super.noSuchMethod(Invocation.getter(#onReset),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onResize =>
+      (super.noSuchMethod(Invocation.getter(#onResize),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onScroll =>
+      (super.noSuchMethod(Invocation.getter(#onScroll),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onSearch =>
+      (super.noSuchMethod(Invocation.getter(#onSearch),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onSeeked =>
+      (super.noSuchMethod(Invocation.getter(#onSeeked),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onSeeking =>
+      (super.noSuchMethod(Invocation.getter(#onSeeking),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onSelect =>
+      (super.noSuchMethod(Invocation.getter(#onSelect),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onSelectStart =>
+      (super.noSuchMethod(Invocation.getter(#onSelectStart),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onStalled =>
+      (super.noSuchMethod(Invocation.getter(#onStalled),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onSubmit =>
+      (super.noSuchMethod(Invocation.getter(#onSubmit),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onSuspend =>
+      (super.noSuchMethod(Invocation.getter(#onSuspend),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onTimeUpdate =>
+      (super.noSuchMethod(Invocation.getter(#onTimeUpdate),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.TouchEvent> get onTouchCancel =>
+      (super.noSuchMethod(Invocation.getter(#onTouchCancel),
+              returnValue: _FakeElementStream_6<_i2.TouchEvent>())
+          as _i2.ElementStream<_i2.TouchEvent>);
+  @override
+  _i2.ElementStream<_i2.TouchEvent> get onTouchEnd =>
+      (super.noSuchMethod(Invocation.getter(#onTouchEnd),
+              returnValue: _FakeElementStream_6<_i2.TouchEvent>())
+          as _i2.ElementStream<_i2.TouchEvent>);
+  @override
+  _i2.ElementStream<_i2.TouchEvent> get onTouchEnter =>
+      (super.noSuchMethod(Invocation.getter(#onTouchEnter),
+              returnValue: _FakeElementStream_6<_i2.TouchEvent>())
+          as _i2.ElementStream<_i2.TouchEvent>);
+  @override
+  _i2.ElementStream<_i2.TouchEvent> get onTouchLeave =>
+      (super.noSuchMethod(Invocation.getter(#onTouchLeave),
+              returnValue: _FakeElementStream_6<_i2.TouchEvent>())
+          as _i2.ElementStream<_i2.TouchEvent>);
+  @override
+  _i2.ElementStream<_i2.TouchEvent> get onTouchMove =>
+      (super.noSuchMethod(Invocation.getter(#onTouchMove),
+              returnValue: _FakeElementStream_6<_i2.TouchEvent>())
+          as _i2.ElementStream<_i2.TouchEvent>);
+  @override
+  _i2.ElementStream<_i2.TouchEvent> get onTouchStart =>
+      (super.noSuchMethod(Invocation.getter(#onTouchStart),
+              returnValue: _FakeElementStream_6<_i2.TouchEvent>())
+          as _i2.ElementStream<_i2.TouchEvent>);
+  @override
+  _i2.ElementStream<_i2.TransitionEvent> get onTransitionEnd =>
+      (super.noSuchMethod(Invocation.getter(#onTransitionEnd),
+              returnValue: _FakeElementStream_6<_i2.TransitionEvent>())
+          as _i2.ElementStream<_i2.TransitionEvent>);
+  @override
+  _i2.ElementStream<_i2.Event> get onVolumeChange =>
+      (super.noSuchMethod(Invocation.getter(#onVolumeChange),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onWaiting =>
+      (super.noSuchMethod(Invocation.getter(#onWaiting),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onFullscreenChange =>
+      (super.noSuchMethod(Invocation.getter(#onFullscreenChange),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.Event> get onFullscreenError =>
+      (super.noSuchMethod(Invocation.getter(#onFullscreenError),
+              returnValue: _FakeElementStream_6<_i2.Event>())
+          as _i2.ElementStream<_i2.Event>);
+  @override
+  _i2.ElementStream<_i2.WheelEvent> get onWheel =>
+      (super.noSuchMethod(Invocation.getter(#onWheel),
+              returnValue: _FakeElementStream_6<_i2.WheelEvent>())
+          as _i2.ElementStream<_i2.WheelEvent>);
+  @override
+  List<_i2.Node> get nodes =>
+      (super.noSuchMethod(Invocation.getter(#nodes), returnValue: <_i2.Node>[])
+          as List<_i2.Node>);
+  @override
+  set nodes(Iterable<_i2.Node>? value) =>
+      super.noSuchMethod(Invocation.setter(#nodes, value),
+          returnValueForMissingStub: null);
+  @override
+  List<_i2.Node> get childNodes =>
+      (super.noSuchMethod(Invocation.getter(#childNodes),
+          returnValue: <_i2.Node>[]) as List<_i2.Node>);
+  @override
+  int get nodeType =>
+      (super.noSuchMethod(Invocation.getter(#nodeType), returnValue: 0) as int);
+  @override
+  set text(String? value) => super.noSuchMethod(Invocation.setter(#text, value),
+      returnValueForMissingStub: null);
+  @override
+  String? getAttribute(String? name) =>
+      (super.noSuchMethod(Invocation.method(#getAttribute, [name])) as String?);
+  @override
+  String? getAttributeNS(String? namespaceURI, String? name) =>
+      (super.noSuchMethod(
+          Invocation.method(#getAttributeNS, [namespaceURI, name])) as String?);
+  @override
+  bool hasAttribute(String? name) =>
+      (super.noSuchMethod(Invocation.method(#hasAttribute, [name]),
+          returnValue: false) as bool);
+  @override
+  bool hasAttributeNS(String? namespaceURI, String? name) => (super
+      .noSuchMethod(Invocation.method(#hasAttributeNS, [namespaceURI, name]),
+          returnValue: false) as bool);
+  @override
+  void removeAttribute(String? name) =>
+      super.noSuchMethod(Invocation.method(#removeAttribute, [name]),
+          returnValueForMissingStub: null);
+  @override
+  void removeAttributeNS(String? namespaceURI, String? name) => super
+      .noSuchMethod(Invocation.method(#removeAttributeNS, [namespaceURI, name]),
+          returnValueForMissingStub: null);
+  @override
+  void setAttribute(String? name, Object? value) =>
+      super.noSuchMethod(Invocation.method(#setAttribute, [name, value]),
+          returnValueForMissingStub: null);
+  @override
+  void setAttributeNS(String? namespaceURI, String? name, Object? value) =>
+      super.noSuchMethod(
+          Invocation.method(#setAttributeNS, [namespaceURI, name, value]),
+          returnValueForMissingStub: null);
+  @override
+  _i2.ElementList<T> querySelectorAll<T extends _i2.Element>(
+          String? selectors) =>
+      (super.noSuchMethod(Invocation.method(#querySelectorAll, [selectors]),
+          returnValue: _FakeElementList_7<T>()) as _i2.ElementList<T>);
+  @override
+  _i6.Future<_i2.ScrollState> setApplyScroll(String? nativeScrollBehavior) =>
+      (super.noSuchMethod(
+              Invocation.method(#setApplyScroll, [nativeScrollBehavior]),
+              returnValue: Future<_i2.ScrollState>.value(_FakeScrollState_8()))
+          as _i6.Future<_i2.ScrollState>);
+  @override
+  _i6.Future<_i2.ScrollState> setDistributeScroll(
+          String? nativeScrollBehavior) =>
+      (super.noSuchMethod(
+              Invocation.method(#setDistributeScroll, [nativeScrollBehavior]),
+              returnValue: Future<_i2.ScrollState>.value(_FakeScrollState_8()))
+          as _i6.Future<_i2.ScrollState>);
+  @override
+  Map<String, String> getNamespacedAttributes(String? namespace) => (super
+      .noSuchMethod(Invocation.method(#getNamespacedAttributes, [namespace]),
+          returnValue: <String, String>{}) as Map<String, String>);
+  @override
+  _i2.CssStyleDeclaration getComputedStyle([String? pseudoElement]) =>
+      (super.noSuchMethod(Invocation.method(#getComputedStyle, [pseudoElement]),
+              returnValue: _FakeCssStyleDeclaration_5())
+          as _i2.CssStyleDeclaration);
+  @override
+  void appendText(String? text) =>
+      super.noSuchMethod(Invocation.method(#appendText, [text]),
+          returnValueForMissingStub: null);
+  @override
+  void appendHtml(String? text,
+          {_i2.NodeValidator? validator,
+          _i2.NodeTreeSanitizer? treeSanitizer}) =>
+      super.noSuchMethod(
+          Invocation.method(#appendHtml, [text],
+              {#validator: validator, #treeSanitizer: treeSanitizer}),
+          returnValueForMissingStub: null);
+  @override
+  void attached() => super.noSuchMethod(Invocation.method(#attached, []),
+      returnValueForMissingStub: null);
+  @override
+  void detached() => super.noSuchMethod(Invocation.method(#detached, []),
+      returnValueForMissingStub: null);
+  @override
+  void enteredView() => super.noSuchMethod(Invocation.method(#enteredView, []),
+      returnValueForMissingStub: null);
+  @override
+  List<_i3.Rectangle<num>> getClientRects() =>
+      (super.noSuchMethod(Invocation.method(#getClientRects, []),
+          returnValue: <_i3.Rectangle<num>>[]) as List<_i3.Rectangle<num>>);
+  @override
+  void leftView() => super.noSuchMethod(Invocation.method(#leftView, []),
+      returnValueForMissingStub: null);
+  @override
+  _i2.Animation animate(Iterable<Map<String, dynamic>>? frames,
+          [dynamic timing]) =>
+      (super.noSuchMethod(Invocation.method(#animate, [frames, timing]),
+          returnValue: _FakeAnimation_9()) as _i2.Animation);
+  @override
+  void attributeChanged(String? name, String? oldValue, String? newValue) =>
+      super.noSuchMethod(
+          Invocation.method(#attributeChanged, [name, oldValue, newValue]),
+          returnValueForMissingStub: null);
+  @override
+  String toString() => super.toString();
+  @override
+  void scrollIntoView([_i2.ScrollAlignment? alignment]) =>
+      super.noSuchMethod(Invocation.method(#scrollIntoView, [alignment]),
+          returnValueForMissingStub: null);
+  @override
+  void insertAdjacentText(String? where, String? text) =>
+      super.noSuchMethod(Invocation.method(#insertAdjacentText, [where, text]),
+          returnValueForMissingStub: null);
+  @override
+  void insertAdjacentHtml(String? where, String? html,
+          {_i2.NodeValidator? validator,
+          _i2.NodeTreeSanitizer? treeSanitizer}) =>
+      super.noSuchMethod(
+          Invocation.method(#insertAdjacentHtml, [where, html],
+              {#validator: validator, #treeSanitizer: treeSanitizer}),
+          returnValueForMissingStub: null);
+  @override
+  _i2.Element insertAdjacentElement(String? where, _i2.Element? element) =>
+      (super.noSuchMethod(
+          Invocation.method(#insertAdjacentElement, [where, element]),
+          returnValue: _FakeElement_10()) as _i2.Element);
+  @override
+  bool matches(String? selectors) =>
+      (super.noSuchMethod(Invocation.method(#matches, [selectors]),
+          returnValue: false) as bool);
+  @override
+  bool matchesWithAncestors(String? selectors) =>
+      (super.noSuchMethod(Invocation.method(#matchesWithAncestors, [selectors]),
+          returnValue: false) as bool);
+  @override
+  _i2.ShadowRoot createShadowRoot() =>
+      (super.noSuchMethod(Invocation.method(#createShadowRoot, []),
+          returnValue: _FakeShadowRoot_11()) as _i2.ShadowRoot);
+  @override
+  _i3.Point<num> offsetTo(_i2.Element? parent) =>
+      (super.noSuchMethod(Invocation.method(#offsetTo, [parent]),
+          returnValue: _FakePoint_3<num>()) as _i3.Point<num>);
+  @override
+  _i2.DocumentFragment createFragment(String? html,
+          {_i2.NodeValidator? validator,
+          _i2.NodeTreeSanitizer? treeSanitizer}) =>
+      (super.noSuchMethod(
+          Invocation.method(#createFragment, [html],
+              {#validator: validator, #treeSanitizer: treeSanitizer}),
+          returnValue: _FakeDocumentFragment_12()) as _i2.DocumentFragment);
+  @override
+  void setInnerHtml(String? html,
+          {_i2.NodeValidator? validator,
+          _i2.NodeTreeSanitizer? treeSanitizer}) =>
+      super.noSuchMethod(
+          Invocation.method(#setInnerHtml, [html],
+              {#validator: validator, #treeSanitizer: treeSanitizer}),
+          returnValueForMissingStub: null);
+  @override
+  void blur() => super.noSuchMethod(Invocation.method(#blur, []),
+      returnValueForMissingStub: null);
+  @override
+  void click() => super.noSuchMethod(Invocation.method(#click, []),
+      returnValueForMissingStub: null);
+  @override
+  void focus() => super.noSuchMethod(Invocation.method(#focus, []),
+      returnValueForMissingStub: null);
+  @override
+  _i2.ShadowRoot attachShadow(Map<dynamic, dynamic>? shadowRootInitDict) =>
+      (super.noSuchMethod(
+          Invocation.method(#attachShadow, [shadowRootInitDict]),
+          returnValue: _FakeShadowRoot_11()) as _i2.ShadowRoot);
+  @override
+  _i2.Element? closest(String? selectors) =>
+      (super.noSuchMethod(Invocation.method(#closest, [selectors]))
+          as _i2.Element?);
+  @override
+  List<_i2.Animation> getAnimations() =>
+      (super.noSuchMethod(Invocation.method(#getAnimations, []),
+          returnValue: <_i2.Animation>[]) as List<_i2.Animation>);
+  @override
+  List<String> getAttributeNames() =>
+      (super.noSuchMethod(Invocation.method(#getAttributeNames, []),
+          returnValue: <String>[]) as List<String>);
+  @override
+  _i3.Rectangle<num> getBoundingClientRect() =>
+      (super.noSuchMethod(Invocation.method(#getBoundingClientRect, []),
+          returnValue: _FakeRectangle_1<num>()) as _i3.Rectangle<num>);
+  @override
+  List<_i2.Node> getDestinationInsertionPoints() =>
+      (super.noSuchMethod(Invocation.method(#getDestinationInsertionPoints, []),
+          returnValue: <_i2.Node>[]) as List<_i2.Node>);
+  @override
+  List<_i2.Node> getElementsByClassName(String? classNames) => (super
+      .noSuchMethod(Invocation.method(#getElementsByClassName, [classNames]),
+          returnValue: <_i2.Node>[]) as List<_i2.Node>);
+  @override
+  bool hasPointerCapture(int? pointerId) =>
+      (super.noSuchMethod(Invocation.method(#hasPointerCapture, [pointerId]),
+          returnValue: false) as bool);
+  @override
+  void releasePointerCapture(int? pointerId) =>
+      super.noSuchMethod(Invocation.method(#releasePointerCapture, [pointerId]),
+          returnValueForMissingStub: null);
+  @override
+  void requestPointerLock() =>
+      super.noSuchMethod(Invocation.method(#requestPointerLock, []),
+          returnValueForMissingStub: null);
+  @override
+  void scroll([dynamic options_OR_x, num? y]) =>
+      super.noSuchMethod(Invocation.method(#scroll, [options_OR_x, y]),
+          returnValueForMissingStub: null);
+  @override
+  void scrollBy([dynamic options_OR_x, num? y]) =>
+      super.noSuchMethod(Invocation.method(#scrollBy, [options_OR_x, y]),
+          returnValueForMissingStub: null);
+  @override
+  void scrollTo([dynamic options_OR_x, num? y]) =>
+      super.noSuchMethod(Invocation.method(#scrollTo, [options_OR_x, y]),
+          returnValueForMissingStub: null);
+  @override
+  void setPointerCapture(int? pointerId) =>
+      super.noSuchMethod(Invocation.method(#setPointerCapture, [pointerId]),
+          returnValueForMissingStub: null);
+  @override
+  void requestFullscreen() =>
+      super.noSuchMethod(Invocation.method(#requestFullscreen, []),
+          returnValueForMissingStub: null);
+  @override
+  void after(Object? nodes) =>
+      super.noSuchMethod(Invocation.method(#after, [nodes]),
+          returnValueForMissingStub: null);
+  @override
+  void before(Object? nodes) =>
+      super.noSuchMethod(Invocation.method(#before, [nodes]),
+          returnValueForMissingStub: null);
+  @override
+  _i2.Element? querySelector(String? selectors) =>
+      (super.noSuchMethod(Invocation.method(#querySelector, [selectors]))
+          as _i2.Element?);
+  @override
+  void remove() => super.noSuchMethod(Invocation.method(#remove, []),
+      returnValueForMissingStub: null);
+  @override
+  _i2.Node replaceWith(_i2.Node? otherNode) =>
+      (super.noSuchMethod(Invocation.method(#replaceWith, [otherNode]),
+          returnValue: _FakeNode_13()) as _i2.Node);
+  @override
+  void insertAllBefore(Iterable<_i2.Node>? newNodes, _i2.Node? refChild) =>
+      super.noSuchMethod(
+          Invocation.method(#insertAllBefore, [newNodes, refChild]),
+          returnValueForMissingStub: null);
+  @override
+  _i2.Node append(_i2.Node? node) =>
+      (super.noSuchMethod(Invocation.method(#append, [node]),
+          returnValue: _FakeNode_13()) as _i2.Node);
+  @override
+  _i2.Node clone(bool? deep) =>
+      (super.noSuchMethod(Invocation.method(#clone, [deep]),
+          returnValue: _FakeNode_13()) as _i2.Node);
+  @override
+  bool contains(_i2.Node? other) =>
+      (super.noSuchMethod(Invocation.method(#contains, [other]),
+          returnValue: false) as bool);
+  @override
+  _i2.Node getRootNode([Map<dynamic, dynamic>? options]) =>
+      (super.noSuchMethod(Invocation.method(#getRootNode, [options]),
+          returnValue: _FakeNode_13()) as _i2.Node);
+  @override
+  bool hasChildNodes() =>
+      (super.noSuchMethod(Invocation.method(#hasChildNodes, []),
+          returnValue: false) as bool);
+  @override
+  _i2.Node insertBefore(_i2.Node? node, _i2.Node? child) =>
+      (super.noSuchMethod(Invocation.method(#insertBefore, [node, child]),
+          returnValue: _FakeNode_13()) as _i2.Node);
+  @override
+  void addEventListener(String? type, _i2.EventListener? listener,
+          [bool? useCapture]) =>
+      super.noSuchMethod(
+          Invocation.method(#addEventListener, [type, listener, useCapture]),
+          returnValueForMissingStub: null);
+  @override
+  void removeEventListener(String? type, _i2.EventListener? listener,
+          [bool? useCapture]) =>
+      super.noSuchMethod(
+          Invocation.method(#removeEventListener, [type, listener, useCapture]),
+          returnValueForMissingStub: null);
+  @override
+  bool dispatchEvent(_i2.Event? event) =>
+      (super.noSuchMethod(Invocation.method(#dispatchEvent, [event]),
+          returnValue: false) as bool);
+}
+
+/// A class which mocks [BuildContext].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockBuildContext extends _i1.Mock implements _i4.BuildContext {
+  MockBuildContext() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  _i4.Widget get widget => (super.noSuchMethod(Invocation.getter(#widget),
+      returnValue: _FakeWidget_14()) as _i4.Widget);
+  @override
+  bool get debugDoingBuild => (super
+          .noSuchMethod(Invocation.getter(#debugDoingBuild), returnValue: false)
+      as bool);
+  @override
+  _i4.InheritedWidget dependOnInheritedElement(_i4.InheritedElement? ancestor,
+          {Object? aspect}) =>
+      (super.noSuchMethod(
+          Invocation.method(
+              #dependOnInheritedElement, [ancestor], {#aspect: aspect}),
+          returnValue: _FakeInheritedWidget_15()) as _i4.InheritedWidget);
+  @override
+  void visitAncestorElements(bool Function(_i4.Element)? visitor) =>
+      super.noSuchMethod(Invocation.method(#visitAncestorElements, [visitor]),
+          returnValueForMissingStub: null);
+  @override
+  void visitChildElements(_i4.ElementVisitor? visitor) =>
+      super.noSuchMethod(Invocation.method(#visitChildElements, [visitor]),
+          returnValueForMissingStub: null);
+  @override
+  _i5.DiagnosticsNode describeElement(String? name,
+          {_i5.DiagnosticsTreeStyle? style =
+              _i5.DiagnosticsTreeStyle.errorProperty}) =>
+      (super.noSuchMethod(
+          Invocation.method(#describeElement, [name], {#style: style}),
+          returnValue: _FakeDiagnosticsNode_16()) as _i5.DiagnosticsNode);
+  @override
+  _i5.DiagnosticsNode describeWidget(String? name,
+          {_i5.DiagnosticsTreeStyle? style =
+              _i5.DiagnosticsTreeStyle.errorProperty}) =>
+      (super.noSuchMethod(
+          Invocation.method(#describeWidget, [name], {#style: style}),
+          returnValue: _FakeDiagnosticsNode_16()) as _i5.DiagnosticsNode);
+  @override
+  List<_i5.DiagnosticsNode> describeMissingAncestor(
+          {Type? expectedAncestorType}) =>
+      (super.noSuchMethod(
+          Invocation.method(#describeMissingAncestor, [],
+              {#expectedAncestorType: expectedAncestorType}),
+          returnValue: <_i5.DiagnosticsNode>[]) as List<_i5.DiagnosticsNode>);
+  @override
+  _i5.DiagnosticsNode describeOwnershipChain(String? name) =>
+      (super.noSuchMethod(Invocation.method(#describeOwnershipChain, [name]),
+          returnValue: _FakeDiagnosticsNode_16()) as _i5.DiagnosticsNode);
+  @override
+  String toString() => super.toString();
+}
+
+/// A class which mocks [CreationParams].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockCreationParams extends _i1.Mock implements _i7.CreationParams {
+  MockCreationParams() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  Set<String> get javascriptChannelNames =>
+      (super.noSuchMethod(Invocation.getter(#javascriptChannelNames),
+          returnValue: <String>{}) as Set<String>);
+  @override
+  _i8.AutoMediaPlaybackPolicy get autoMediaPlaybackPolicy =>
+      (super.noSuchMethod(Invocation.getter(#autoMediaPlaybackPolicy),
+              returnValue: _i8.AutoMediaPlaybackPolicy
+                  .require_user_action_for_all_media_types)
+          as _i8.AutoMediaPlaybackPolicy);
+  @override
+  List<_i7.WebViewCookie> get cookies =>
+      (super.noSuchMethod(Invocation.getter(#cookies),
+          returnValue: <_i7.WebViewCookie>[]) as List<_i7.WebViewCookie>);
+  @override
+  String toString() => super.toString();
+}
+
+/// A class which mocks [WebViewPlatformCallbacksHandler].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockWebViewPlatformCallbacksHandler extends _i1.Mock
+    implements _i9.WebViewPlatformCallbacksHandler {
+  MockWebViewPlatformCallbacksHandler() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  _i6.FutureOr<bool> onNavigationRequest({String? url, bool? isForMainFrame}) =>
+      (super.noSuchMethod(
+          Invocation.method(#onNavigationRequest, [],
+              {#url: url, #isForMainFrame: isForMainFrame}),
+          returnValue: Future<bool>.value(false)) as _i6.FutureOr<bool>);
+  @override
+  void onPageStarted(String? url) =>
+      super.noSuchMethod(Invocation.method(#onPageStarted, [url]),
+          returnValueForMissingStub: null);
+  @override
+  void onPageFinished(String? url) =>
+      super.noSuchMethod(Invocation.method(#onPageFinished, [url]),
+          returnValueForMissingStub: null);
+  @override
+  void onProgress(int? progress) =>
+      super.noSuchMethod(Invocation.method(#onProgress, [progress]),
+          returnValueForMissingStub: null);
+  @override
+  void onWebResourceError(_i7.WebResourceError? error) =>
+      super.noSuchMethod(Invocation.method(#onWebResourceError, [error]),
+          returnValueForMissingStub: null);
+  @override
+  String toString() => super.toString();
+}
+
+/// A class which mocks [HttpRequestFactory].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockHttpRequestFactory extends _i1.Mock
+    implements _i10.HttpRequestFactory {
+  MockHttpRequestFactory() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  _i6.Future<_i2.HttpRequest> request(String? url,
+          {String? method,
+          bool? withCredentials,
+          String? responseType,
+          String? mimeType,
+          Map<String, String>? requestHeaders,
+          dynamic sendData,
+          void Function(_i2.ProgressEvent)? onProgress}) =>
+      (super.noSuchMethod(
+              Invocation.method(#request, [
+                url
+              ], {
+                #method: method,
+                #withCredentials: withCredentials,
+                #responseType: responseType,
+                #mimeType: mimeType,
+                #requestHeaders: requestHeaders,
+                #sendData: sendData,
+                #onProgress: onProgress
+              }),
+              returnValue: Future<_i2.HttpRequest>.value(_FakeHttpRequest_17()))
+          as _i6.Future<_i2.HttpRequest>);
+  @override
+  String toString() => super.toString();
+}
+
+/// A class which mocks [HttpRequest].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockHttpRequest extends _i1.Mock implements _i2.HttpRequest {
+  MockHttpRequest() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  Map<String, String> get responseHeaders =>
+      (super.noSuchMethod(Invocation.getter(#responseHeaders),
+          returnValue: <String, String>{}) as Map<String, String>);
+  @override
+  int get readyState =>
+      (super.noSuchMethod(Invocation.getter(#readyState), returnValue: 0)
+          as int);
+  @override
+  String get responseType =>
+      (super.noSuchMethod(Invocation.getter(#responseType), returnValue: '')
+          as String);
+  @override
+  set responseType(String? value) =>
+      super.noSuchMethod(Invocation.setter(#responseType, value),
+          returnValueForMissingStub: null);
+  @override
+  set timeout(int? value) =>
+      super.noSuchMethod(Invocation.setter(#timeout, value),
+          returnValueForMissingStub: null);
+  @override
+  _i2.HttpRequestUpload get upload =>
+      (super.noSuchMethod(Invocation.getter(#upload),
+          returnValue: _FakeHttpRequestUpload_18()) as _i2.HttpRequestUpload);
+  @override
+  set withCredentials(bool? value) =>
+      super.noSuchMethod(Invocation.setter(#withCredentials, value),
+          returnValueForMissingStub: null);
+  @override
+  _i6.Stream<_i2.Event> get onReadyStateChange =>
+      (super.noSuchMethod(Invocation.getter(#onReadyStateChange),
+          returnValue: Stream<_i2.Event>.empty()) as _i6.Stream<_i2.Event>);
+  @override
+  _i6.Stream<_i2.ProgressEvent> get onAbort =>
+      (super.noSuchMethod(Invocation.getter(#onAbort),
+              returnValue: Stream<_i2.ProgressEvent>.empty())
+          as _i6.Stream<_i2.ProgressEvent>);
+  @override
+  _i6.Stream<_i2.ProgressEvent> get onError =>
+      (super.noSuchMethod(Invocation.getter(#onError),
+              returnValue: Stream<_i2.ProgressEvent>.empty())
+          as _i6.Stream<_i2.ProgressEvent>);
+  @override
+  _i6.Stream<_i2.ProgressEvent> get onLoad =>
+      (super.noSuchMethod(Invocation.getter(#onLoad),
+              returnValue: Stream<_i2.ProgressEvent>.empty())
+          as _i6.Stream<_i2.ProgressEvent>);
+  @override
+  _i6.Stream<_i2.ProgressEvent> get onLoadEnd =>
+      (super.noSuchMethod(Invocation.getter(#onLoadEnd),
+              returnValue: Stream<_i2.ProgressEvent>.empty())
+          as _i6.Stream<_i2.ProgressEvent>);
+  @override
+  _i6.Stream<_i2.ProgressEvent> get onLoadStart =>
+      (super.noSuchMethod(Invocation.getter(#onLoadStart),
+              returnValue: Stream<_i2.ProgressEvent>.empty())
+          as _i6.Stream<_i2.ProgressEvent>);
+  @override
+  _i6.Stream<_i2.ProgressEvent> get onProgress =>
+      (super.noSuchMethod(Invocation.getter(#onProgress),
+              returnValue: Stream<_i2.ProgressEvent>.empty())
+          as _i6.Stream<_i2.ProgressEvent>);
+  @override
+  _i6.Stream<_i2.ProgressEvent> get onTimeout =>
+      (super.noSuchMethod(Invocation.getter(#onTimeout),
+              returnValue: Stream<_i2.ProgressEvent>.empty())
+          as _i6.Stream<_i2.ProgressEvent>);
+  @override
+  _i2.Events get on =>
+      (super.noSuchMethod(Invocation.getter(#on), returnValue: _FakeEvents_19())
+          as _i2.Events);
+  @override
+  void open(String? method, String? url,
+          {bool? async, String? user, String? password}) =>
+      super.noSuchMethod(
+          Invocation.method(#open, [method, url],
+              {#async: async, #user: user, #password: password}),
+          returnValueForMissingStub: null);
+  @override
+  void abort() => super.noSuchMethod(Invocation.method(#abort, []),
+      returnValueForMissingStub: null);
+  @override
+  String getAllResponseHeaders() =>
+      (super.noSuchMethod(Invocation.method(#getAllResponseHeaders, []),
+          returnValue: '') as String);
+  @override
+  String? getResponseHeader(String? name) =>
+      (super.noSuchMethod(Invocation.method(#getResponseHeader, [name]))
+          as String?);
+  @override
+  void overrideMimeType(String? mime) =>
+      super.noSuchMethod(Invocation.method(#overrideMimeType, [mime]),
+          returnValueForMissingStub: null);
+  @override
+  void send([dynamic body_OR_data]) =>
+      super.noSuchMethod(Invocation.method(#send, [body_OR_data]),
+          returnValueForMissingStub: null);
+  @override
+  void setRequestHeader(String? name, String? value) =>
+      super.noSuchMethod(Invocation.method(#setRequestHeader, [name, value]),
+          returnValueForMissingStub: null);
+  @override
+  void addEventListener(String? type, _i2.EventListener? listener,
+          [bool? useCapture]) =>
+      super.noSuchMethod(
+          Invocation.method(#addEventListener, [type, listener, useCapture]),
+          returnValueForMissingStub: null);
+  @override
+  void removeEventListener(String? type, _i2.EventListener? listener,
+          [bool? useCapture]) =>
+      super.noSuchMethod(
+          Invocation.method(#removeEventListener, [type, listener, useCapture]),
+          returnValueForMissingStub: null);
+  @override
+  bool dispatchEvent(_i2.Event? event) =>
+      (super.noSuchMethod(Invocation.method(#dispatchEvent, [event]),
+          returnValue: false) as bool);
+  @override
+  String toString() => super.toString();
+}