From dc5c6c73d0b5d2e1784e19ea2b07a8b13f2e09e2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 25 Feb 2025 14:21:18 -0500 Subject: [PATCH 1/8] impl --- .../webview_flutter_wkwebview/CHANGELOG.md | 5 + .../NavigationDelegateProxyAPITests.swift | 10 +- .../NavigationDelegateProxyAPIDelegate.swift | 6 +- .../WebKitLibrary.g.swift | 12 +- .../lib/src/common/web_kit.g.dart | 9 +- .../src/legacy/web_kit_webview_widget.dart | 10 +- .../lib/src/webkit_proxy.dart | 2 +- .../lib/src/webkit_webview_controller.dart | 42 +++---- .../pigeons/web_kit.dart | 5 +- .../webview_flutter_wkwebview/pubspec.yaml | 2 +- .../web_kit_webview_widget_test.mocks.dart | 113 ++++++++---------- .../test/webkit_navigation_delegate_test.dart | 98 +++++++-------- .../test/webkit_webview_controller_test.dart | 8 +- 13 files changed, 160 insertions(+), 162 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index 4df80f2f6788..94ea0ff9f2a9 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,3 +1,8 @@ +## 3.18.3 + +* Fixes crash where the native `AuthenticationChallengeResponse` could not be found for auth + requests. + ## 3.18.2 * Updates generated pigeon code to ensure the internal wrapper immediately sends constructor calls. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift index 2bda6591ae5b..2667cb7f0902 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift @@ -219,17 +219,17 @@ class TestNavigationDelegateApi: PigeonApiProtocolWKNavigationDelegate { challenge challengeArg: URLAuthenticationChallenge, completion: @escaping ( Result< - webview_flutter_wkwebview.AuthenticationChallengeResponse, + [Any?], webview_flutter_wkwebview.PigeonError > ) -> Void ) { didReceiveAuthenticationChallengeArgs = [webViewArg, challengeArg] completion( - .success( - AuthenticationChallengeResponse( - disposition: .useCredential, - credential: URLCredential(user: "user", password: "password", persistence: .none)))) + .success([ + URLSession.AuthChallengeDisposition.useCredential, + URLCredential(user: "user", password: "password", persistence: .none), + ])) } } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift index 4988bb60228a..0a960e51380a 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift @@ -244,7 +244,8 @@ public class NavigationDelegateImpl: NSObject, WKNavigationDelegate { DispatchQueue.main.async { switch result { case .success(let response): - completionHandler(response.disposition, response.credential) + completionHandler( + response[0] as! URLSession.AuthChallengeDisposition, response[1] as? URLCredential) case .failure(let error): completionHandler(.cancelAuthenticationChallenge, nil) onFailure("WKNavigationDelegate.didReceiveAuthenticationChallenge", error) @@ -266,7 +267,8 @@ public class NavigationDelegateImpl: NSObject, WKNavigationDelegate { DispatchQueue.main.async { switch result { case .success(let response): - completionHandler(response.disposition, response.credential) + completionHandler( + response[0] as! URLSession.AuthChallengeDisposition, response[1] as? URLCredential) case .failure(let error): completionHandler(.cancelAuthenticationChallenge, nil) onFailure("WKNavigationDelegate.didReceiveAuthenticationChallenge", error) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/WebKitLibrary.g.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/WebKitLibrary.g.swift index ffb16868aa59..d2b88d745e1b 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/WebKitLibrary.g.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/WebKitLibrary.g.swift @@ -3992,10 +3992,13 @@ protocol PigeonApiProtocolWKNavigationDelegate { pigeonInstance pigeonInstanceArg: WKNavigationDelegate, webView webViewArg: WKWebView, completion: @escaping (Result) -> Void) /// Asks the delegate to respond to an authentication challenge. + /// + /// Returns a List with a `UrlSessionAuthChallengeDisposition` and a nullable + /// `URLCredential`. func didReceiveAuthenticationChallenge( pigeonInstance pigeonInstanceArg: WKNavigationDelegate, webView webViewArg: WKWebView, challenge challengeArg: URLAuthenticationChallenge, - completion: @escaping (Result) -> Void) + completion: @escaping (Result<[Any?], PigeonError>) -> Void) } final class PigeonApiWKNavigationDelegate: PigeonApiProtocolWKNavigationDelegate { @@ -4333,10 +4336,13 @@ final class PigeonApiWKNavigationDelegate: PigeonApiProtocolWKNavigationDelegate } /// Asks the delegate to respond to an authentication challenge. + /// + /// Returns a List with a `UrlSessionAuthChallengeDisposition` and a nullable + /// `URLCredential`. func didReceiveAuthenticationChallenge( pigeonInstance pigeonInstanceArg: WKNavigationDelegate, webView webViewArg: WKWebView, challenge challengeArg: URLAuthenticationChallenge, - completion: @escaping (Result) -> Void + completion: @escaping (Result<[Any?], PigeonError>) -> Void ) { if pigeonRegistrar.ignoreCallsToDart { completion( @@ -4369,7 +4375,7 @@ final class PigeonApiWKNavigationDelegate: PigeonApiProtocolWKNavigationDelegate code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) } else { - let result = listResponse[0] as! AuthenticationChallengeResponse + let result = listResponse[0] as! [Any?] completion(.success(result)) } } 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 6856de8ef2e7..428e45c2f571 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 @@ -4326,6 +4326,9 @@ class WKNavigationDelegate extends NSObject { /// Asks the delegate to respond to an authentication challenge. /// + /// Returns a List with a `UrlSessionAuthChallengeDisposition` and a nullable + /// `URLCredential`. + /// /// For the associated Native object to be automatically garbage collected, /// it is required that the implementation of this `Function` doesn't have a /// strong reference to the encapsulating class instance. When this `Function` @@ -4343,7 +4346,7 @@ class WKNavigationDelegate extends NSObject { /// /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. - final Future Function( + final Future> Function( WKNavigationDelegate pigeon_instance, WKWebView webView, URLAuthenticationChallenge challenge, @@ -4387,7 +4390,7 @@ class WKNavigationDelegate extends NSObject { WKNavigationDelegate pigeon_instance, WKWebView webView, )? webViewWebContentProcessDidTerminate, - Future Function( + Future> Function( WKNavigationDelegate pigeon_instance, WKWebView webView, URLAuthenticationChallenge challenge, @@ -4693,7 +4696,7 @@ class WKNavigationDelegate extends NSObject { assert(arg_challenge != null, 'Argument for dev.flutter.pigeon.webview_flutter_wkwebview.WKNavigationDelegate.didReceiveAuthenticationChallenge was null, expected non-null URLAuthenticationChallenge.'); try { - final AuthenticationChallengeResponse output = + final List output = await (didReceiveAuthenticationChallenge ?? arg_pigeon_instance!.didReceiveAuthenticationChallenge) .call(arg_pigeon_instance!, arg_webView!, arg_challenge!); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart index 3caec799cfe5..016f1734b946 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart @@ -193,10 +193,10 @@ class WebKitWebViewPlatformController extends WebViewPlatformController { return NavigationResponsePolicy.allow; }, didReceiveAuthenticationChallenge: (_, __, ___) async { - return AuthenticationChallengeResponse( - disposition: - UrlSessionAuthChallengeDisposition.performDefaultHandling, - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ); }, @@ -751,7 +751,7 @@ class WebViewWidgetProxy { WKWebView webView, WKNavigationResponse navigationResponse, ) decidePolicyForNavigationResponse, - required Future Function( + required Future> Function( WKNavigationDelegate, WKWebView webView, URLAuthenticationChallenge challenge, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_proxy.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_proxy.dart index d60dedf3aa01..a9ecf777fefc 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_proxy.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_proxy.dart @@ -102,7 +102,7 @@ class WebKitProxy { WKNavigationDelegate, WKWebView, )? webViewWebContentProcessDidTerminate, - required Future Function( + required Future> Function( WKNavigationDelegate, WKWebView, URLAuthenticationChallenge, 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 cc04cb83c981..466524e8ef59 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 @@ -1213,32 +1213,34 @@ class WebKitNavigationDelegate extends PlatformNavigationDelegate { final String host = protectionSpace.host; final String? realm = protectionSpace.realm; - final Completer responseCompleter = - Completer(); + final Completer> responseCompleter = + Completer>(); callback( HttpAuthRequest( host: host, realm: realm, onProceed: (WebViewCredential credential) { - final AuthenticationChallengeResponse response = - proxy.newAuthenticationChallengeResponse( - disposition: UrlSessionAuthChallengeDisposition.useCredential, - credential: URLCredential.withUser( - user: credential.user, - password: credential.password, - persistence: UrlCredentialPersistence.forSession, - ), + final URLCredential userCredential = URLCredential.withUser( + user: credential.user, + password: credential.password, + persistence: UrlCredentialPersistence.forSession, + ); + responseCompleter.complete( + [ + UrlSessionAuthChallengeDisposition.useCredential, + userCredential, + ], ); - responseCompleter.complete(response); }, onCancel: () { - final AuthenticationChallengeResponse response = - proxy.newAuthenticationChallengeResponse( - disposition: UrlSessionAuthChallengeDisposition - .cancelAuthenticationChallenge, + responseCompleter.complete( + [ + UrlSessionAuthChallengeDisposition + .cancelAuthenticationChallenge, + null, + ], ); - responseCompleter.complete(response); }, ), ); @@ -1246,10 +1248,10 @@ class WebKitNavigationDelegate extends PlatformNavigationDelegate { return responseCompleter.future; } - return AuthenticationChallengeResponse( - disposition: - UrlSessionAuthChallengeDisposition.performDefaultHandling, - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ); } 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 dd247f247622..69267fa53720 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart @@ -746,8 +746,11 @@ abstract class WKNavigationDelegate extends NSObject { void Function(WKWebView webView)? webViewWebContentProcessDidTerminate; /// Asks the delegate to respond to an authentication challenge. + /// + /// This return value expects a List with a + /// `UrlSessionAuthChallengeDisposition` and a nullable `URLCredential`. @async - late AuthenticationChallengeResponse Function( + late List Function( WKWebView webView, URLAuthenticationChallenge challenge, ) didReceiveAuthenticationChallenge; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml index f86c23f22484..518e0b3465cb 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_wkwebview 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.18.2 +version: 3.18.3 environment: sdk: ^3.5.0 diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.mocks.dart index 58aa23e918a8..94e5749c461b 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.mocks.dart @@ -49,80 +49,72 @@ class _FakeURLRequest_2 extends _i1.SmartFake implements _i2.URLRequest { : super(parent, parentInvocation); } -class _FakeAuthenticationChallengeResponse_3 extends _i1.SmartFake - implements _i2.AuthenticationChallengeResponse { - _FakeAuthenticationChallengeResponse_3( - Object parent, - Invocation parentInvocation, - ) : super(parent, parentInvocation); -} - -class _FakeWKNavigationDelegate_4 extends _i1.SmartFake +class _FakeWKNavigationDelegate_3 extends _i1.SmartFake implements _i2.WKNavigationDelegate { - _FakeWKNavigationDelegate_4(Object parent, Invocation parentInvocation) + _FakeWKNavigationDelegate_3(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeWKPreferences_5 extends _i1.SmartFake implements _i2.WKPreferences { - _FakeWKPreferences_5(Object parent, Invocation parentInvocation) +class _FakeWKPreferences_4 extends _i1.SmartFake implements _i2.WKPreferences { + _FakeWKPreferences_4(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeWKScriptMessageHandler_6 extends _i1.SmartFake +class _FakeWKScriptMessageHandler_5 extends _i1.SmartFake implements _i2.WKScriptMessageHandler { - _FakeWKScriptMessageHandler_6(Object parent, Invocation parentInvocation) + _FakeWKScriptMessageHandler_5(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeWKWebView_7 extends _i1.SmartFake implements _i2.WKWebView { - _FakeWKWebView_7(Object parent, Invocation parentInvocation) +class _FakeWKWebView_6 extends _i1.SmartFake implements _i2.WKWebView { + _FakeWKWebView_6(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeWKWebViewConfiguration_8 extends _i1.SmartFake +class _FakeWKWebViewConfiguration_7 extends _i1.SmartFake implements _i2.WKWebViewConfiguration { - _FakeWKWebViewConfiguration_8(Object parent, Invocation parentInvocation) + _FakeWKWebViewConfiguration_7(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeUIViewWKWebView_9 extends _i1.SmartFake +class _FakeUIViewWKWebView_8 extends _i1.SmartFake implements _i2.UIViewWKWebView { - _FakeUIViewWKWebView_9(Object parent, Invocation parentInvocation) + _FakeUIViewWKWebView_8(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeWKUserContentController_10 extends _i1.SmartFake +class _FakeWKUserContentController_9 extends _i1.SmartFake implements _i2.WKUserContentController { - _FakeWKUserContentController_10(Object parent, Invocation parentInvocation) + _FakeWKUserContentController_9(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeWKWebsiteDataStore_11 extends _i1.SmartFake +class _FakeWKWebsiteDataStore_10 extends _i1.SmartFake implements _i2.WKWebsiteDataStore { - _FakeWKWebsiteDataStore_11(Object parent, Invocation parentInvocation) + _FakeWKWebsiteDataStore_10(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeWKWebpagePreferences_12 extends _i1.SmartFake +class _FakeWKWebpagePreferences_11 extends _i1.SmartFake implements _i2.WKWebpagePreferences { - _FakeWKWebpagePreferences_12(Object parent, Invocation parentInvocation) + _FakeWKWebpagePreferences_11(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeWKHTTPCookieStore_13 extends _i1.SmartFake +class _FakeWKHTTPCookieStore_12 extends _i1.SmartFake implements _i2.WKHTTPCookieStore { - _FakeWKHTTPCookieStore_13(Object parent, Invocation parentInvocation) + _FakeWKHTTPCookieStore_12(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeWKUIDelegate_14 extends _i1.SmartFake implements _i2.WKUIDelegate { - _FakeWKUIDelegate_14(Object parent, Invocation parentInvocation) +class _FakeWKUIDelegate_13 extends _i1.SmartFake implements _i2.WKUIDelegate { + _FakeWKUIDelegate_13(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakePlatformWebView_15 extends _i1.SmartFake +class _FakePlatformWebView_14 extends _i1.SmartFake implements _i3.PlatformWebView { - _FakePlatformWebView_15(Object parent, Invocation parentInvocation) + _FakePlatformWebView_14(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } @@ -398,7 +390,7 @@ class MockWKNavigationDelegate extends _i1.Mock )); @override - _i4.Future<_i2.AuthenticationChallengeResponse> Function( + _i4.Future> Function( _i2.WKNavigationDelegate, _i2.WKWebView, _i2.URLAuthenticationChallenge, @@ -409,13 +401,8 @@ class MockWKNavigationDelegate extends _i1.Mock _i2.WKWebView webView, _i2.URLAuthenticationChallenge challenge, ) => - _i4.Future<_i2.AuthenticationChallengeResponse>.value( - _FakeAuthenticationChallengeResponse_3( - this, - Invocation.getter(#didReceiveAuthenticationChallenge), - ), - ), - ) as _i4.Future<_i2.AuthenticationChallengeResponse> Function( + _i4.Future>.value([]), + ) as _i4.Future> Function( _i2.WKNavigationDelegate, _i2.WKWebView, _i2.URLAuthenticationChallenge, @@ -433,7 +420,7 @@ class MockWKNavigationDelegate extends _i1.Mock @override _i2.WKNavigationDelegate pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeWKNavigationDelegate_4( + returnValue: _FakeWKNavigationDelegate_3( this, Invocation.method(#pigeon_copy, []), ), @@ -487,7 +474,7 @@ class MockWKPreferences extends _i1.Mock implements _i2.WKPreferences { @override _i2.WKPreferences pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeWKPreferences_5( + returnValue: _FakeWKPreferences_4( this, Invocation.method(#pigeon_copy, []), ), @@ -553,7 +540,7 @@ class MockWKScriptMessageHandler extends _i1.Mock @override _i2.WKScriptMessageHandler pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeWKScriptMessageHandler_6( + returnValue: _FakeWKScriptMessageHandler_5( this, Invocation.method(#pigeon_copy, []), ), @@ -600,7 +587,7 @@ class MockWKWebView extends _i1.Mock implements _i2.WKWebView { @override _i2.WKWebView pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeWKWebView_7( + returnValue: _FakeWKWebView_6( this, Invocation.method(#pigeon_copy, []), ), @@ -638,7 +625,7 @@ class MockUIViewWKWebView extends _i1.Mock implements _i2.UIViewWKWebView { @override _i2.WKWebViewConfiguration get configuration => (super.noSuchMethod( Invocation.getter(#configuration), - returnValue: _FakeWKWebViewConfiguration_8( + returnValue: _FakeWKWebViewConfiguration_7( this, Invocation.getter(#configuration), ), @@ -665,7 +652,7 @@ class MockUIViewWKWebView extends _i1.Mock implements _i2.UIViewWKWebView { @override _i2.WKWebViewConfiguration pigeonVar_configuration() => (super.noSuchMethod( Invocation.method(#pigeonVar_configuration, []), - returnValue: _FakeWKWebViewConfiguration_8( + returnValue: _FakeWKWebViewConfiguration_7( this, Invocation.method(#pigeonVar_configuration, []), ), @@ -815,7 +802,7 @@ class MockUIViewWKWebView extends _i1.Mock implements _i2.UIViewWKWebView { @override _i2.UIViewWKWebView pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeUIViewWKWebView_9( + returnValue: _FakeUIViewWKWebView_8( this, Invocation.method(#pigeon_copy, []), ), @@ -889,7 +876,7 @@ class MockWKWebViewConfiguration extends _i1.Mock (super.noSuchMethod( Invocation.method(#getUserContentController, []), returnValue: _i4.Future<_i2.WKUserContentController>.value( - _FakeWKUserContentController_10( + _FakeWKUserContentController_9( this, Invocation.method(#getUserContentController, []), ), @@ -909,7 +896,7 @@ class MockWKWebViewConfiguration extends _i1.Mock (super.noSuchMethod( Invocation.method(#getWebsiteDataStore, []), returnValue: _i4.Future<_i2.WKWebsiteDataStore>.value( - _FakeWKWebsiteDataStore_11( + _FakeWKWebsiteDataStore_10( this, Invocation.method(#getWebsiteDataStore, []), ), @@ -928,7 +915,7 @@ class MockWKWebViewConfiguration extends _i1.Mock _i4.Future<_i2.WKPreferences> getPreferences() => (super.noSuchMethod( Invocation.method(#getPreferences, []), returnValue: _i4.Future<_i2.WKPreferences>.value( - _FakeWKPreferences_5( + _FakeWKPreferences_4( this, Invocation.method(#getPreferences, []), ), @@ -968,7 +955,7 @@ class MockWKWebViewConfiguration extends _i1.Mock (super.noSuchMethod( Invocation.method(#getDefaultWebpagePreferences, []), returnValue: _i4.Future<_i2.WKWebpagePreferences>.value( - _FakeWKWebpagePreferences_12( + _FakeWKWebpagePreferences_11( this, Invocation.method(#getDefaultWebpagePreferences, []), ), @@ -978,7 +965,7 @@ class MockWKWebViewConfiguration extends _i1.Mock @override _i2.WKWebViewConfiguration pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeWKWebViewConfiguration_8( + returnValue: _FakeWKWebViewConfiguration_7( this, Invocation.method(#pigeon_copy, []), ), @@ -1017,7 +1004,7 @@ class MockWKWebsiteDataStore extends _i1.Mock @override _i2.WKHTTPCookieStore get httpCookieStore => (super.noSuchMethod( Invocation.getter(#httpCookieStore), - returnValue: _FakeWKHTTPCookieStore_13( + returnValue: _FakeWKHTTPCookieStore_12( this, Invocation.getter(#httpCookieStore), ), @@ -1035,7 +1022,7 @@ class MockWKWebsiteDataStore extends _i1.Mock @override _i2.WKHTTPCookieStore pigeonVar_httpCookieStore() => (super.noSuchMethod( Invocation.method(#pigeonVar_httpCookieStore, []), - returnValue: _FakeWKHTTPCookieStore_13( + returnValue: _FakeWKHTTPCookieStore_12( this, Invocation.method(#pigeonVar_httpCookieStore, []), ), @@ -1057,7 +1044,7 @@ class MockWKWebsiteDataStore extends _i1.Mock @override _i2.WKWebsiteDataStore pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeWKWebsiteDataStore_11( + returnValue: _FakeWKWebsiteDataStore_10( this, Invocation.method(#pigeon_copy, []), ), @@ -1153,7 +1140,7 @@ class MockWKUIDelegate extends _i1.Mock implements _i2.WKUIDelegate { @override _i2.WKUIDelegate pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeWKUIDelegate_14( + returnValue: _FakeWKUIDelegate_13( this, Invocation.method(#pigeon_copy, []), ), @@ -1242,7 +1229,7 @@ class MockWKUserContentController extends _i1.Mock @override _i2.WKUserContentController pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeWKUserContentController_10( + returnValue: _FakeWKUserContentController_9( this, Invocation.method(#pigeon_copy, []), ), @@ -1367,7 +1354,7 @@ class MockWebViewWidgetProxy extends _i1.Mock [configuration], {#observeValue: observeValue}, ), - returnValue: _FakePlatformWebView_15( + returnValue: _FakePlatformWebView_14( this, Invocation.method( #createWebView, @@ -1398,7 +1385,7 @@ class MockWebViewWidgetProxy extends _i1.Mock Invocation.method(#createScriptMessageHandler, [], { #didReceiveScriptMessage: didReceiveScriptMessage, }), - returnValue: _FakeWKScriptMessageHandler_6( + returnValue: _FakeWKScriptMessageHandler_5( this, Invocation.method(#createScriptMessageHandler, [], { #didReceiveScriptMessage: didReceiveScriptMessage, @@ -1419,7 +1406,7 @@ class MockWebViewWidgetProxy extends _i1.Mock Invocation.method(#createUIDelgate, [], { #onCreateWebView: onCreateWebView, }), - returnValue: _FakeWKUIDelegate_14( + returnValue: _FakeWKUIDelegate_13( this, Invocation.method(#createUIDelgate, [], { #onCreateWebView: onCreateWebView, @@ -1449,7 +1436,7 @@ class MockWebViewWidgetProxy extends _i1.Mock _i2.WKWebView, _i2.WKNavigationResponse, )? decidePolicyForNavigationResponse, - required _i4.Future<_i2.AuthenticationChallengeResponse> Function( + required _i4.Future> Function( _i2.WKNavigationDelegate, _i2.WKWebView, _i2.URLAuthenticationChallenge, @@ -1467,7 +1454,7 @@ class MockWebViewWidgetProxy extends _i1.Mock #decidePolicyForNavigationResponse: decidePolicyForNavigationResponse, #didReceiveAuthenticationChallenge: didReceiveAuthenticationChallenge, }), - returnValue: _FakeWKNavigationDelegate_4( + returnValue: _FakeWKNavigationDelegate_3( this, Invocation.method(#createNavigationDelegate, [], { #didFinishNavigation: didFinishNavigation, @@ -1515,7 +1502,7 @@ class MockWKWebpagePreferences extends _i1.Mock @override _i2.WKWebpagePreferences pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeWKWebpagePreferences_12( + returnValue: _FakeWKWebpagePreferences_11( this, Invocation.method(#pigeon_copy, []), ), diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart index f19e2d23f2f1..ff90d12960a0 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart @@ -54,11 +54,10 @@ void main() { return NavigationResponsePolicy.cancel; }, didReceiveAuthenticationChallenge: (_, __, ___) async { - return AuthenticationChallengeResponse.pigeon_detached( - disposition: - UrlSessionAuthChallengeDisposition.performDefaultHandling, - pigeon_instanceManager: TestInstanceManager(), - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ), WKWebView.pigeon_detached( @@ -93,11 +92,10 @@ void main() { return NavigationResponsePolicy.cancel; }, didReceiveAuthenticationChallenge: (_, __, ___) async { - return AuthenticationChallengeResponse.pigeon_detached( - disposition: - UrlSessionAuthChallengeDisposition.performDefaultHandling, - pigeon_instanceManager: TestInstanceManager(), - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ), WKWebView.pigeon_detached( @@ -136,11 +134,10 @@ void main() { return NavigationResponsePolicy.cancel; }, didReceiveAuthenticationChallenge: (_, __, ___) async { - return AuthenticationChallengeResponse.pigeon_detached( - disposition: - UrlSessionAuthChallengeDisposition.performDefaultHandling, - pigeon_instanceManager: TestInstanceManager(), - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ), WKWebView.pigeon_detached( @@ -186,11 +183,10 @@ void main() { return NavigationResponsePolicy.cancel; }, didReceiveAuthenticationChallenge: (_, __, ___) async { - return AuthenticationChallengeResponse.pigeon_detached( - disposition: - UrlSessionAuthChallengeDisposition.performDefaultHandling, - pigeon_instanceManager: TestInstanceManager(), - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ), WKWebView.pigeon_detached( @@ -235,11 +231,10 @@ void main() { return NavigationResponsePolicy.cancel; }, didReceiveAuthenticationChallenge: (_, __, ___) async { - return AuthenticationChallengeResponse.pigeon_detached( - disposition: - UrlSessionAuthChallengeDisposition.performDefaultHandling, - pigeon_instanceManager: TestInstanceManager(), - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ), WKWebView.pigeon_detached( @@ -291,11 +286,10 @@ void main() { return NavigationResponsePolicy.cancel; }, didReceiveAuthenticationChallenge: (_, __, ___) async { - return AuthenticationChallengeResponse.pigeon_detached( - disposition: - UrlSessionAuthChallengeDisposition.performDefaultHandling, - pigeon_instanceManager: TestInstanceManager(), - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ), WKWebView.pigeon_detached( @@ -348,11 +342,10 @@ void main() { return NavigationResponsePolicy.cancel; }, didReceiveAuthenticationChallenge: (_, __, ___) async { - return AuthenticationChallengeResponse.pigeon_detached( - disposition: - UrlSessionAuthChallengeDisposition.performDefaultHandling, - pigeon_instanceManager: TestInstanceManager(), - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ), WKWebView.pigeon_detached( @@ -406,11 +399,10 @@ void main() { return NavigationResponsePolicy.cancel; }, didReceiveAuthenticationChallenge: (_, __, ___) async { - return AuthenticationChallengeResponse.pigeon_detached( - disposition: - UrlSessionAuthChallengeDisposition.performDefaultHandling, - pigeon_instanceManager: TestInstanceManager(), - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ), WKWebView.pigeon_detached( @@ -496,11 +488,10 @@ void main() { return NavigationResponsePolicy.cancel; }, didReceiveAuthenticationChallenge: (_, __, ___) async { - return AuthenticationChallengeResponse.pigeon_detached( - disposition: - UrlSessionAuthChallengeDisposition.performDefaultHandling, - pigeon_instanceManager: TestInstanceManager(), - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ), WKWebView.pigeon_detached( @@ -574,11 +565,10 @@ void main() { return NavigationResponsePolicy.cancel; }, didReceiveAuthenticationChallenge: (_, __, ___) async { - return AuthenticationChallengeResponse.pigeon_detached( - disposition: - UrlSessionAuthChallengeDisposition.performDefaultHandling, - pigeon_instanceManager: TestInstanceManager(), - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ), WKWebView.pigeon_detached( @@ -616,10 +606,10 @@ class CapturingNavigationDelegate extends WKNavigationDelegate { return NavigationResponsePolicy.cancel; }, didReceiveAuthenticationChallenge: (_, __, ___) async { - return AuthenticationChallengeResponse.pigeon_detached( - disposition: UrlSessionAuthChallengeDisposition.performDefaultHandling, - pigeon_instanceManager: TestInstanceManager(), - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ); } 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 798fe7bd4448..e6a350de4e63 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 @@ -1888,10 +1888,10 @@ class CapturingNavigationDelegate extends WKNavigationDelegate { return NavigationResponsePolicy.cancel; }, didReceiveAuthenticationChallenge: (_, __, ___) async { - return AuthenticationChallengeResponse.pigeon_detached( - disposition: UrlSessionAuthChallengeDisposition.performDefaultHandling, - pigeon_instanceManager: TestInstanceManager(), - ); + return [ + UrlSessionAuthChallengeDisposition.performDefaultHandling, + null, + ]; }, ); } From 49d41a4c43d1287d0d58b110295d9608f6e916c2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 25 Feb 2025 14:36:02 -0500 Subject: [PATCH 2/8] improve auth test --- .../lib/src/webkit_webview_controller.dart | 3 ++- .../test/webkit_navigation_delegate_test.dart | 27 +++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) 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 466524e8ef59..b6f13fe702f6 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 @@ -1221,7 +1221,8 @@ class WebKitNavigationDelegate extends PlatformNavigationDelegate { host: host, realm: realm, onProceed: (WebViewCredential credential) { - final URLCredential userCredential = URLCredential.withUser( + final URLCredential userCredential = + proxy.withUserURLCredential( user: credential.user, password: credential.password, persistence: UrlCredentialPersistence.forSession, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart index ff90d12960a0..b5610342f485 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart @@ -505,6 +505,8 @@ void main() { }); test('onHttpNtlmAuthRequest emits host and realm', () async { + late final String credentialUser; + late final String credentialPassword; final WebKitNavigationDelegate iosNavigationDelegate = WebKitNavigationDelegate( WebKitNavigationDelegateCreationParams( @@ -520,6 +522,17 @@ void main() { pigeon_instanceManager: TestInstanceManager(), ); }, + withUserURLCredential: ({ + required String user, + required String password, + required UrlCredentialPersistence persistence, + }) { + credentialUser = user; + credentialPassword = password; + return URLCredential.pigeon_detached( + pigeon_instanceManager: TestInstanceManager(), + ); + }, ), ), ); @@ -527,11 +540,15 @@ void main() { String? callbackHost; String? callbackRealm; + const String user = 'user'; + const String password = 'password'; await iosNavigationDelegate.setOnHttpAuthRequest( (HttpAuthRequest request) { callbackHost = request.host; callbackRealm = request.realm; - request.onCancel(); + request.onProceed( + const WebViewCredential(user: user, password: password), + ); }, ); @@ -554,7 +571,8 @@ void main() { }, ); - await CapturingNavigationDelegate.lastCreatedDelegate + final List result = await CapturingNavigationDelegate + .lastCreatedDelegate .didReceiveAuthenticationChallenge( WKNavigationDelegate.pigeon_detached( pigeon_instanceManager: TestInstanceManager(), @@ -577,6 +595,11 @@ void main() { mockChallenge, ); + expect(result[0], UrlSessionAuthChallengeDisposition.useCredential); + expect(result[1], isA()); + expect(credentialUser, user); + expect(credentialPassword, password); + expect(callbackHost, expectedHost); expect(callbackRealm, expectedRealm); }); From eda13c61a2b1198a0355c428e1b2ec5a5c2d4cc8 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 25 Feb 2025 14:50:35 -0500 Subject: [PATCH 3/8] try fix conversion --- .../NavigationDelegateProxyAPIDelegate.swift | 38 +++++++++++++++++-- .../ios/Runner.xcodeproj/project.pbxproj | 2 +- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift index 0a960e51380a..66c6a2edd640 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift @@ -244,8 +244,23 @@ public class NavigationDelegateImpl: NSObject, WKNavigationDelegate { DispatchQueue.main.async { switch result { case .success(let response): - completionHandler( - response[0] as! URLSession.AuthChallengeDisposition, response[1] as? URLCredential) + let disposition = response[0] as! UrlSessionAuthChallengeDisposition + var nativeDisposition: URLSession.AuthChallengeDisposition + switch disposition { + case .useCredential: + nativeDisposition = .useCredential + case .performDefaultHandling: + nativeDisposition = .performDefaultHandling + case .cancelAuthenticationChallenge: + nativeDisposition = .cancelAuthenticationChallenge + case .rejectProtectionSpace: + nativeDisposition = .rejectProtectionSpace + case .unknown: + print( + self.registrar.createUnknownEnumError(withEnum: disposition).localizedDescription) + nativeDisposition = .cancelAuthenticationChallenge + } + completionHandler(nativeDisposition, response[1] as? URLCredential) case .failure(let error): completionHandler(.cancelAuthenticationChallenge, nil) onFailure("WKNavigationDelegate.didReceiveAuthenticationChallenge", error) @@ -267,8 +282,23 @@ public class NavigationDelegateImpl: NSObject, WKNavigationDelegate { DispatchQueue.main.async { switch result { case .success(let response): - completionHandler( - response[0] as! URLSession.AuthChallengeDisposition, response[1] as? URLCredential) + let disposition = response[0] as! UrlSessionAuthChallengeDisposition + var nativeDisposition: URLSession.AuthChallengeDisposition + switch disposition { + case .useCredential: + nativeDisposition = .useCredential + case .performDefaultHandling: + nativeDisposition = .performDefaultHandling + case .cancelAuthenticationChallenge: + nativeDisposition = .cancelAuthenticationChallenge + case .rejectProtectionSpace: + nativeDisposition = .rejectProtectionSpace + case .unknown: + print( + self.registrar.createUnknownEnumError(withEnum: disposition).localizedDescription) + nativeDisposition = .cancelAuthenticationChallenge + } + completionHandler(nativeDisposition, response[1] as? URLCredential) case .failure(let error): completionHandler(.cancelAuthenticationChallenge, nil) onFailure("WKNavigationDelegate.didReceiveAuthenticationChallenge", error) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj index 8d55bed26057..22def7bcd074 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 60; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ From d8e28173d60525607812e35b2473dca6c15cdb56 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 25 Feb 2025 14:54:47 -0500 Subject: [PATCH 4/8] fix native unit test --- .../darwin/Tests/NavigationDelegateProxyAPITests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift index 2667cb7f0902..b8c663accb84 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift @@ -227,7 +227,7 @@ class TestNavigationDelegateApi: PigeonApiProtocolWKNavigationDelegate { didReceiveAuthenticationChallengeArgs = [webViewArg, challengeArg] completion( .success([ - URLSession.AuthChallengeDisposition.useCredential, + UrlSessionAuthChallengeDisposition.useCredential, URLCredential(user: "user", password: "password", persistence: .none), ])) } From 88f30eb8d4441a09cde78eaf19d00e484956d6c1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 25 Feb 2025 15:59:49 -0500 Subject: [PATCH 5/8] add comment --- .../example/ios/Runner.xcodeproj/project.pbxproj | 2 +- .../webview_flutter_wkwebview/pigeons/web_kit.dart | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj index 22def7bcd074..8d55bed26057 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 60; objects = { /* Begin PBXBuildFile section */ 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 69267fa53720..2ac2cff3b7fc 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart @@ -745,6 +745,9 @@ abstract class WKNavigationDelegate extends NSObject { /// Tells the delegate that the web view’s content process was terminated. void Function(WKWebView webView)? webViewWebContentProcessDidTerminate; + // TODO(bparrishMines): This method should return an + // `AuthenticationChallengeResponse` once the cause of + // https://github.com/flutter/flutter/issues/162437 can be found and fixed. /// Asks the delegate to respond to an authentication challenge. /// /// This return value expects a List with a From 01063e647cbe6be56719cfa340e7414edd805433 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 26 Feb 2025 18:38:02 -0500 Subject: [PATCH 6/8] flatten credential --- .../NavigationDelegateProxyAPITests.swift | 6 +++-- .../NavigationDelegateProxyAPIDelegate.swift | 20 ++++++++++++++++- .../lib/src/webkit_webview_controller.dart | 12 +++++----- .../test/webkit_navigation_delegate_test.dart | 22 +++++-------------- 4 files changed, 34 insertions(+), 26 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift index b8c663accb84..822e38025ff6 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift @@ -131,7 +131,9 @@ class NavigationDelegateProxyAPITests: XCTestCase { XCTAssertEqual(api.didReceiveAuthenticationChallengeArgs, [webView, challenge]) XCTAssertEqual(dispositionResult, .useCredential) - XCTAssertNotNil(credentialResult) + XCTAssertEqual(credentialResult?.user, "user1") + XCTAssertEqual(credentialResult?.password, "password1") + XCTAssertEqual(credentialResult?.persistence, URLCredential.Persistence.none) } } @@ -228,7 +230,7 @@ class TestNavigationDelegateApi: PigeonApiProtocolWKNavigationDelegate { completion( .success([ UrlSessionAuthChallengeDisposition.useCredential, - URLCredential(user: "user", password: "password", persistence: .none), + ["user": "user1", "password": "password1", "persistence": UrlCredentialPersistence.none], ])) } } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift index 66c6a2edd640..c39cb07eb37f 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift @@ -260,7 +260,25 @@ public class NavigationDelegateImpl: NSObject, WKNavigationDelegate { self.registrar.createUnknownEnumError(withEnum: disposition).localizedDescription) nativeDisposition = .cancelAuthenticationChallenge } - completionHandler(nativeDisposition, response[1] as? URLCredential) + let credentialMap = response[1] as? [AnyHashable?: AnyHashable?] + var credential: URLCredential? + if let credentialMap = credentialMap { + let nativePersistence: URLCredential.Persistence + switch credentialMap["persistence"] as! UrlCredentialPersistence { + case .none: + nativePersistence = .none + case .forSession: + nativePersistence = .forSession + case .permanent: + nativePersistence = .permanent + case .synchronizable: + nativePersistence = .synchronizable + } + credential = URLCredential( + user: credentialMap["user"] as! String, + password: credentialMap["password"] as! String, persistence: nativePersistence) + } + completionHandler(nativeDisposition, credential) case .failure(let error): completionHandler(.cancelAuthenticationChallenge, nil) onFailure("WKNavigationDelegate.didReceiveAuthenticationChallenge", error) 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 b6f13fe702f6..4bf9d87aedf7 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 @@ -1221,16 +1221,14 @@ class WebKitNavigationDelegate extends PlatformNavigationDelegate { host: host, realm: realm, onProceed: (WebViewCredential credential) { - final URLCredential userCredential = - proxy.withUserURLCredential( - user: credential.user, - password: credential.password, - persistence: UrlCredentialPersistence.forSession, - ); responseCompleter.complete( [ UrlSessionAuthChallengeDisposition.useCredential, - userCredential, + { + 'user': credential.user, + 'password': credential.password, + 'persistence': UrlCredentialPersistence.forSession, + }, ], ); }, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart index b5610342f485..d7f7b5898799 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart @@ -505,8 +505,6 @@ void main() { }); test('onHttpNtlmAuthRequest emits host and realm', () async { - late final String credentialUser; - late final String credentialPassword; final WebKitNavigationDelegate iosNavigationDelegate = WebKitNavigationDelegate( WebKitNavigationDelegateCreationParams( @@ -522,17 +520,6 @@ void main() { pigeon_instanceManager: TestInstanceManager(), ); }, - withUserURLCredential: ({ - required String user, - required String password, - required UrlCredentialPersistence persistence, - }) { - credentialUser = user; - credentialPassword = password; - return URLCredential.pigeon_detached( - pigeon_instanceManager: TestInstanceManager(), - ); - }, ), ), ); @@ -596,9 +583,12 @@ void main() { ); expect(result[0], UrlSessionAuthChallengeDisposition.useCredential); - expect(result[1], isA()); - expect(credentialUser, user); - expect(credentialPassword, password); + expect(result[1], containsPair('user', user)); + expect(result[1], containsPair('password', password)); + expect( + result[1], + containsPair('persistence', UrlCredentialPersistence.forSession), + ); expect(callbackHost, expectedHost); expect(callbackRealm, expectedRealm); From 684d68e6f8819eb41a1d16fbaf831e94af8022a2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 26 Feb 2025 18:56:52 -0500 Subject: [PATCH 7/8] swift 5 version --- .../NavigationDelegateProxyAPIDelegate.swift | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift index c39cb07eb37f..1b3a0da0509e 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift @@ -316,7 +316,25 @@ public class NavigationDelegateImpl: NSObject, WKNavigationDelegate { self.registrar.createUnknownEnumError(withEnum: disposition).localizedDescription) nativeDisposition = .cancelAuthenticationChallenge } - completionHandler(nativeDisposition, response[1] as? URLCredential) + let credentialMap = response[1] as? [AnyHashable?: AnyHashable?] + var credential: URLCredential? + if let credentialMap = credentialMap { + let nativePersistence: URLCredential.Persistence + switch credentialMap["persistence"] as! UrlCredentialPersistence { + case .none: + nativePersistence = .none + case .forSession: + nativePersistence = .forSession + case .permanent: + nativePersistence = .permanent + case .synchronizable: + nativePersistence = .synchronizable + } + credential = URLCredential( + user: credentialMap["user"] as! String, + password: credentialMap["password"] as! String, persistence: nativePersistence) + } + completionHandler(nativeDisposition, credential) case .failure(let error): completionHandler(.cancelAuthenticationChallenge, nil) onFailure("WKNavigationDelegate.didReceiveAuthenticationChallenge", error) From 277aba83368f7934671327531bd8c7dcdaaa1db0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 27 Feb 2025 14:24:21 -0500 Subject: [PATCH 8/8] comments --- .../NavigationDelegateProxyAPIDelegate.swift | 114 +++++++----------- .../pigeons/web_kit.dart | 11 +- 2 files changed, 53 insertions(+), 72 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift index 1b3a0da0509e..8735fddf4c60 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift @@ -230,6 +230,46 @@ public class NavigationDelegateImpl: NSObject, WKNavigationDelegate { } #endif + func handleAuthChallengeSuccessResponse(_ response: [Any?]) -> ( + URLSession.AuthChallengeDisposition, URLCredential? + ) { + let disposition = response[0] as! UrlSessionAuthChallengeDisposition + var nativeDisposition: URLSession.AuthChallengeDisposition + switch disposition { + case .useCredential: + nativeDisposition = .useCredential + case .performDefaultHandling: + nativeDisposition = .performDefaultHandling + case .cancelAuthenticationChallenge: + nativeDisposition = .cancelAuthenticationChallenge + case .rejectProtectionSpace: + nativeDisposition = .rejectProtectionSpace + case .unknown: + print( + self.registrar.createUnknownEnumError(withEnum: disposition).localizedDescription) + nativeDisposition = .cancelAuthenticationChallenge + } + let credentialMap = response[1] as? [AnyHashable?: AnyHashable?] + var credential: URLCredential? + if let credentialMap = credentialMap { + let nativePersistence: URLCredential.Persistence + switch credentialMap["persistence"] as! UrlCredentialPersistence { + case .none: + nativePersistence = .none + case .forSession: + nativePersistence = .forSession + case .permanent: + nativePersistence = .permanent + case .synchronizable: + nativePersistence = .synchronizable + } + credential = URLCredential( + user: credentialMap["user"] as! String, + password: credentialMap["password"] as! String, persistence: nativePersistence) + } + return (nativeDisposition, credential) + } + #if compiler(>=6.0) public func webView( _ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, @@ -244,41 +284,8 @@ public class NavigationDelegateImpl: NSObject, WKNavigationDelegate { DispatchQueue.main.async { switch result { case .success(let response): - let disposition = response[0] as! UrlSessionAuthChallengeDisposition - var nativeDisposition: URLSession.AuthChallengeDisposition - switch disposition { - case .useCredential: - nativeDisposition = .useCredential - case .performDefaultHandling: - nativeDisposition = .performDefaultHandling - case .cancelAuthenticationChallenge: - nativeDisposition = .cancelAuthenticationChallenge - case .rejectProtectionSpace: - nativeDisposition = .rejectProtectionSpace - case .unknown: - print( - self.registrar.createUnknownEnumError(withEnum: disposition).localizedDescription) - nativeDisposition = .cancelAuthenticationChallenge - } - let credentialMap = response[1] as? [AnyHashable?: AnyHashable?] - var credential: URLCredential? - if let credentialMap = credentialMap { - let nativePersistence: URLCredential.Persistence - switch credentialMap["persistence"] as! UrlCredentialPersistence { - case .none: - nativePersistence = .none - case .forSession: - nativePersistence = .forSession - case .permanent: - nativePersistence = .permanent - case .synchronizable: - nativePersistence = .synchronizable - } - credential = URLCredential( - user: credentialMap["user"] as! String, - password: credentialMap["password"] as! String, persistence: nativePersistence) - } - completionHandler(nativeDisposition, credential) + let nativeValues = self.handleAuthChallengeSuccessResponse(response) + completionHandler(nativeValues.0, nativeValues.1) case .failure(let error): completionHandler(.cancelAuthenticationChallenge, nil) onFailure("WKNavigationDelegate.didReceiveAuthenticationChallenge", error) @@ -300,41 +307,8 @@ public class NavigationDelegateImpl: NSObject, WKNavigationDelegate { DispatchQueue.main.async { switch result { case .success(let response): - let disposition = response[0] as! UrlSessionAuthChallengeDisposition - var nativeDisposition: URLSession.AuthChallengeDisposition - switch disposition { - case .useCredential: - nativeDisposition = .useCredential - case .performDefaultHandling: - nativeDisposition = .performDefaultHandling - case .cancelAuthenticationChallenge: - nativeDisposition = .cancelAuthenticationChallenge - case .rejectProtectionSpace: - nativeDisposition = .rejectProtectionSpace - case .unknown: - print( - self.registrar.createUnknownEnumError(withEnum: disposition).localizedDescription) - nativeDisposition = .cancelAuthenticationChallenge - } - let credentialMap = response[1] as? [AnyHashable?: AnyHashable?] - var credential: URLCredential? - if let credentialMap = credentialMap { - let nativePersistence: URLCredential.Persistence - switch credentialMap["persistence"] as! UrlCredentialPersistence { - case .none: - nativePersistence = .none - case .forSession: - nativePersistence = .forSession - case .permanent: - nativePersistence = .permanent - case .synchronizable: - nativePersistence = .synchronizable - } - credential = URLCredential( - user: credentialMap["user"] as! String, - password: credentialMap["password"] as! String, persistence: nativePersistence) - } - completionHandler(nativeDisposition, credential) + let nativeValues = self.handleAuthChallengeSuccessResponse(response) + completionHandler(nativeValues.0, nativeValues.1) case .failure(let error): completionHandler(.cancelAuthenticationChallenge, nil) onFailure("WKNavigationDelegate.didReceiveAuthenticationChallenge", error) 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 2ac2cff3b7fc..c1dc26823a33 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart @@ -750,8 +750,15 @@ abstract class WKNavigationDelegate extends NSObject { // https://github.com/flutter/flutter/issues/162437 can be found and fixed. /// Asks the delegate to respond to an authentication challenge. /// - /// This return value expects a List with a - /// `UrlSessionAuthChallengeDisposition` and a nullable `URLCredential`. + /// This return value expects a List with: + /// + /// 1. `UrlSessionAuthChallengeDisposition` + /// 2. A nullable map to instantiate a `URLCredential`. The map structure is + /// [ + /// "user": "", + /// "password": "", + /// "persistence": , + /// ] @async late List Function( WKWebView webView,