[webview_flutter] Migrate to nnbd (#3327)

diff --git a/packages/webview_flutter/CHANGELOG.md b/packages/webview_flutter/CHANGELOG.md
index 447e263..3526139 100644
--- a/packages/webview_flutter/CHANGELOG.md
+++ b/packages/webview_flutter/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 2.0.0-nullsafety
+
+* Migration to null-safety.
+
 ## 1.0.8
 
 * Update Flutter SDK constraint.
diff --git a/packages/webview_flutter/lib/platform_interface.dart b/packages/webview_flutter/lib/platform_interface.dart
index 6c991b1..f162e58 100644
--- a/packages/webview_flutter/lib/platform_interface.dart
+++ b/packages/webview_flutter/lib/platform_interface.dart
@@ -21,7 +21,8 @@
   /// Invoked by [WebViewPlatformController] when a navigation request is pending.
   ///
   /// If true is returned the navigation is allowed, otherwise it is blocked.
-  FutureOr<bool> onNavigationRequest({String url, bool isForMainFrame});
+  FutureOr<bool> onNavigationRequest(
+      {required String url, required bool isForMainFrame});
 
   /// Invoked by [WebViewPlatformController] when a page has started loading.
   void onPageStarted(String url);
@@ -103,8 +104,8 @@
   /// A user should not need to instantiate this class, but will receive one in
   /// [WebResourceErrorCallback].
   WebResourceError({
-    @required this.errorCode,
-    @required this.description,
+    required this.errorCode,
+    required this.description,
     this.domain,
     this.errorType,
     this.failingUrl,
@@ -131,7 +132,7 @@
   /// in Objective-C. See
   /// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorObjectsDomains/ErrorObjectsDomains.html
   /// for more information on error handling on iOS.
-  final String domain;
+  final String? domain;
 
   /// Description of the error that can be used to communicate the problem to the user.
   final String description;
@@ -139,13 +140,13 @@
   /// The type this error can be categorized as.
   ///
   /// This will never be `null` on Android, but can be `null` on iOS.
-  final WebResourceErrorType errorType;
+  final WebResourceErrorType? errorType;
 
   /// Gets the URL for which the resource request was made.
   ///
   /// This value is not provided on iOS. Alternatively, you can keep track of
   /// the last values provided to [WebViewPlatformController.loadUrl].
-  final String failingUrl;
+  final String? failingUrl;
 }
 
 /// Interface for talking to the webview's platform implementation.
@@ -176,7 +177,7 @@
   /// Throws an ArgumentError if `url` is not a valid URL string.
   Future<void> loadUrl(
     String url,
-    Map<String, String> headers,
+    Map<String, String>? headers,
   ) {
     throw UnimplementedError(
         "WebView loadUrl is not implemented on the current platform");
@@ -194,7 +195,7 @@
   /// Accessor to the current URL that the WebView is displaying.
   ///
   /// If no URL was ever loaded, returns `null`.
-  Future<String> currentUrl() {
+  Future<String?> currentUrl() {
     throw UnimplementedError(
         "WebView currentUrl is not implemented on the current platform");
   }
@@ -281,7 +282,7 @@
   }
 
   /// Returns the title of the currently loaded page.
-  Future<String> getTitle() {
+  Future<String?> getTitle() {
     throw UnimplementedError(
         "WebView getTitle is not implemented on the current platform");
   }
@@ -337,7 +338,7 @@
       : _value = value,
         isPresent = true;
 
-  final T _value;
+  final T? _value;
 
   /// The setting's value.
   ///
@@ -347,7 +348,14 @@
       throw StateError('Cannot access a value of an absent WebSetting');
     }
     assert(isPresent);
-    return _value;
+    // The intention of this getter is to return T whether it is nullable or
+    // not whereas _value is of type T? since _value can be null even when
+    // T is not nullable (when isPresent == false).
+    //
+    // We promote _value to T using `as T` instead of `!` operator to handle
+    // the case when _value is legitimately null (and T is a nullable type).
+    // `!` operator would always throw if _value is null.
+    return _value as T;
   }
 
   /// True when this web setting instance contains a value.
@@ -358,7 +366,7 @@
   @override
   bool operator ==(Object other) {
     if (other.runtimeType != runtimeType) return false;
-    final WebSetting<T> typedOther = other;
+    final WebSetting<T> typedOther = other as WebSetting<T>;
     return typedOther.isPresent == isPresent && typedOther._value == _value;
   }
 
@@ -382,19 +390,19 @@
     this.hasNavigationDelegate,
     this.debuggingEnabled,
     this.gestureNavigationEnabled,
-    @required this.userAgent,
+    required this.userAgent,
   }) : assert(userAgent != null);
 
   /// The JavaScript execution mode to be used by the webview.
-  final JavascriptMode javascriptMode;
+  final JavascriptMode? javascriptMode;
 
   /// Whether the [WebView] has a [NavigationDelegate] set.
-  final bool hasNavigationDelegate;
+  final bool? hasNavigationDelegate;
 
   /// Whether to enable the platform's webview content debugging tools.
   ///
   /// See also: [WebView.debuggingEnabled].
-  final bool debuggingEnabled;
+  final bool? debuggingEnabled;
 
   /// The value used for the HTTP `User-Agent:` request header.
   ///
@@ -404,12 +412,12 @@
   /// last time it was set.
   ///
   /// See also [WebView.userAgent].
-  final WebSetting<String> userAgent;
+  final WebSetting<String?> userAgent;
 
   /// Whether to allow swipe based navigation in iOS.
   ///
   /// See also: [WebView.gestureNavigationEnabled]
-  final bool gestureNavigationEnabled;
+  final bool? gestureNavigationEnabled;
 
   @override
   String toString() {
@@ -428,7 +436,7 @@
   CreationParams({
     this.initialUrl,
     this.webSettings,
-    this.javascriptChannelNames,
+    this.javascriptChannelNames = const <String>{},
     this.userAgent,
     this.autoMediaPlaybackPolicy =
         AutoMediaPlaybackPolicy.require_user_action_for_all_media_types,
@@ -437,12 +445,12 @@
   /// The initialUrl to load in the webview.
   ///
   /// When null the webview will be created without loading any page.
-  final String initialUrl;
+  final String? initialUrl;
 
   /// The initial [WebSettings] for the new webview.
   ///
   /// This can later be updated with [WebViewPlatformController.updateSettings].
-  final WebSettings webSettings;
+  final WebSettings? webSettings;
 
   /// The initial set of JavaScript channels that are configured for this webview.
   ///
@@ -460,7 +468,7 @@
   /// The value used for the HTTP User-Agent: request header.
   ///
   /// When null the platform's webview default is used for the User-Agent header.
-  final String userAgent;
+  final String? userAgent;
 
   /// Which restrictions apply on automatic media playback.
   final AutoMediaPlaybackPolicy autoMediaPlaybackPolicy;
@@ -475,7 +483,7 @@
 ///
 /// See also the `onWebViewPlatformCreated` argument for [WebViewPlatform.build].
 typedef WebViewPlatformCreatedCallback = void Function(
-    WebViewPlatformController webViewPlatformController);
+    WebViewPlatformController? webViewPlatformController);
 
 /// Interface for a platform implementation of a WebView.
 ///
@@ -505,14 +513,14 @@
   ///
   /// `webViewPlatformHandler` must not be null.
   Widget build({
-    BuildContext context,
+    required BuildContext context,
     // TODO(amirh): convert this to be the actual parameters.
     // I'm starting without it as the PR is starting to become pretty big.
     // I'll followup with the conversion PR.
-    CreationParams creationParams,
-    @required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
-    WebViewPlatformCreatedCallback onWebViewPlatformCreated,
-    Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
+    required CreationParams creationParams,
+    required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
+    WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
+    Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers,
   });
 
   /// Clears all cookies for all [WebView] instances.
diff --git a/packages/webview_flutter/lib/src/webview_android.dart b/packages/webview_flutter/lib/src/webview_android.dart
index f7afcc0..cba9e1b 100644
--- a/packages/webview_flutter/lib/src/webview_android.dart
+++ b/packages/webview_flutter/lib/src/webview_android.dart
@@ -20,11 +20,11 @@
 class AndroidWebView implements WebViewPlatform {
   @override
   Widget build({
-    BuildContext context,
-    CreationParams creationParams,
-    @required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
-    WebViewPlatformCreatedCallback onWebViewPlatformCreated,
-    Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
+    required BuildContext context,
+    required CreationParams creationParams,
+    required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
+    WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
+    Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers,
   }) {
     assert(webViewPlatformCallbacksHandler != null);
     return GestureDetector(
diff --git a/packages/webview_flutter/lib/src/webview_cupertino.dart b/packages/webview_flutter/lib/src/webview_cupertino.dart
index 0e84908..e681655 100644
--- a/packages/webview_flutter/lib/src/webview_cupertino.dart
+++ b/packages/webview_flutter/lib/src/webview_cupertino.dart
@@ -20,11 +20,11 @@
 class CupertinoWebView implements WebViewPlatform {
   @override
   Widget build({
-    BuildContext context,
-    CreationParams creationParams,
-    @required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
-    WebViewPlatformCreatedCallback onWebViewPlatformCreated,
-    Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
+    required BuildContext context,
+    required CreationParams creationParams,
+    required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
+    WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
+    Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers,
   }) {
     return UiKitView(
       viewType: 'plugins.flutter.io/webview',
diff --git a/packages/webview_flutter/lib/src/webview_method_channel.dart b/packages/webview_flutter/lib/src/webview_method_channel.dart
index 348b225..1c666d7 100644
--- a/packages/webview_flutter/lib/src/webview_method_channel.dart
+++ b/packages/webview_flutter/lib/src/webview_method_channel.dart
@@ -25,31 +25,31 @@
   static const MethodChannel _cookieManagerChannel =
       MethodChannel('plugins.flutter.io/cookie_manager');
 
-  Future<bool> _onMethodCall(MethodCall call) async {
+  Future<bool?> _onMethodCall(MethodCall call) async {
     switch (call.method) {
       case 'javascriptChannelMessage':
-        final String channel = call.arguments['channel'];
-        final String message = call.arguments['message'];
+        final String channel = call.arguments['channel']!;
+        final String message = call.arguments['message']!;
         _platformCallbacksHandler.onJavaScriptChannelMessage(channel, message);
         return true;
       case 'navigationRequest':
         return await _platformCallbacksHandler.onNavigationRequest(
-          url: call.arguments['url'],
-          isForMainFrame: call.arguments['isForMainFrame'],
+          url: call.arguments['url']!,
+          isForMainFrame: call.arguments['isForMainFrame']!,
         );
       case 'onPageFinished':
-        _platformCallbacksHandler.onPageFinished(call.arguments['url']);
+        _platformCallbacksHandler.onPageFinished(call.arguments['url']!);
         return null;
       case 'onPageStarted':
-        _platformCallbacksHandler.onPageStarted(call.arguments['url']);
+        _platformCallbacksHandler.onPageStarted(call.arguments['url']!);
         return null;
       case 'onWebResourceError':
         _platformCallbacksHandler.onWebResourceError(
           WebResourceError(
-            errorCode: call.arguments['errorCode'],
-            description: call.arguments['description'],
+            errorCode: call.arguments['errorCode']!,
+            description: call.arguments['description']!,
+            failingUrl: call.arguments['failingUrl']!,
             domain: call.arguments['domain'],
-            failingUrl: call.arguments['failingUrl'],
             errorType: call.arguments['errorType'] == null
                 ? null
                 : WebResourceErrorType.values.firstWhere(
@@ -71,7 +71,7 @@
   @override
   Future<void> loadUrl(
     String url,
-    Map<String, String> headers,
+    Map<String, String>? headers,
   ) async {
     assert(url != null);
     return _channel.invokeMethod<void>('loadUrl', <String, dynamic>{
@@ -81,13 +81,15 @@
   }
 
   @override
-  Future<String> currentUrl() => _channel.invokeMethod<String>('currentUrl');
+  Future<String?> currentUrl() => _channel.invokeMethod<String>('currentUrl');
 
   @override
-  Future<bool> canGoBack() => _channel.invokeMethod<bool>("canGoBack");
+  Future<bool> canGoBack() =>
+      _channel.invokeMethod<bool>("canGoBack").then((result) => result!);
 
   @override
-  Future<bool> canGoForward() => _channel.invokeMethod<bool>("canGoForward");
+  Future<bool> canGoForward() =>
+      _channel.invokeMethod<bool>("canGoForward").then((result) => result!);
 
   @override
   Future<void> goBack() => _channel.invokeMethod<void>("goBack");
@@ -102,18 +104,18 @@
   Future<void> clearCache() => _channel.invokeMethod<void>("clearCache");
 
   @override
-  Future<void> updateSettings(WebSettings settings) {
+  Future<void> updateSettings(WebSettings settings) async {
     final Map<String, dynamic> updatesMap = _webSettingsToMap(settings);
-    if (updatesMap.isEmpty) {
-      return null;
+    if (updatesMap.isNotEmpty) {
+      await _channel.invokeMethod<void>('updateSettings', updatesMap);
     }
-    return _channel.invokeMethod<void>('updateSettings', updatesMap);
   }
 
   @override
   Future<String> evaluateJavascript(String javascriptString) {
-    return _channel.invokeMethod<String>(
-        'evaluateJavascript', javascriptString);
+    return _channel
+        .invokeMethod<String>('evaluateJavascript', javascriptString)
+        .then((result) => result!);
   }
 
   @override
@@ -129,7 +131,7 @@
   }
 
   @override
-  Future<String> getTitle() => _channel.invokeMethod<String>("getTitle");
+  Future<String?> getTitle() => _channel.invokeMethod<String>("getTitle");
 
   @override
   Future<void> scrollTo(int x, int y) {
@@ -148,19 +150,21 @@
   }
 
   @override
-  Future<int> getScrollX() => _channel.invokeMethod<int>("getScrollX");
+  Future<int> getScrollX() =>
+      _channel.invokeMethod<int>("getScrollX").then((result) => result!);
 
   @override
-  Future<int> getScrollY() => _channel.invokeMethod<int>("getScrollY");
+  Future<int> getScrollY() =>
+      _channel.invokeMethod<int>("getScrollY").then((result) => result!);
 
   /// Method channel implementation for [WebViewPlatform.clearCookies].
   static Future<bool> clearCookies() {
     return _cookieManagerChannel
         .invokeMethod<bool>('clearCookies')
-        .then<bool>((dynamic result) => result);
+        .then<bool>((dynamic result) => result!);
   }
 
-  static Map<String, dynamic> _webSettingsToMap(WebSettings settings) {
+  static Map<String, dynamic> _webSettingsToMap(WebSettings? settings) {
     final Map<String, dynamic> map = <String, dynamic>{};
     void _addIfNonNull(String key, dynamic value) {
       if (value == null) {
@@ -176,7 +180,7 @@
       map[key] = setting.value;
     }
 
-    _addIfNonNull('jsMode', settings.javascriptMode?.index);
+    _addIfNonNull('jsMode', settings!.javascriptMode?.index);
     _addIfNonNull('hasNavigationDelegate', settings.hasNavigationDelegate);
     _addIfNonNull('debuggingEnabled', settings.debuggingEnabled);
     _addIfNonNull(
diff --git a/packages/webview_flutter/lib/webview_flutter.dart b/packages/webview_flutter/lib/webview_flutter.dart
index 2fdf639..4327c78 100644
--- a/packages/webview_flutter/lib/webview_flutter.dart
+++ b/packages/webview_flutter/lib/webview_flutter.dart
@@ -44,7 +44,7 @@
 
 /// Information about a navigation action that is about to be executed.
 class NavigationRequest {
-  NavigationRequest._({this.url, this.isForMainFrame});
+  NavigationRequest._({required this.url, required this.isForMainFrame});
 
   /// The URL that will be loaded if the navigation is executed.
   final String url;
@@ -79,11 +79,11 @@
 class SurfaceAndroidWebView extends AndroidWebView {
   @override
   Widget build({
-    BuildContext context,
-    CreationParams creationParams,
-    WebViewPlatformCreatedCallback onWebViewPlatformCreated,
-    Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
-    @required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
+    required BuildContext context,
+    required CreationParams creationParams,
+    WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
+    Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers,
+    required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
   }) {
     assert(webViewPlatformCallbacksHandler != null);
     return PlatformViewLink(
@@ -93,7 +93,7 @@
         PlatformViewController controller,
       ) {
         return AndroidViewSurface(
-          controller: controller,
+          controller: controller as AndroidViewController,
           gestureRecognizers: gestureRecognizers ??
               const <Factory<OneSequenceGestureRecognizer>>{},
           hitTestBehavior: PlatformViewHitTestBehavior.opaque,
@@ -172,9 +172,9 @@
   ///
   /// The parameters `name` and `onMessageReceived` must not be null.
   JavascriptChannel({
-    @required this.name,
-    @required this.onMessageReceived,
-  })  : assert(name != null),
+    required this.name,
+    required this.onMessageReceived,
+  })   : assert(name != null),
         assert(onMessageReceived != null),
         assert(_validChannelNames.hasMatch(name));
 
@@ -208,7 +208,7 @@
   ///
   /// The `javascriptMode` and `autoMediaPlaybackPolicy` parameters must not be null.
   const WebView({
-    Key key,
+    Key? key,
     this.onWebViewCreated,
     this.initialUrl,
     this.javascriptMode = JavascriptMode.disabled,
@@ -227,7 +227,7 @@
         assert(initialMediaPlaybackPolicy != null),
         super(key: key);
 
-  static WebViewPlatform _platform;
+  static WebViewPlatform? _platform;
 
   /// Sets a custom [WebViewPlatform].
   ///
@@ -236,7 +236,7 @@
   /// Setting `platform` doesn't affect [WebView]s that were already created.
   ///
   /// The default value is [AndroidWebView] on Android and [CupertinoWebView] on iOS.
-  static set platform(WebViewPlatform platform) {
+  static set platform(WebViewPlatform? platform) {
     _platform = platform;
   }
 
@@ -257,11 +257,11 @@
               "Trying to use the default webview implementation for $defaultTargetPlatform but there isn't a default one");
       }
     }
-    return _platform;
+    return _platform!;
   }
 
   /// If not null invoked once the web view is created.
-  final WebViewCreatedCallback onWebViewCreated;
+  final WebViewCreatedCallback? onWebViewCreated;
 
   /// Which gestures should be consumed by the web view.
   ///
@@ -272,10 +272,10 @@
   ///
   /// When this set is empty or null, the web view will only handle pointer events for gestures that
   /// were not claimed by any other gesture recognizer.
-  final Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers;
+  final Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers;
 
   /// The initial URL to load.
-  final String initialUrl;
+  final String? initialUrl;
 
   /// Whether Javascript execution is enabled.
   final JavascriptMode javascriptMode;
@@ -307,7 +307,7 @@
   /// channels in the list.
   ///
   /// A null value is equivalent to an empty set.
-  final Set<JavascriptChannel> javascriptChannels;
+  final Set<JavascriptChannel>? javascriptChannels;
 
   /// A delegate function that decides how to handle navigation actions.
   ///
@@ -331,10 +331,10 @@
   ///     * When a navigationDelegate is set pages with frames are not properly handled by the
   ///       webview, and frames will be opened in the main frame.
   ///     * When a navigationDelegate is set HTTP requests do not include the HTTP referer header.
-  final NavigationDelegate navigationDelegate;
+  final NavigationDelegate? navigationDelegate;
 
   /// Invoked when a page starts loading.
-  final PageStartedCallback onPageStarted;
+  final PageStartedCallback? onPageStarted;
 
   /// Invoked when a page has finished loading.
   ///
@@ -346,13 +346,13 @@
   /// When invoked on iOS or Android, any Javascript code that is embedded
   /// directly in the HTML has been loaded and code injected with
   /// [WebViewController.evaluateJavascript] can assume this.
-  final PageFinishedCallback onPageFinished;
+  final PageFinishedCallback? onPageFinished;
 
   /// Invoked when a web resource has failed to load.
   ///
   /// This can be called for any resource (iframe, image, etc.), not just for
   /// the main page.
-  final WebResourceErrorCallback onWebResourceError;
+  final WebResourceErrorCallback? onWebResourceError;
 
   /// Controls whether WebView debugging is enabled.
   ///
@@ -386,7 +386,7 @@
   /// user agent.
   ///
   /// By default `userAgent` is null.
-  final String userAgent;
+  final String? userAgent;
 
   /// Which restrictions apply on automatic media playback.
   ///
@@ -404,7 +404,7 @@
   final Completer<WebViewController> _controller =
       Completer<WebViewController>();
 
-  _PlatformCallbacksHandler _platformCallbacksHandler;
+  late _PlatformCallbacksHandler _platformCallbacksHandler;
 
   @override
   Widget build(BuildContext context) {
@@ -434,22 +434,22 @@
     });
   }
 
-  void _onWebViewPlatformCreated(WebViewPlatformController webViewPlatform) {
-    final WebViewController controller =
-        WebViewController._(widget, webViewPlatform, _platformCallbacksHandler);
+  void _onWebViewPlatformCreated(WebViewPlatformController? webViewPlatform) {
+    final WebViewController controller = WebViewController._(
+        widget, webViewPlatform!, _platformCallbacksHandler);
     _controller.complete(controller);
     if (widget.onWebViewCreated != null) {
-      widget.onWebViewCreated(controller);
+      widget.onWebViewCreated!(controller);
     }
   }
 
   void _assertJavascriptChannelNamesAreUnique() {
     if (widget.javascriptChannels == null ||
-        widget.javascriptChannels.isEmpty) {
+        widget.javascriptChannels!.isEmpty) {
       return;
     }
     assert(_extractChannelNames(widget.javascriptChannels).length ==
-        widget.javascriptChannels.length);
+        widget.javascriptChannels!.length);
   }
 }
 
@@ -469,7 +469,7 @@
     hasNavigationDelegate: widget.navigationDelegate != null,
     debuggingEnabled: widget.debuggingEnabled,
     gestureNavigationEnabled: widget.gestureNavigationEnabled,
-    userAgent: WebSetting<String>.of(widget.userAgent),
+    userAgent: WebSetting<String?>.of(widget.userAgent),
   );
 }
 
@@ -479,16 +479,16 @@
   assert(currentValue.javascriptMode != null);
   assert(currentValue.hasNavigationDelegate != null);
   assert(currentValue.debuggingEnabled != null);
-  assert(currentValue.userAgent.isPresent);
+  assert(currentValue.userAgent != null);
   assert(newValue.javascriptMode != null);
   assert(newValue.hasNavigationDelegate != null);
   assert(newValue.debuggingEnabled != null);
-  assert(newValue.userAgent.isPresent);
+  assert(newValue.userAgent != null);
 
-  JavascriptMode javascriptMode;
-  bool hasNavigationDelegate;
-  bool debuggingEnabled;
-  WebSetting<String> userAgent = WebSetting<String>.absent();
+  JavascriptMode? javascriptMode;
+  bool? hasNavigationDelegate;
+  bool? debuggingEnabled;
+  WebSetting<String?> userAgent = WebSetting.absent();
   if (currentValue.javascriptMode != newValue.javascriptMode) {
     javascriptMode = newValue.javascriptMode;
   }
@@ -510,7 +510,7 @@
   );
 }
 
-Set<String> _extractChannelNames(Set<JavascriptChannel> channels) {
+Set<String> _extractChannelNames(Set<JavascriptChannel>? channels) {
   final Set<String> channelNames = channels == null
       ? <String>{}
       : channels.map((JavascriptChannel channel) => channel.name).toSet();
@@ -530,15 +530,18 @@
 
   @override
   void onJavaScriptChannelMessage(String channel, String message) {
-    _javascriptChannels[channel].onMessageReceived(JavascriptMessage(message));
+    _javascriptChannels[channel]!.onMessageReceived(JavascriptMessage(message));
   }
 
   @override
-  FutureOr<bool> onNavigationRequest({String url, bool isForMainFrame}) async {
+  FutureOr<bool> onNavigationRequest({
+    required String url,
+    required bool isForMainFrame,
+  }) async {
     final NavigationRequest request =
         NavigationRequest._(url: url, isForMainFrame: isForMainFrame);
     final bool allowNavigation = _widget.navigationDelegate == null ||
-        await _widget.navigationDelegate(request) ==
+        await _widget.navigationDelegate!(request) ==
             NavigationDecision.navigate;
     return allowNavigation;
   }
@@ -546,25 +549,25 @@
   @override
   void onPageStarted(String url) {
     if (_widget.onPageStarted != null) {
-      _widget.onPageStarted(url);
+      _widget.onPageStarted!(url);
     }
   }
 
   @override
   void onPageFinished(String url) {
     if (_widget.onPageFinished != null) {
-      _widget.onPageFinished(url);
+      _widget.onPageFinished!(url);
     }
   }
 
   @override
   void onWebResourceError(WebResourceError error) {
     if (_widget.onWebResourceError != null) {
-      _widget.onWebResourceError(error);
+      _widget.onWebResourceError!(error);
     }
   }
 
-  void _updateJavascriptChannelsFromSet(Set<JavascriptChannel> channels) {
+  void _updateJavascriptChannelsFromSet(Set<JavascriptChannel>? channels) {
     _javascriptChannels.clear();
     if (channels == null) {
       return;
@@ -592,7 +595,7 @@
 
   final _PlatformCallbacksHandler _platformCallbacksHandler;
 
-  WebSettings _settings;
+  late WebSettings _settings;
 
   WebView _widget;
 
@@ -606,7 +609,7 @@
   /// Throws an ArgumentError if `url` is not a valid URL string.
   Future<void> loadUrl(
     String url, {
-    Map<String, String> headers,
+    Map<String, String>? headers,
   }) async {
     assert(url != null);
     _validateUrlString(url);
@@ -620,7 +623,7 @@
   /// 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() {
+  Future<String?> currentUrl() {
     return _webViewPlatformController.currentUrl();
   }
 
@@ -688,7 +691,7 @@
   }
 
   Future<void> _updateJavascriptChannels(
-      Set<JavascriptChannel> newChannels) async {
+      Set<JavascriptChannel>? newChannels) async {
     final Set<String> currentChannels =
         _platformCallbacksHandler._javascriptChannels.keys.toSet();
     final Set<String> newChannelNames = _extractChannelNames(newChannels);
@@ -727,10 +730,6 @@
       return Future<String>.error(FlutterError(
           'JavaScript mode must be enabled/unrestricted when calling evaluateJavascript.'));
     }
-    if (javascriptString == null) {
-      return Future<String>.error(
-          ArgumentError('The argument javascriptString must not be null.'));
-    }
     // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter.
     // https://github.com/flutter/flutter/issues/26431
     // ignore: strong_mode_implicit_dynamic_method
@@ -738,7 +737,7 @@
   }
 
   /// Returns the title of the currently loaded page.
-  Future<String> getTitle() {
+  Future<String?> getTitle() {
     return _webViewPlatformController.getTitle();
   }
 
@@ -780,7 +779,7 @@
 
   CookieManager._();
 
-  static CookieManager _instance;
+  static CookieManager? _instance;
 
   /// Clears all cookies for all [WebView] instances.
   ///
diff --git a/packages/webview_flutter/pubspec.yaml b/packages/webview_flutter/pubspec.yaml
index de99c4b..de62a50 100644
--- a/packages/webview_flutter/pubspec.yaml
+++ b/packages/webview_flutter/pubspec.yaml
@@ -1,10 +1,10 @@
 name: webview_flutter
 description: A Flutter plugin that provides a WebView widget on Android and iOS.
-version: 1.0.8
+version: 2.0.0-nullsafety
 homepage: https://github.com/flutter/plugins/tree/master/packages/webview_flutter
 
 environment:
-  sdk: ">=2.7.0 <3.0.0"
+  sdk: ">=2.12.0-0 <3.0.0"
   flutter: ">=1.22.0"
 
 dependencies:
@@ -16,7 +16,7 @@
     sdk: flutter
   flutter_driver:
     sdk: flutter
-  pedantic: ^1.8.0
+  pedantic: ^1.10.0-nullsafety.1
 
 flutter:
   plugin:
diff --git a/packages/webview_flutter/test/webview_flutter_test.dart b/packages/webview_flutter/test/webview_flutter_test.dart
index c7cf46a..662a2f7 100644
--- a/packages/webview_flutter/test/webview_flutter_test.dart
+++ b/packages/webview_flutter/test/webview_flutter_test.dart
@@ -40,7 +40,7 @@
   });
 
   testWidgets('Initial url', (WidgetTester tester) async {
-    WebViewController controller;
+    late WebViewController controller;
     await tester.pumpWidget(
       WebView(
         initialUrl: 'https://youtube.com',
@@ -60,7 +60,7 @@
     ));
 
     final FakePlatformWebView platformWebView =
-        fakePlatformViewsController.lastCreatedView;
+        fakePlatformViewsController.lastCreatedView!;
 
     expect(platformWebView.javascriptMode, JavascriptMode.unrestricted);
 
@@ -72,7 +72,7 @@
   });
 
   testWidgets('Load url', (WidgetTester tester) async {
-    WebViewController controller;
+    WebViewController? controller;
     await tester.pumpWidget(
       WebView(
         onWebViewCreated: (WebViewController webViewController) {
@@ -83,13 +83,13 @@
 
     expect(controller, isNotNull);
 
-    await controller.loadUrl('https://flutter.io');
+    await controller!.loadUrl('https://flutter.io');
 
-    expect(await controller.currentUrl(), 'https://flutter.io');
+    expect(await controller!.currentUrl(), 'https://flutter.io');
   });
 
   testWidgets('Invalid urls', (WidgetTester tester) async {
-    WebViewController controller;
+    WebViewController? controller;
     await tester.pumpWidget(
       WebView(
         onWebViewCreated: (WebViewController webViewController) {
@@ -100,19 +100,18 @@
 
     expect(controller, isNotNull);
 
-    expect(() => controller.loadUrl(null), throwsA(anything));
-    expect(await controller.currentUrl(), isNull);
+    expect(await controller!.currentUrl(), isNull);
 
-    expect(() => controller.loadUrl(''), throwsA(anything));
-    expect(await controller.currentUrl(), isNull);
+    expect(() => controller!.loadUrl(''), throwsA(anything));
+    expect(await controller!.currentUrl(), isNull);
 
     // Missing schema.
-    expect(() => controller.loadUrl('flutter.io'), throwsA(anything));
-    expect(await controller.currentUrl(), isNull);
+    expect(() => controller!.loadUrl('flutter.io'), throwsA(anything));
+    expect(await controller!.currentUrl(), isNull);
   });
 
   testWidgets('Headers in loadUrl', (WidgetTester tester) async {
-    WebViewController controller;
+    WebViewController? controller;
     await tester.pumpWidget(
       WebView(
         onWebViewCreated: (WebViewController webViewController) {
@@ -126,13 +125,13 @@
     final Map<String, String> headers = <String, String>{
       'CACHE-CONTROL': 'ABC'
     };
-    await controller.loadUrl('https://flutter.io', headers: headers);
-    expect(await controller.currentUrl(), equals('https://flutter.io'));
+    await controller!.loadUrl('https://flutter.io', headers: headers);
+    expect(await controller!.currentUrl(), equals('https://flutter.io'));
   });
 
   testWidgets("Can't go back before loading a page",
       (WidgetTester tester) async {
-    WebViewController controller;
+    WebViewController? controller;
     await tester.pumpWidget(
       WebView(
         onWebViewCreated: (WebViewController webViewController) {
@@ -143,13 +142,13 @@
 
     expect(controller, isNotNull);
 
-    final bool canGoBackNoPageLoaded = await controller.canGoBack();
+    final bool canGoBackNoPageLoaded = await controller!.canGoBack();
 
     expect(canGoBackNoPageLoaded, false);
   });
 
   testWidgets("Clear Cache", (WidgetTester tester) async {
-    WebViewController controller;
+    WebViewController? controller;
     await tester.pumpWidget(
       WebView(
         onWebViewCreated: (WebViewController webViewController) {
@@ -159,15 +158,15 @@
     );
 
     expect(controller, isNotNull);
-    expect(fakePlatformViewsController.lastCreatedView.hasCache, true);
+    expect(fakePlatformViewsController.lastCreatedView!.hasCache, true);
 
-    await controller.clearCache();
+    await controller!.clearCache();
 
-    expect(fakePlatformViewsController.lastCreatedView.hasCache, false);
+    expect(fakePlatformViewsController.lastCreatedView!.hasCache, false);
   });
 
   testWidgets("Can't go back with no history", (WidgetTester tester) async {
-    WebViewController controller;
+    WebViewController? controller;
     await tester.pumpWidget(
       WebView(
         initialUrl: 'https://flutter.io',
@@ -178,13 +177,13 @@
     );
 
     expect(controller, isNotNull);
-    final bool canGoBackFirstPageLoaded = await controller.canGoBack();
+    final bool canGoBackFirstPageLoaded = await controller!.canGoBack();
 
     expect(canGoBackFirstPageLoaded, false);
   });
 
   testWidgets('Can go back', (WidgetTester tester) async {
-    WebViewController controller;
+    WebViewController? controller;
     await tester.pumpWidget(
       WebView(
         initialUrl: 'https://flutter.io',
@@ -196,15 +195,15 @@
 
     expect(controller, isNotNull);
 
-    await controller.loadUrl('https://www.google.com');
-    final bool canGoBackSecondPageLoaded = await controller.canGoBack();
+    await controller!.loadUrl('https://www.google.com');
+    final bool canGoBackSecondPageLoaded = await controller!.canGoBack();
 
     expect(canGoBackSecondPageLoaded, true);
   });
 
   testWidgets("Can't go forward before loading a page",
       (WidgetTester tester) async {
-    WebViewController controller;
+    WebViewController? controller;
     await tester.pumpWidget(
       WebView(
         onWebViewCreated: (WebViewController webViewController) {
@@ -215,13 +214,13 @@
 
     expect(controller, isNotNull);
 
-    final bool canGoForwardNoPageLoaded = await controller.canGoForward();
+    final bool canGoForwardNoPageLoaded = await controller!.canGoForward();
 
     expect(canGoForwardNoPageLoaded, false);
   });
 
   testWidgets("Can't go forward with no history", (WidgetTester tester) async {
-    WebViewController controller;
+    WebViewController? controller;
     await tester.pumpWidget(
       WebView(
         initialUrl: 'https://flutter.io',
@@ -232,13 +231,13 @@
     );
 
     expect(controller, isNotNull);
-    final bool canGoForwardFirstPageLoaded = await controller.canGoForward();
+    final bool canGoForwardFirstPageLoaded = await controller!.canGoForward();
 
     expect(canGoForwardFirstPageLoaded, false);
   });
 
   testWidgets('Can go forward', (WidgetTester tester) async {
-    WebViewController controller;
+    WebViewController? controller;
     await tester.pumpWidget(
       WebView(
         initialUrl: 'https://flutter.io',
@@ -250,15 +249,15 @@
 
     expect(controller, isNotNull);
 
-    await controller.loadUrl('https://youtube.com');
-    await controller.goBack();
-    final bool canGoForwardFirstPageBacked = await controller.canGoForward();
+    await controller!.loadUrl('https://youtube.com');
+    await controller!.goBack();
+    final bool canGoForwardFirstPageBacked = await controller!.canGoForward();
 
     expect(canGoForwardFirstPageBacked, true);
   });
 
   testWidgets('Go back', (WidgetTester tester) async {
-    WebViewController controller;
+    WebViewController? controller;
     await tester.pumpWidget(
       WebView(
         initialUrl: 'https://youtube.com',
@@ -270,19 +269,19 @@
 
     expect(controller, isNotNull);
 
-    expect(await controller.currentUrl(), 'https://youtube.com');
+    expect(await controller!.currentUrl(), 'https://youtube.com');
 
-    await controller.loadUrl('https://flutter.io');
+    await controller!.loadUrl('https://flutter.io');
 
-    expect(await controller.currentUrl(), 'https://flutter.io');
+    expect(await controller!.currentUrl(), 'https://flutter.io');
 
-    await controller.goBack();
+    await controller!.goBack();
 
-    expect(await controller.currentUrl(), 'https://youtube.com');
+    expect(await controller!.currentUrl(), 'https://youtube.com');
   });
 
   testWidgets('Go forward', (WidgetTester tester) async {
-    WebViewController controller;
+    WebViewController? controller;
     await tester.pumpWidget(
       WebView(
         initialUrl: 'https://youtube.com',
@@ -294,23 +293,23 @@
 
     expect(controller, isNotNull);
 
-    expect(await controller.currentUrl(), 'https://youtube.com');
+    expect(await controller!.currentUrl(), 'https://youtube.com');
 
-    await controller.loadUrl('https://flutter.io');
+    await controller!.loadUrl('https://flutter.io');
 
-    expect(await controller.currentUrl(), 'https://flutter.io');
+    expect(await controller!.currentUrl(), 'https://flutter.io');
 
-    await controller.goBack();
+    await controller!.goBack();
 
-    expect(await controller.currentUrl(), 'https://youtube.com');
+    expect(await controller!.currentUrl(), 'https://youtube.com');
 
-    await controller.goForward();
+    await controller!.goForward();
 
-    expect(await controller.currentUrl(), 'https://flutter.io');
+    expect(await controller!.currentUrl(), 'https://flutter.io');
   });
 
   testWidgets('Current URL', (WidgetTester tester) async {
-    WebViewController controller;
+    WebViewController? controller;
     await tester.pumpWidget(
       WebView(
         onWebViewCreated: (WebViewController webViewController) {
@@ -322,20 +321,20 @@
     expect(controller, isNotNull);
 
     // Test a WebView without an explicitly set first URL.
-    expect(await controller.currentUrl(), isNull);
+    expect(await controller!.currentUrl(), isNull);
 
-    await controller.loadUrl('https://youtube.com');
-    expect(await controller.currentUrl(), 'https://youtube.com');
+    await controller!.loadUrl('https://youtube.com');
+    expect(await controller!.currentUrl(), 'https://youtube.com');
 
-    await controller.loadUrl('https://flutter.io');
-    expect(await controller.currentUrl(), 'https://flutter.io');
+    await controller!.loadUrl('https://flutter.io');
+    expect(await controller!.currentUrl(), 'https://flutter.io');
 
-    await controller.goBack();
-    expect(await controller.currentUrl(), 'https://youtube.com');
+    await controller!.goBack();
+    expect(await controller!.currentUrl(), 'https://youtube.com');
   });
 
   testWidgets('Reload url', (WidgetTester tester) async {
-    WebViewController controller;
+    late WebViewController controller;
     await tester.pumpWidget(
       WebView(
         initialUrl: 'https://flutter.io',
@@ -346,7 +345,7 @@
     );
 
     final FakePlatformWebView platformWebView =
-        fakePlatformViewsController.lastCreatedView;
+        fakePlatformViewsController.lastCreatedView!;
 
     expect(platformWebView.currentUrl, 'https://flutter.io');
     expect(platformWebView.amountOfReloadsOnCurrentUrl, 0);
@@ -362,7 +361,7 @@
   });
 
   testWidgets('evaluate Javascript', (WidgetTester tester) async {
-    WebViewController controller;
+    late WebViewController controller;
     await tester.pumpWidget(
       WebView(
         initialUrl: 'https://flutter.io',
@@ -375,15 +374,11 @@
     expect(
         await controller.evaluateJavascript("fake js string"), "fake js string",
         reason: 'should get the argument');
-    expect(
-      () => controller.evaluateJavascript(null),
-      throwsA(anything),
-    );
   });
 
   testWidgets('evaluate Javascript with JavascriptMode disabled',
       (WidgetTester tester) async {
-    WebViewController controller;
+    late WebViewController controller;
     await tester.pumpWidget(
       WebView(
         initialUrl: 'https://flutter.io',
@@ -397,10 +392,6 @@
       () => controller.evaluateJavascript('fake js string'),
       throwsA(anything),
     );
-    expect(
-      () => controller.evaluateJavascript(null),
-      throwsA(anything),
-    );
   });
 
   testWidgets('Cookies can be cleared once', (WidgetTester tester) async {
@@ -444,7 +435,7 @@
     );
 
     final FakePlatformWebView platformWebView =
-        fakePlatformViewsController.lastCreatedView;
+        fakePlatformViewsController.lastCreatedView!;
 
     expect(platformWebView.javascriptChannelNames,
         unorderedEquals(<String>['Tts', 'Alarm']));
@@ -517,7 +508,7 @@
     );
 
     final FakePlatformWebView platformWebView =
-        fakePlatformViewsController.lastCreatedView;
+        fakePlatformViewsController.lastCreatedView!;
 
     expect(platformWebView.javascriptChannelNames,
         unorderedEquals(<String>['Tts', 'Alarm2', 'Alarm3']));
@@ -560,7 +551,7 @@
     );
 
     final FakePlatformWebView platformWebView =
-        fakePlatformViewsController.lastCreatedView;
+        fakePlatformViewsController.lastCreatedView!;
 
     expect(platformWebView.javascriptChannelNames,
         unorderedEquals(<String>['Tts']));
@@ -590,7 +581,7 @@
     );
 
     final FakePlatformWebView platformWebView =
-        fakePlatformViewsController.lastCreatedView;
+        fakePlatformViewsController.lastCreatedView!;
 
     expect(ttsMessagesReceived, isEmpty);
     expect(alarmMessagesReceived, isEmpty);
@@ -603,7 +594,7 @@
 
   group('$PageStartedCallback', () {
     testWidgets('onPageStarted is not null', (WidgetTester tester) async {
-      String returnedUrl;
+      String? returnedUrl;
 
       await tester.pumpWidget(WebView(
         initialUrl: 'https://youtube.com',
@@ -613,7 +604,7 @@
       ));
 
       final FakePlatformWebView platformWebView =
-          fakePlatformViewsController.lastCreatedView;
+          fakePlatformViewsController.lastCreatedView!;
 
       platformWebView.fakeOnPageStartedCallback();
 
@@ -627,7 +618,7 @@
       ));
 
       final FakePlatformWebView platformWebView =
-          fakePlatformViewsController.lastCreatedView;
+          fakePlatformViewsController.lastCreatedView!;
 
       // The platform side will always invoke a call for onPageStarted. This is
       // to test that it does not crash on a null callback.
@@ -635,7 +626,7 @@
     });
 
     testWidgets('onPageStarted changed', (WidgetTester tester) async {
-      String returnedUrl;
+      String? returnedUrl;
 
       await tester.pumpWidget(WebView(
         initialUrl: 'https://youtube.com',
@@ -650,7 +641,7 @@
       ));
 
       final FakePlatformWebView platformWebView =
-          fakePlatformViewsController.lastCreatedView;
+          fakePlatformViewsController.lastCreatedView!;
 
       platformWebView.fakeOnPageStartedCallback();
 
@@ -660,7 +651,7 @@
 
   group('$PageFinishedCallback', () {
     testWidgets('onPageFinished is not null', (WidgetTester tester) async {
-      String returnedUrl;
+      String? returnedUrl;
 
       await tester.pumpWidget(WebView(
         initialUrl: 'https://youtube.com',
@@ -670,7 +661,7 @@
       ));
 
       final FakePlatformWebView platformWebView =
-          fakePlatformViewsController.lastCreatedView;
+          fakePlatformViewsController.lastCreatedView!;
 
       platformWebView.fakeOnPageFinishedCallback();
 
@@ -684,7 +675,7 @@
       ));
 
       final FakePlatformWebView platformWebView =
-          fakePlatformViewsController.lastCreatedView;
+          fakePlatformViewsController.lastCreatedView!;
 
       // The platform side will always invoke a call for onPageFinished. This is
       // to test that it does not crash on a null callback.
@@ -692,7 +683,7 @@
     });
 
     testWidgets('onPageFinished changed', (WidgetTester tester) async {
-      String returnedUrl;
+      String? returnedUrl;
 
       await tester.pumpWidget(WebView(
         initialUrl: 'https://youtube.com',
@@ -707,7 +698,7 @@
       ));
 
       final FakePlatformWebView platformWebView =
-          fakePlatformViewsController.lastCreatedView;
+          fakePlatformViewsController.lastCreatedView!;
 
       platformWebView.fakeOnPageFinishedCallback();
 
@@ -722,13 +713,14 @@
       ));
 
       final FakePlatformWebView platformWebView =
-          fakePlatformViewsController.lastCreatedView;
+          fakePlatformViewsController.lastCreatedView!;
 
       expect(platformWebView.hasNavigationDelegate, false);
 
       await tester.pumpWidget(WebView(
         initialUrl: 'https://youtube.com',
-        navigationDelegate: (NavigationRequest r) => null,
+        navigationDelegate: (NavigationRequest r) =>
+            NavigationDecision.navigate,
       ));
 
       expect(platformWebView.hasNavigationDelegate, true);
@@ -748,7 +740,7 @@
           }));
 
       final FakePlatformWebView platformWebView =
-          fakePlatformViewsController.lastCreatedView;
+          fakePlatformViewsController.lastCreatedView!;
 
       expect(platformWebView.hasNavigationDelegate, true);
 
@@ -773,7 +765,7 @@
       ));
 
       final FakePlatformWebView platformWebView =
-          fakePlatformViewsController.lastCreatedView;
+          fakePlatformViewsController.lastCreatedView!;
 
       expect(platformWebView.debuggingEnabled, true);
     });
@@ -782,7 +774,7 @@
       await tester.pumpWidget(const WebView());
 
       final FakePlatformWebView platformWebView =
-          fakePlatformViewsController.lastCreatedView;
+          fakePlatformViewsController.lastCreatedView!;
 
       expect(platformWebView.debuggingEnabled, false);
     });
@@ -792,7 +784,7 @@
       await tester.pumpWidget(WebView(key: key));
 
       final FakePlatformWebView platformWebView =
-          fakePlatformViewsController.lastCreatedView;
+          fakePlatformViewsController.lastCreatedView!;
 
       await tester.pumpWidget(WebView(
         key: key,
@@ -826,8 +818,8 @@
         ),
       );
 
-      final MyWebViewPlatform builder = WebView.platform;
-      final MyWebViewPlatformController platform = builder.lastPlatformBuilt;
+      final MyWebViewPlatform builder = WebView.platform as MyWebViewPlatform;
+      final MyWebViewPlatformController platform = builder.lastPlatformBuilt!;
 
       expect(
           platform.creationParams,
@@ -837,17 +829,14 @@
               javascriptMode: JavascriptMode.disabled,
               hasNavigationDelegate: false,
               debuggingEnabled: false,
-              userAgent: WebSetting<String>.of(null),
+              userAgent: WebSetting<String?>.of(null),
               gestureNavigationEnabled: true,
             ),
-            // TODO(iskakaushik): Remove this when collection literals makes it to stable.
-            // ignore: prefer_collection_literals
-            javascriptChannelNames: Set<String>(),
           )));
     });
 
     testWidgets('loadUrl', (WidgetTester tester) async {
-      WebViewController controller;
+      late WebViewController controller;
       await tester.pumpWidget(
         WebView(
           initialUrl: 'https://youtube.com',
@@ -857,8 +846,8 @@
         ),
       );
 
-      final MyWebViewPlatform builder = WebView.platform;
-      final MyWebViewPlatformController platform = builder.lastPlatformBuilt;
+      final MyWebViewPlatform builder = WebView.platform as MyWebViewPlatform;
+      final MyWebViewPlatformController platform = builder.lastPlatformBuilt!;
 
       final Map<String, String> headers = <String, String>{
         'header': 'value',
@@ -877,7 +866,7 @@
     ));
 
     final FakePlatformWebView platformWebView =
-        fakePlatformViewsController.lastCreatedView;
+        fakePlatformViewsController.lastCreatedView!;
 
     expect(platformWebView.userAgent, isNull);
 
@@ -892,9 +881,9 @@
 }
 
 class FakePlatformWebView {
-  FakePlatformWebView(int id, Map<dynamic, dynamic> params) {
+  FakePlatformWebView(int? id, Map<dynamic, dynamic> params) {
     if (params.containsKey('initialUrl')) {
-      final String initialUrl = params['initialUrl'];
+      final String? initialUrl = params['initialUrl'];
       if (initialUrl != null) {
         history.add(initialUrl);
         currentPosition++;
@@ -914,20 +903,20 @@
     channel.setMockMethodCallHandler(onMethodCall);
   }
 
-  MethodChannel channel;
+  late MethodChannel channel;
 
-  List<String> history = <String>[];
+  List<String?> history = <String?>[];
   int currentPosition = -1;
   int amountOfReloadsOnCurrentUrl = 0;
   bool hasCache = true;
 
-  String get currentUrl => history.isEmpty ? null : history[currentPosition];
-  JavascriptMode javascriptMode;
-  List<String> javascriptChannelNames;
+  String? get currentUrl => history.isEmpty ? null : history[currentPosition];
+  JavascriptMode? javascriptMode;
+  List<String>? javascriptChannelNames;
 
-  bool hasNavigationDelegate;
-  bool debuggingEnabled;
-  String userAgent;
+  bool? hasNavigationDelegate;
+  bool? debuggingEnabled;
+  String? userAgent;
 
   Future<dynamic> onMethodCall(MethodCall call) {
     switch (call.method) {
@@ -949,34 +938,28 @@
         break;
       case 'canGoBack':
         return Future<bool>.sync(() => currentPosition > 0);
-        break;
       case 'canGoForward':
         return Future<bool>.sync(() => currentPosition < history.length - 1);
-        break;
       case 'goBack':
         currentPosition = max(-1, currentPosition - 1);
         return Future<void>.sync(() {});
-        break;
       case 'goForward':
         currentPosition = min(history.length - 1, currentPosition + 1);
         return Future<void>.sync(() {});
       case 'reload':
         amountOfReloadsOnCurrentUrl++;
         return Future<void>.sync(() {});
-        break;
       case 'currentUrl':
-        return Future<String>.value(currentUrl);
-        break;
+        return Future<String?>.value(currentUrl);
       case 'evaluateJavascript':
         return Future<dynamic>.value(call.arguments);
-        break;
       case 'addJavascriptChannels':
         final List<String> channelNames = List<String>.from(call.arguments);
-        javascriptChannelNames.addAll(channelNames);
+        javascriptChannelNames!.addAll(channelNames);
         break;
       case 'removeJavascriptChannels':
         final List<String> channelNames = List<String>.from(call.arguments);
-        javascriptChannelNames
+        javascriptChannelNames!
             .removeWhere((String channel) => channelNames.contains(channel));
         break;
       case 'clearCache':
@@ -994,14 +977,14 @@
     };
     final ByteData data = codec
         .encodeMethodCall(MethodCall('javascriptChannelMessage', arguments));
-    ServicesBinding.instance.defaultBinaryMessenger
-        .handlePlatformMessage(channel.name, data, (ByteData data) {});
+    ServicesBinding.instance!.defaultBinaryMessenger
+        .handlePlatformMessage(channel.name, data, (ByteData? data) {});
   }
 
   // Fakes a main frame navigation that was initiated by the webview, e.g when
   // the user clicks a link in the currently loaded page.
   void fakeNavigate(String url) {
-    if (!hasNavigationDelegate) {
+    if (!hasNavigationDelegate!) {
       print('no navigation delegate');
       _loadUrl(url);
       return;
@@ -1013,9 +996,9 @@
     };
     final ByteData data =
         codec.encodeMethodCall(MethodCall('navigationRequest', arguments));
-    ServicesBinding.instance.defaultBinaryMessenger
-        .handlePlatformMessage(channel.name, data, (ByteData data) {
-      final bool allow = codec.decodeEnvelope(data);
+    ServicesBinding.instance!.defaultBinaryMessenger
+        .handlePlatformMessage(channel.name, data, (ByteData? data) {
+      final bool allow = codec.decodeEnvelope(data!);
       if (allow) {
         _loadUrl(url);
       }
@@ -1030,10 +1013,10 @@
       <dynamic, dynamic>{'url': currentUrl},
     ));
 
-    ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
+    ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
       channel.name,
       data,
-      (ByteData data) {},
+      (ByteData? data) {},
     );
   }
 
@@ -1045,14 +1028,14 @@
       <dynamic, dynamic>{'url': currentUrl},
     ));
 
-    ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
+    ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
       channel.name,
       data,
-      (ByteData data) {},
+      (ByteData? data) {},
     );
   }
 
-  void _loadUrl(String url) {
+  void _loadUrl(String? url) {
     history = history.sublist(0, currentPosition + 1);
     history.add(url);
     currentPosition++;
@@ -1061,13 +1044,13 @@
 }
 
 class _FakePlatformViewsController {
-  FakePlatformWebView lastCreatedView;
+  FakePlatformWebView? lastCreatedView;
 
   Future<dynamic> fakePlatformViewsMethodHandler(MethodCall call) {
     switch (call.method) {
       case 'create':
         final Map<dynamic, dynamic> args = call.arguments;
-        final Map<dynamic, dynamic> params = _decodeParams(args['params']);
+        final Map<dynamic, dynamic> params = _decodeParams(args['params'])!;
         lastCreatedView = FakePlatformWebView(
           args['id'],
           params,
@@ -1083,7 +1066,7 @@
   }
 }
 
-Map<dynamic, dynamic> _decodeParams(Uint8List paramsMessage) {
+Map<dynamic, dynamic>? _decodeParams(Uint8List paramsMessage) {
   final ByteBuffer buffer = paramsMessage.buffer;
   final ByteData messageBytes = buffer.asByteData(
     paramsMessage.offsetInBytes,
@@ -1114,9 +1097,8 @@
         return Future<bool>.sync(() {
           return hadCookies;
         });
-        break;
     }
-    return Future<bool>.sync(() => null);
+    return Future<bool>.sync(() => true);
   }
 
   void reset() {
@@ -1125,26 +1107,26 @@
 }
 
 class MyWebViewPlatform implements WebViewPlatform {
-  MyWebViewPlatformController lastPlatformBuilt;
+  MyWebViewPlatformController? lastPlatformBuilt;
 
   @override
   Widget build({
-    BuildContext context,
-    CreationParams creationParams,
-    @required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
-    @required WebViewPlatformCreatedCallback onWebViewPlatformCreated,
-    Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
+    BuildContext? context,
+    CreationParams? creationParams,
+    required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
+    WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
+    Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers,
   }) {
     assert(onWebViewPlatformCreated != null);
     lastPlatformBuilt = MyWebViewPlatformController(
         creationParams, gestureRecognizers, webViewPlatformCallbacksHandler);
-    onWebViewPlatformCreated(lastPlatformBuilt);
+    onWebViewPlatformCreated!(lastPlatformBuilt);
     return Container();
   }
 
   @override
   Future<bool> clearCookies() {
-    return Future<bool>.sync(() => null);
+    return Future<bool>.sync(() => true);
   }
 }
 
@@ -1153,25 +1135,24 @@
       WebViewPlatformCallbacksHandler platformHandler)
       : super(platformHandler);
 
-  CreationParams creationParams;
-  Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers;
+  CreationParams? creationParams;
+  Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers;
 
-  String lastUrlLoaded;
-  Map<String, String> lastRequestHeaders;
+  String? lastUrlLoaded;
+  Map<String, String>? lastRequestHeaders;
 
   @override
-  Future<void> loadUrl(String url, Map<String, String> headers) {
+  Future<void> loadUrl(String url, Map<String, String>? headers) async {
     equals(1, 1);
     lastUrlLoaded = url;
     lastRequestHeaders = headers;
-    return null;
   }
 }
 
 class MatchesWebSettings extends Matcher {
   MatchesWebSettings(this._webSettings);
 
-  final WebSettings _webSettings;
+  final WebSettings? _webSettings;
 
   @override
   Description describe(Description description) =>
@@ -1180,13 +1161,13 @@
   @override
   bool matches(
       covariant WebSettings webSettings, Map<dynamic, dynamic> matchState) {
-    return _webSettings.javascriptMode == webSettings.javascriptMode &&
-        _webSettings.hasNavigationDelegate ==
+    return _webSettings!.javascriptMode == webSettings.javascriptMode &&
+        _webSettings!.hasNavigationDelegate ==
             webSettings.hasNavigationDelegate &&
-        _webSettings.debuggingEnabled == webSettings.debuggingEnabled &&
-        _webSettings.gestureNavigationEnabled ==
+        _webSettings!.debuggingEnabled == webSettings.debuggingEnabled &&
+        _webSettings!.gestureNavigationEnabled ==
             webSettings.gestureNavigationEnabled &&
-        _webSettings.userAgent == webSettings.userAgent;
+        _webSettings!.userAgent == webSettings.userAgent;
   }
 }
 
@@ -1204,7 +1185,7 @@
       Map<dynamic, dynamic> matchState) {
     return _creationParams.initialUrl == creationParams.initialUrl &&
         MatchesWebSettings(_creationParams.webSettings)
-            .matches(creationParams.webSettings, matchState) &&
+            .matches(creationParams.webSettings!, matchState) &&
         orderedEquals(_creationParams.javascriptChannelNames)
             .matches(creationParams.javascriptChannelNames, matchState);
   }
diff --git a/script/nnbd_plugins.sh b/script/nnbd_plugins.sh
index 8b73ecc..6e08c72 100644
--- a/script/nnbd_plugins.sh
+++ b/script/nnbd_plugins.sh
@@ -15,6 +15,7 @@
   "plugin_platform_interface"
   "url_launcher"
   "video_player"
+  "webview_flutter"
 )
 
 export EXCLUDED_PLUGINS_FROM_STABLE=$(IFS=, ; echo "${NNBD_PLUGINS_LIST[*]}")