url change for platform interface (#3323)

diff --git a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md
index d763e97..b94310b 100644
--- a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md
+++ b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md
@@ -1,5 +1,6 @@
-## NEXT
+## 2.1.0
 
+* Adds support to track url changes. See `PlatformNavigationDelegate.setOnUrlChange`.
 * Aligns Dart and Flutter SDK constraints.
 
 ## 2.0.2
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_navigation_delegate.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_navigation_delegate.dart
index ec7af71..096975b 100644
--- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_navigation_delegate.dart
+++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_navigation_delegate.dart
@@ -22,6 +22,10 @@
 /// Signature for callbacks that report a resource loading error.
 typedef WebResourceErrorCallback = void Function(WebResourceError error);
 
+/// Signature for callbacks that notify the host application of a change to the
+/// url of the web view.
+typedef UrlChangeCallback = void Function(UrlChange change);
+
 /// An interface defining navigation events that occur on the native platform.
 ///
 /// The [PlatformWebViewController] is notifying this delegate on events that
@@ -105,4 +109,13 @@
     throw UnimplementedError(
         'setOnWebResourceError is not implemented on the current platform.');
   }
+
+  /// Invoked when the underlying web view changes to a new url.
+  ///
+  /// See [PlatformWebViewController.setPlatformNavigationDelegate].
+  Future<void> setOnUrlChange(UrlChangeCallback onUrlChange) {
+    throw UnimplementedError(
+      'setOnUrlChange is not implemented on the current platform.',
+    );
+  }
 }
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/types.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/types.dart
index 4df8800..693a264 100644
--- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/types.dart
+++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/types.dart
@@ -11,5 +11,6 @@
 export 'platform_webview_controller_creation_params.dart';
 export 'platform_webview_cookie_manager_creation_params.dart';
 export 'platform_webview_widget_creation_params.dart';
+export 'url_change.dart';
 export 'web_resource_error.dart';
 export 'webview_cookie.dart';
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/url_change.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/url_change.dart
new file mode 100644
index 0000000..622b019
--- /dev/null
+++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/url_change.dart
@@ -0,0 +1,29 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/cupertino.dart';
+
+/// Details of the change to a web view's url.
+///
+/// Platform specific implementations can add additional fields by extending
+/// this class.
+///
+/// This example demonstrates how to extend the [UrlChange] to provide
+/// additional platform specific parameters:
+///
+/// ```dart
+/// class AndroidUrlChange extends UrlChange {
+///   const AndroidUrlChange({required super.url, required this.isReload});
+///
+///   final bool isReload;
+/// }
+/// ```
+@immutable
+class UrlChange {
+  /// Creates a new [UrlChange].
+  const UrlChange({required this.url});
+
+  /// The new url of the web view.
+  final String? url;
+}
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml b/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml
index c69645d..36a0418 100644
--- a/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml
+++ b/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml
@@ -4,7 +4,7 @@
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview_flutter%22
 # NOTE: We strongly prefer non-breaking changes, even at the expense of a
 # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
-version: 2.0.2
+version: 2.1.0
 
 environment:
   sdk: ">=2.17.0 <3.0.0"
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/test/platform_navigation_delegate_test.dart b/packages/webview_flutter/webview_flutter_platform_interface/test/platform_navigation_delegate_test.dart
index 8535e87..f06902c 100644
--- a/packages/webview_flutter/webview_flutter_platform_interface/test/platform_navigation_delegate_test.dart
+++ b/packages/webview_flutter/webview_flutter_platform_interface/test/platform_navigation_delegate_test.dart
@@ -51,7 +51,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of setOnNavigationRequest should throw unimplemented error',
       () {
     final PlatformNavigationDelegate callbackDelegate =
@@ -66,7 +65,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of setOnPageStarted should throw unimplemented error',
       () {
     final PlatformNavigationDelegate callbackDelegate =
@@ -80,7 +78,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of setOnPageFinished should throw unimplemented error',
       () {
     final PlatformNavigationDelegate callbackDelegate =
@@ -94,7 +91,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of setOnProgress should throw unimplemented error',
       () {
     final PlatformNavigationDelegate callbackDelegate =
@@ -108,7 +104,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of setOnWebResourceError should throw unimplemented error',
       () {
     final PlatformNavigationDelegate callbackDelegate =
@@ -120,6 +115,19 @@
       throwsUnimplementedError,
     );
   });
+
+  test(
+      'Default implementation of setOnUrlChange should throw unimplemented error',
+      () {
+    final PlatformNavigationDelegate callbackDelegate =
+        ExtendsPlatformNavigationDelegate(
+            const PlatformNavigationDelegateCreationParams());
+
+    expect(
+      () => callbackDelegate.setOnUrlChange((UrlChange change) {}),
+      throwsUnimplementedError,
+    );
+  });
 }
 
 class MockWebViewPlatformWithMixin extends MockWebViewPlatform
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/test/platform_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_platform_interface/test/platform_webview_controller_test.dart
index 80fd625..b322688 100644
--- a/packages/webview_flutter/webview_flutter_platform_interface/test/platform_webview_controller_test.dart
+++ b/packages/webview_flutter/webview_flutter_platform_interface/test/platform_webview_controller_test.dart
@@ -57,9 +57,7 @@
         isNotNull);
   });
 
-  test(
-      // ignore: lines_longer_than_80_chars
-      'Default implementation of loadFile should throw unimplemented error',
+  test('Default implementation of loadFile should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
         ExtendsPlatformWebViewController(
@@ -72,7 +70,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of loadFlutterAsset should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
@@ -86,7 +83,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of loadHtmlString should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
@@ -99,9 +95,7 @@
     );
   });
 
-  test(
-      // ignore: lines_longer_than_80_chars
-      'Default implementation of loadRequest should throw unimplemented error',
+  test('Default implementation of loadRequest should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
         ExtendsPlatformWebViewController(
@@ -113,9 +107,7 @@
     );
   });
 
-  test(
-      // ignore: lines_longer_than_80_chars
-      'Default implementation of currentUrl should throw unimplemented error',
+  test('Default implementation of currentUrl should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
         ExtendsPlatformWebViewController(
@@ -127,9 +119,7 @@
     );
   });
 
-  test(
-      // ignore: lines_longer_than_80_chars
-      'Default implementation of canGoBack should throw unimplemented error',
+  test('Default implementation of canGoBack should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
         ExtendsPlatformWebViewController(
@@ -142,7 +132,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of canGoForward should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
@@ -155,9 +144,7 @@
     );
   });
 
-  test(
-      // ignore: lines_longer_than_80_chars
-      'Default implementation of goBack should throw unimplemented error', () {
+  test('Default implementation of goBack should throw unimplemented error', () {
     final PlatformWebViewController controller =
         ExtendsPlatformWebViewController(
             const PlatformWebViewControllerCreationParams());
@@ -168,9 +155,7 @@
     );
   });
 
-  test(
-      // ignore: lines_longer_than_80_chars
-      'Default implementation of goForward should throw unimplemented error',
+  test('Default implementation of goForward should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
         ExtendsPlatformWebViewController(
@@ -182,9 +167,7 @@
     );
   });
 
-  test(
-      // ignore: lines_longer_than_80_chars
-      'Default implementation of reload should throw unimplemented error', () {
+  test('Default implementation of reload should throw unimplemented error', () {
     final PlatformWebViewController controller =
         ExtendsPlatformWebViewController(
             const PlatformWebViewControllerCreationParams());
@@ -195,9 +178,7 @@
     );
   });
 
-  test(
-      // ignore: lines_longer_than_80_chars
-      'Default implementation of clearCache should throw unimplemented error',
+  test('Default implementation of clearCache should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
         ExtendsPlatformWebViewController(
@@ -210,7 +191,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of clearLocalStorage should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
@@ -239,7 +219,6 @@
   );
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of runJavaScript should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
@@ -253,7 +232,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of runJavaScriptReturningResult should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
@@ -267,7 +245,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of addJavaScriptChannel should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
@@ -286,7 +263,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of removeJavaScriptChannel should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
@@ -299,9 +275,7 @@
     );
   });
 
-  test(
-      // ignore: lines_longer_than_80_chars
-      'Default implementation of getTitle should throw unimplemented error',
+  test('Default implementation of getTitle should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
         ExtendsPlatformWebViewController(
@@ -313,9 +287,7 @@
     );
   });
 
-  test(
-      // ignore: lines_longer_than_80_chars
-      'Default implementation of scrollTo should throw unimplemented error',
+  test('Default implementation of scrollTo should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
         ExtendsPlatformWebViewController(
@@ -327,9 +299,7 @@
     );
   });
 
-  test(
-      // ignore: lines_longer_than_80_chars
-      'Default implementation of scrollBy should throw unimplemented error',
+  test('Default implementation of scrollBy should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
         ExtendsPlatformWebViewController(
@@ -342,7 +312,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of getScrollPosition should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
@@ -355,9 +324,7 @@
     );
   });
 
-  test(
-      // ignore: lines_longer_than_80_chars
-      'Default implementation of enableZoom should throw unimplemented error',
+  test('Default implementation of enableZoom should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
         ExtendsPlatformWebViewController(
@@ -370,7 +337,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of setBackgroundColor should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
@@ -384,7 +350,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of setJavaScriptMode should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
@@ -398,7 +363,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of setUserAgent should throw unimplemented error',
       () {
     final PlatformWebViewController controller =
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/test/platform_webview_controller_test.mocks.dart b/packages/webview_flutter/webview_flutter_platform_interface/test/platform_webview_controller_test.mocks.dart
index db142fe..807ea02 100644
--- a/packages/webview_flutter/webview_flutter_platform_interface/test/platform_webview_controller_test.mocks.dart
+++ b/packages/webview_flutter/webview_flutter_platform_interface/test/platform_webview_controller_test.mocks.dart
@@ -103,4 +103,14 @@
         returnValue: _i4.Future<void>.value(),
         returnValueForMissingStub: _i4.Future<void>.value(),
       ) as _i4.Future<void>);
+  @override
+  _i4.Future<void> setOnUrlChange(_i3.UrlChangeCallback? onUrlChange) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #setOnUrlChange,
+          [onUrlChange],
+        ),
+        returnValue: _i4.Future<void>.value(),
+        returnValueForMissingStub: _i4.Future<void>.value(),
+      ) as _i4.Future<void>);
 }
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/test/webview_platform_test.dart b/packages/webview_flutter/webview_flutter_platform_interface/test/webview_platform_test.dart
index ec24dd7..f1e4dbb 100644
--- a/packages/webview_flutter/webview_flutter_platform_interface/test/webview_platform_test.dart
+++ b/packages/webview_flutter/webview_flutter_platform_interface/test/webview_platform_test.dart
@@ -104,7 +104,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of createCookieManagerDelegate should throw unimplemented error',
       () {
     final WebViewPlatform webViewPlatform = ExtendsWebViewPlatform();
@@ -117,7 +116,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of createNavigationCallbackHandlerDelegate should throw unimplemented error',
       () {
     final WebViewPlatform webViewPlatform = ExtendsWebViewPlatform();
@@ -130,7 +128,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of createWebViewControllerDelegate should throw unimplemented error',
       () {
     final WebViewPlatform webViewPlatform = ExtendsWebViewPlatform();
@@ -143,7 +140,6 @@
   });
 
   test(
-      // ignore: lines_longer_than_80_chars
       'Default implementation of createWebViewWidgetDelegate should throw unimplemented error',
       () {
     final WebViewPlatform webViewPlatform = ExtendsWebViewPlatform();