[webview_flutter] Add support for limitsNavigationsToAppBoundDomains (#4026)

`WebKitWebViewControllerCreationParams` doesn't allow the configuration of limitsNavigationsToAppBoundDomains

https://webkit.org/blog/10882/app-bound-domains/

It's very useful after ios14 if you want users to be able to call runJavaScript on a non local web-page.

This PR adds support for it
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md
index 566f23f..69c700f 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md
+++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 3.5.0
+
+* Adds support to limit navigation to pages within the app’s domain. See
+  `WebKitWebViewControllerCreationParams.limitsNavigationsToAppBoundDomains`.
+
 ## 3.4.4
 
 * Removes obsolete null checks on non-nullable values.
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebViewConfigurationHostApiTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebViewConfigurationHostApiTests.m
index 2ec74d0..98be6df 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebViewConfigurationHostApiTests.m
+++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebViewConfigurationHostApiTests.m
@@ -62,6 +62,24 @@
   XCTAssertNil(error);
 }
 
+- (void)testSetLimitsNavigationsToAppBoundDomains API_AVAILABLE(ios(14.0)) {
+  WKWebViewConfiguration *mockWebViewConfiguration = OCMClassMock([WKWebViewConfiguration class]);
+
+  FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init];
+  [instanceManager addDartCreatedInstance:mockWebViewConfiguration withIdentifier:0];
+
+  FWFWebViewConfigurationHostApiImpl *hostAPI = [[FWFWebViewConfigurationHostApiImpl alloc]
+      initWithBinaryMessenger:OCMProtocolMock(@protocol(FlutterBinaryMessenger))
+              instanceManager:instanceManager];
+
+  FlutterError *error;
+  [hostAPI setLimitsNavigationsToAppBoundDomainsForConfigurationWithIdentifier:@0
+                                                                     isLimited:@NO
+                                                                         error:&error];
+  OCMVerify([mockWebViewConfiguration setLimitsNavigationsToAppBoundDomains:NO]);
+  XCTAssertNil(error);
+}
+
 - (void)testSetMediaTypesRequiringUserActionForPlayback {
   WKWebViewConfiguration *mockWebViewConfiguration = OCMClassMock([WKWebViewConfiguration class]);
 
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.h
index 45b1e42..24b6346 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.h
+++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.h
@@ -1,7 +1,7 @@
 // Copyright 2013 The Flutter Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-// Autogenerated from Pigeon (v9.2.4), do not edit directly.
+// Autogenerated from Pigeon (v9.2.5), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 
 #import <Foundation/Foundation.h>
@@ -480,6 +480,10 @@
                                                              error:
                                                                  (FlutterError *_Nullable *_Nonnull)
                                                                      error;
+- (void)setLimitsNavigationsToAppBoundDomainsForConfigurationWithIdentifier:(NSNumber *)identifier
+                                                                  isLimited:(NSNumber *)limit
+                                                                      error:(FlutterError *_Nullable
+                                                                                 *_Nonnull)error;
 - (void)
     setMediaTypesRequiresUserActionForConfigurationWithIdentifier:(NSNumber *)identifier
                                                          forTypes:
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.m
index 3a5dff6..fc28c28 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.m
+++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.m
@@ -1,7 +1,7 @@
 // Copyright 2013 The Flutter Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-// Autogenerated from Pigeon (v9.2.4), do not edit directly.
+// Autogenerated from Pigeon (v9.2.5), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 
 #import "FWFGeneratedWebKitApis.h"
@@ -1005,6 +1005,34 @@
   {
     FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc]
            initWithName:@"dev.flutter.pigeon.WKWebViewConfigurationHostApi."
+                        @"setLimitsNavigationsToAppBoundDomains"
+        binaryMessenger:binaryMessenger
+                  codec:FWFWKWebViewConfigurationHostApiGetCodec()];
+    if (api) {
+      NSCAssert([api respondsToSelector:@selector
+                     (setLimitsNavigationsToAppBoundDomainsForConfigurationWithIdentifier:
+                                                                                isLimited:error:)],
+                @"FWFWKWebViewConfigurationHostApi api (%@) doesn't respond to "
+                @"@selector(setLimitsNavigationsToAppBoundDomainsForConfigurationWithIdentifier:"
+                @"isLimited:error:)",
+                api);
+      [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
+        NSArray *args = message;
+        NSNumber *arg_identifier = GetNullableObjectAtIndex(args, 0);
+        NSNumber *arg_limit = GetNullableObjectAtIndex(args, 1);
+        FlutterError *error;
+        [api setLimitsNavigationsToAppBoundDomainsForConfigurationWithIdentifier:arg_identifier
+                                                                       isLimited:arg_limit
+                                                                           error:&error];
+        callback(wrapResult(nil, error));
+      }];
+    } else {
+      [channel setMessageHandler:nil];
+    }
+  }
+  {
+    FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc]
+           initWithName:@"dev.flutter.pigeon.WKWebViewConfigurationHostApi."
                         @"setMediaTypesRequiringUserActionForPlayback"
         binaryMessenger:binaryMessenger
                   codec:FWFWKWebViewConfigurationHostApiGetCodec()];
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebViewConfigurationHostApi.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebViewConfigurationHostApi.m
index 987d3f4..762c07b 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebViewConfigurationHostApi.m
+++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebViewConfigurationHostApi.m
@@ -104,6 +104,23 @@
       setAllowsInlineMediaPlayback:allow.boolValue];
 }
 
+- (void)setLimitsNavigationsToAppBoundDomainsForConfigurationWithIdentifier:
+            (nonnull NSNumber *)identifier
+                                                                  isLimited:
+                                                                      (nonnull NSNumber *)limit
+                                                                      error:(FlutterError *_Nullable
+                                                                                 *_Nonnull)error {
+  if (@available(iOS 14, *)) {
+    [[self webViewConfigurationForIdentifier:identifier]
+        setLimitsNavigationsToAppBoundDomains:limit.boolValue];
+  } else {
+    *error = [FlutterError
+        errorWithCode:@"FWFUnsupportedVersionError"
+              message:@"setLimitsNavigationsToAppBoundDomains is only supported on versions 14+."
+              details:nil];
+  }
+}
+
 - (void)
     setMediaTypesRequiresUserActionForConfigurationWithIdentifier:(nonnull NSNumber *)identifier
                                                          forTypes:
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.g.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.g.dart
index 2ce5055..0f3547a 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.g.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.g.dart
@@ -1,7 +1,7 @@
 // Copyright 2013 The Flutter Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-// Autogenerated from Pigeon (v9.2.4), do not edit directly.
+// Autogenerated from Pigeon (v9.2.5), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
 
@@ -1067,6 +1067,30 @@
     }
   }
 
+  Future<void> setLimitsNavigationsToAppBoundDomains(
+      int arg_identifier, bool arg_limit) async {
+    final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+        'dev.flutter.pigeon.WKWebViewConfigurationHostApi.setLimitsNavigationsToAppBoundDomains',
+        codec,
+        binaryMessenger: _binaryMessenger);
+    final List<Object?>? replyList = await channel
+        .send(<Object?>[arg_identifier, arg_limit]) as List<Object?>?;
+    if (replyList == null) {
+      throw PlatformException(
+        code: 'channel-error',
+        message: 'Unable to establish connection on channel.',
+      );
+    } else if (replyList.length > 1) {
+      throw PlatformException(
+        code: replyList[0]! as String,
+        message: replyList[1] as String?,
+        details: replyList[2],
+      );
+    } else {
+      return;
+    }
+  }
+
   Future<void> setMediaTypesRequiringUserActionForPlayback(int arg_identifier,
       List<WKAudiovisualMediaTypeEnumData?> arg_types) async {
     final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart
index 070f554..31cbbf3 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart
@@ -678,6 +678,20 @@
     );
   }
 
+  /// Indicates whether the web view limits navigation to pages within the app’s domain.
+  ///
+  /// When navigation is limited, Javascript evaluation is unrestricted.
+  /// See https://webkit.org/blog/10882/app-bound-domains/
+  ///
+  /// Sets [WKWebViewConfiguration.limitsNavigationsToAppBoundDomains](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/3585117-limitsnavigationstoappbounddomai?language=objc).
+  Future<void> setLimitsNavigationsToAppBoundDomains(bool limit) {
+    return _webViewConfigurationApi
+        .setLimitsNavigationsToAppBoundDomainsForInstances(
+      this,
+      limit,
+    );
+  }
+
   /// The media types that require a user gesture to begin playing.
   ///
   /// Use [WKAudiovisualMediaType.none] to indicate that no user gestures are
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart
index 07a32ae..daba854 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart
@@ -629,6 +629,17 @@
     );
   }
 
+  /// Calls [setLimitsNavigationsToAppBoundDomains] with the ids of the provided object instances.
+  Future<void> setLimitsNavigationsToAppBoundDomainsForInstances(
+    WKWebViewConfiguration instance,
+    bool limit,
+  ) {
+    return setLimitsNavigationsToAppBoundDomains(
+      instanceManager.getIdentifier(instance)!,
+      limit,
+    );
+  }
+
   /// Calls [setMediaTypesRequiringUserActionForPlayback] with the ids of the provided object instances.
   Future<void> setMediaTypesRequiringUserActionForPlaybackForInstances(
     WKWebViewConfiguration instance,
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart
index e49d412..b0666e6 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart
@@ -48,6 +48,7 @@
       PlaybackMediaTypes.video,
     },
     this.allowsInlineMediaPlayback = false,
+    this.limitsNavigationsToAppBoundDomains = false,
     @visibleForTesting InstanceManager? instanceManager,
   }) : _instanceManager = instanceManager ?? NSObject.globalInstanceManager {
     _configuration = webKitProxy.createWebViewConfiguration(
@@ -68,6 +69,8 @@
       );
     }
     _configuration.setAllowsInlineMediaPlayback(allowsInlineMediaPlayback);
+    _configuration.setLimitsNavigationsToAppBoundDomains(
+        limitsNavigationsToAppBoundDomains);
   }
 
   /// Constructs a [WebKitWebViewControllerCreationParams] using a
@@ -83,11 +86,14 @@
       PlaybackMediaTypes.video,
     },
     bool allowsInlineMediaPlayback = false,
+    bool limitsNavigationsToAppBoundDomains = false,
     @visibleForTesting InstanceManager? instanceManager,
   }) : this(
           webKitProxy: webKitProxy,
           mediaTypesRequiringUserAction: mediaTypesRequiringUserAction,
           allowsInlineMediaPlayback: allowsInlineMediaPlayback,
+          limitsNavigationsToAppBoundDomains:
+              limitsNavigationsToAppBoundDomains,
           instanceManager: instanceManager,
         );
 
@@ -104,6 +110,13 @@
   /// Defaults to false.
   final bool allowsInlineMediaPlayback;
 
+  /// Whether to limit navigation to configured domains.
+  ///
+  /// See https://webkit.org/blog/10882/app-bound-domains/
+  /// (Only available for iOS > 14.0)
+  /// Defaults to false.
+  final bool limitsNavigationsToAppBoundDomains;
+
   /// Handles constructing objects and calling static methods for the WebKit
   /// native library.
   @visibleForTesting
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart
index 20d4ee4..ac13958 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart
@@ -417,6 +417,11 @@
   void setAllowsInlineMediaPlayback(int identifier, bool allow);
 
   @ObjCSelector(
+    'setLimitsNavigationsToAppBoundDomainsForConfigurationWithIdentifier:isLimited:',
+  )
+  void setLimitsNavigationsToAppBoundDomains(int identifier, bool limit);
+
+  @ObjCSelector(
     'setMediaTypesRequiresUserActionForConfigurationWithIdentifier:forTypes:',
   )
   void setMediaTypesRequiringUserActionForPlayback(
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml
index db7407b..9056fd9 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml
+++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml
@@ -2,7 +2,7 @@
 description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control.
 repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_wkwebview
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
-version: 3.4.4
+version: 3.5.0
 
 environment:
   sdk: ">=2.18.0 <4.0.0"
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.g.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.g.dart
index ff09d44..faf0123 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.g.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.g.dart
@@ -1,7 +1,7 @@
 // Copyright 2013 The Flutter Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-// Autogenerated from Pigeon (v9.2.4), do not edit directly.
+// Autogenerated from Pigeon (v9.2.5), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import
 // ignore_for_file: avoid_relative_lib_imports
@@ -369,6 +369,8 @@
 
   void setAllowsInlineMediaPlayback(int identifier, bool allow);
 
+  void setLimitsNavigationsToAppBoundDomains(int identifier, bool limit);
+
   void setMediaTypesRequiringUserActionForPlayback(
       int identifier, List<WKAudiovisualMediaTypeEnumData?> types);
 
@@ -450,6 +452,33 @@
     }
     {
       final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+          'dev.flutter.pigeon.WKWebViewConfigurationHostApi.setLimitsNavigationsToAppBoundDomains',
+          codec,
+          binaryMessenger: binaryMessenger);
+      if (api == null) {
+        _testBinaryMessengerBinding!.defaultBinaryMessenger
+            .setMockDecodedMessageHandler<Object?>(channel, null);
+      } else {
+        _testBinaryMessengerBinding!.defaultBinaryMessenger
+            .setMockDecodedMessageHandler<Object?>(channel,
+                (Object? message) async {
+          assert(message != null,
+              'Argument for dev.flutter.pigeon.WKWebViewConfigurationHostApi.setLimitsNavigationsToAppBoundDomains was null.');
+          final List<Object?> args = (message as List<Object?>?)!;
+          final int? arg_identifier = (args[0] as int?);
+          assert(arg_identifier != null,
+              'Argument for dev.flutter.pigeon.WKWebViewConfigurationHostApi.setLimitsNavigationsToAppBoundDomains was null, expected non-null int.');
+          final bool? arg_limit = (args[1] as bool?);
+          assert(arg_limit != null,
+              'Argument for dev.flutter.pigeon.WKWebViewConfigurationHostApi.setLimitsNavigationsToAppBoundDomains was null, expected non-null bool.');
+          api.setLimitsNavigationsToAppBoundDomains(
+              arg_identifier!, arg_limit!);
+          return <Object?>[];
+        });
+      }
+    }
+    {
+      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
           'dev.flutter.pigeon.WKWebViewConfigurationHostApi.setMediaTypesRequiringUserActionForPlayback',
           codec,
           binaryMessenger: binaryMessenger);
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.mocks.dart
index 355d69e..8a9cc19 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.mocks.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.mocks.dart
@@ -69,6 +69,21 @@
         returnValueForMissingStub: null,
       );
   @override
+  void setLimitsNavigationsToAppBoundDomains(
+    int? identifier,
+    bool? limit,
+  ) =>
+      super.noSuchMethod(
+        Invocation.method(
+          #setLimitsNavigationsToAppBoundDomains,
+          [
+            identifier,
+            limit,
+          ],
+        ),
+        returnValueForMissingStub: null,
+      );
+  @override
   void setMediaTypesRequiringUserActionForPlayback(
     int? identifier,
     List<_i3.WKAudiovisualMediaTypeEnumData?>? types,
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart
index e2d53bc..ac266ff 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart
@@ -441,6 +441,14 @@
         ));
       });
 
+      test('limitsNavigationsToAppBoundDomains', () {
+        webViewConfiguration.setLimitsNavigationsToAppBoundDomains(true);
+        verify(mockPlatformHostApi.setLimitsNavigationsToAppBoundDomains(
+          instanceManager.getIdentifier(webViewConfiguration),
+          true,
+        ));
+      });
+
       test('mediaTypesRequiringUserActionForPlayback', () {
         webViewConfiguration.setMediaTypesRequiringUserActionForPlayback(
           <WKAudiovisualMediaType>{
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart
index 6019640..0291867 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart
@@ -298,6 +298,21 @@
         returnValueForMissingStub: null,
       );
   @override
+  void setLimitsNavigationsToAppBoundDomains(
+    int? identifier,
+    bool? limit,
+  ) =>
+      super.noSuchMethod(
+        Invocation.method(
+          #setLimitsNavigationsToAppBoundDomains,
+          [
+            identifier,
+            limit,
+          ],
+        ),
+        returnValueForMissingStub: null,
+      );
+  @override
   void setMediaTypesRequiringUserActionForPlayback(
     int? identifier,
     List<_i4.WKAudiovisualMediaTypeEnumData?>? types,
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart
index 7e61d36..4e56c21 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart
@@ -140,6 +140,24 @@
         );
       });
 
+      test('limitsNavigationsToAppBoundDomains', () {
+        final MockWKWebViewConfiguration mockConfiguration =
+            MockWKWebViewConfiguration();
+
+        WebKitWebViewControllerCreationParams(
+          webKitProxy: WebKitProxy(
+            createWebViewConfiguration: ({InstanceManager? instanceManager}) {
+              return mockConfiguration;
+            },
+          ),
+          limitsNavigationsToAppBoundDomains: true,
+        );
+
+        verify(
+          mockConfiguration.setLimitsNavigationsToAppBoundDomains(true),
+        );
+      });
+
       test('mediaTypesRequiringUserAction', () {
         final MockWKWebViewConfiguration mockConfiguration =
             MockWKWebViewConfiguration();
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.mocks.dart
index 9eb0397..de787a1 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.mocks.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.mocks.dart
@@ -848,6 +848,16 @@
         returnValueForMissingStub: _i6.Future<void>.value(),
       ) as _i6.Future<void>);
   @override
+  _i6.Future<void> setLimitsNavigationsToAppBoundDomains(bool? limit) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #setLimitsNavigationsToAppBoundDomains,
+          [limit],
+        ),
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
+  @override
   _i6.Future<void> setMediaTypesRequiringUserActionForPlayback(
           Set<_i5.WKAudiovisualMediaType>? types) =>
       (super.noSuchMethod(
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_widget_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_widget_test.mocks.dart
index fe86de7..b171e28 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_widget_test.mocks.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_widget_test.mocks.dart
@@ -176,6 +176,16 @@
         returnValueForMissingStub: _i3.Future<void>.value(),
       ) as _i3.Future<void>);
   @override
+  _i3.Future<void> setLimitsNavigationsToAppBoundDomains(bool? limit) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #setLimitsNavigationsToAppBoundDomains,
+          [limit],
+        ),
+        returnValue: _i3.Future<void>.value(),
+        returnValueForMissingStub: _i3.Future<void>.value(),
+      ) as _i3.Future<void>);
+  @override
   _i3.Future<void> setMediaTypesRequiringUserActionForPlayback(
           Set<_i2.WKAudiovisualMediaType>? types) =>
       (super.noSuchMethod(