diff --git a/packages/webview_flutter/webview_flutter/example/lib/main.dart b/packages/webview_flutter/webview_flutter/example/lib/main.dart index 9ff1ffc5981f..da69b4367ed8 100644 --- a/packages/webview_flutter/webview_flutter/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter/example/lib/main.dart @@ -428,9 +428,17 @@ class SampleMenu extends StatelessWidget { } Future _onListCookies(BuildContext context) async { - final cookies = - await webViewController.runJavaScriptReturningResult('document.cookie') - as String; + final Uri? domain = Uri.tryParse( + (await webViewController.currentUrl()) ?? '', + ); + + late final List cookies; + if (domain == null) { + cookies = []; + } else { + cookies = await cookieManager.getCookies(domain: domain); + } + if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( @@ -536,13 +544,12 @@ class SampleMenu extends StatelessWidget { return webViewController.loadHtmlString(kTransparentBackgroundPage); } - Widget _getCookieList(String cookies) { - if (cookies == '""') { + Widget _getCookieList(List cookies) { + if (cookies.isEmpty) { return Container(); } - final List cookieList = cookies.split(';'); - final Iterable cookieWidgets = cookieList.map( - (String cookie) => Text(cookie), + final Iterable cookieWidgets = cookies.map( + (WebViewCookie cookie) => Text(cookie.toString()), ); return Column( mainAxisAlignment: MainAxisAlignment.end, diff --git a/packages/webview_flutter/webview_flutter/example/pubspec.yaml b/packages/webview_flutter/webview_flutter/example/pubspec.yaml index 26902fbf4ef0..827538cc7105 100644 --- a/packages/webview_flutter/webview_flutter/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter/example/pubspec.yaml @@ -36,3 +36,9 @@ flutter: - assets/sample_video.mp4 - assets/www/index.html - assets/www/styles/style.css +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + webview_flutter_android: {path: ../../../../packages/webview_flutter/webview_flutter_android} + webview_flutter_platform_interface: {path: ../../../../packages/webview_flutter/webview_flutter_platform_interface} + webview_flutter_wkwebview: {path: ../../../../packages/webview_flutter/webview_flutter_wkwebview} diff --git a/packages/webview_flutter/webview_flutter/lib/src/webview_cookie_manager.dart b/packages/webview_flutter/webview_flutter/lib/src/webview_cookie_manager.dart index 3d9c5dec9904..a939b60011d3 100644 --- a/packages/webview_flutter/webview_flutter/lib/src/webview_cookie_manager.dart +++ b/packages/webview_flutter/webview_flutter/lib/src/webview_cookie_manager.dart @@ -86,4 +86,12 @@ class WebViewCookieManager { /// /// This is a no op on iOS versions below 11. Future setCookie(WebViewCookie cookie) => platform.setCookie(cookie); + + /// Gets a list of existing cookie for specified domain from all + /// WebView instances of the application. + /// + /// Each platform can have different url requirements. Please check individual + /// platform implementation for details + Future> getCookies({required Uri domain}) => + platform.getCookies(domain); } diff --git a/packages/webview_flutter/webview_flutter/pubspec.yaml b/packages/webview_flutter/webview_flutter/pubspec.yaml index 8c27843fb500..4fdabb714d6a 100644 --- a/packages/webview_flutter/webview_flutter/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter/pubspec.yaml @@ -36,3 +36,9 @@ topics: - html - webview - webview-flutter +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + webview_flutter_android: {path: ../../../packages/webview_flutter/webview_flutter_android} + webview_flutter_platform_interface: {path: ../../../packages/webview_flutter/webview_flutter_platform_interface} + webview_flutter_wkwebview: {path: ../../../packages/webview_flutter/webview_flutter_wkwebview} diff --git a/packages/webview_flutter/webview_flutter/test/legacy/webview_flutter_test.mocks.dart b/packages/webview_flutter/webview_flutter/test/legacy/webview_flutter_test.mocks.dart index 7954c2f769aa..b6d2e7616769 100644 --- a/packages/webview_flutter/webview_flutter/test/legacy/webview_flutter_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter/test/legacy/webview_flutter_test.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.5 from annotations +// Mocks generated by Mockito 5.4.6 from annotations // in webview_flutter/test/legacy/webview_flutter_test.dart. // Do not manually edit this file. @@ -34,6 +34,7 @@ import 'package:webview_flutter_platform_interface/src/legacy/types/types.dart' // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member class _FakeWidget_0 extends _i1.SmartFake implements _i2.Widget { _FakeWidget_0(Object parent, Invocation parentInvocation) diff --git a/packages/webview_flutter/webview_flutter/test/navigation_delegate_test.mocks.dart b/packages/webview_flutter/webview_flutter/test/navigation_delegate_test.mocks.dart index df0089f7968a..851329857ba7 100644 --- a/packages/webview_flutter/webview_flutter/test/navigation_delegate_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter/test/navigation_delegate_test.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.5 from annotations +// Mocks generated by Mockito 5.4.6 from annotations // in webview_flutter/test/navigation_delegate_test.dart. // Do not manually edit this file. @@ -34,6 +34,7 @@ import 'package:webview_flutter_platform_interface/src/webview_platform.dart' // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member class _FakePlatformWebViewCookieManager_0 extends _i1.SmartFake implements _i2.PlatformWebViewCookieManager { diff --git a/packages/webview_flutter/webview_flutter/test/webview_controller_test.mocks.dart b/packages/webview_flutter/webview_flutter/test/webview_controller_test.mocks.dart index 7baf88057099..7356ed35db01 100644 --- a/packages/webview_flutter/webview_flutter/test/webview_controller_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter/test/webview_controller_test.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.5 from annotations +// Mocks generated by Mockito 5.4.6 from annotations // in webview_flutter/test/webview_controller_test.dart. // Do not manually edit this file. @@ -26,6 +26,7 @@ import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i2; // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member class _FakePlatformWebViewControllerCreationParams_0 extends _i1.SmartFake implements _i2.PlatformWebViewControllerCreationParams { @@ -82,6 +83,15 @@ class MockPlatformWebViewController extends _i1.Mock ) as _i5.Future); + @override + _i5.Future loadFileWithParams(_i2.LoadFileParams? params) => + (super.noSuchMethod( + Invocation.method(#loadFileWithParams, [params]), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) + as _i5.Future); + @override _i5.Future loadFlutterAsset(String? key) => (super.noSuchMethod( diff --git a/packages/webview_flutter/webview_flutter/test/webview_cookie_manager_test.dart b/packages/webview_flutter/webview_flutter/test/webview_cookie_manager_test.dart index 2eff52171aba..ac0c4492a11a 100644 --- a/packages/webview_flutter/webview_flutter/test/webview_cookie_manager_test.dart +++ b/packages/webview_flutter/webview_flutter/test/webview_cookie_manager_test.dart @@ -50,5 +50,43 @@ void main() { as WebViewCookie; expect(capturedCookie, cookie); }); + + test('getCookies', () async { + final mockPlatformWebViewCookieManager = + MockPlatformWebViewCookieManager(); + final cookieManager = WebViewCookieManager.fromPlatform( + mockPlatformWebViewCookieManager, + ); + + when( + mockPlatformWebViewCookieManager.getCookies(Uri(host: 'flutter.dev')), + ).thenAnswer((_) async => []); + + final List cookies = await cookieManager.getCookies( + domain: Uri(host: 'flutter.dev'), + ); + + expect(cookies, isEmpty); + + verify( + mockPlatformWebViewCookieManager.getCookies(Uri(host: 'flutter.dev')), + ).called(1); + + const cookie = WebViewCookie( + name: 'name', + value: 'value', + domain: 'domain', + ); + + when( + mockPlatformWebViewCookieManager.getCookies(Uri(host: 'domain')), + ).thenAnswer((_) => Future.value([cookie])); + + await cookieManager.getCookies(domain: Uri(host: 'domain')); + + verify( + mockPlatformWebViewCookieManager.getCookies(Uri(host: 'domain')), + ).called(1); + }); }); } diff --git a/packages/webview_flutter/webview_flutter/test/webview_cookie_manager_test.mocks.dart b/packages/webview_flutter/webview_flutter/test/webview_cookie_manager_test.mocks.dart index c40d739926a7..e9b5f74c14ce 100644 --- a/packages/webview_flutter/webview_flutter/test/webview_cookie_manager_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter/test/webview_cookie_manager_test.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.5 from annotations +// Mocks generated by Mockito 5.4.6 from annotations // in webview_flutter/test/webview_cookie_manager_test.dart. // Do not manually edit this file. @@ -23,6 +23,7 @@ import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i2; // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member class _FakePlatformWebViewCookieManagerCreationParams_0 extends _i1.SmartFake implements _i2.PlatformWebViewCookieManagerCreationParams { @@ -68,4 +69,14 @@ class MockPlatformWebViewCookieManager extends _i1.Mock returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + + @override + _i4.Future> getCookies(Uri? domain) => + (super.noSuchMethod( + Invocation.method(#getCookies, [domain]), + returnValue: _i4.Future>.value( + <_i2.WebViewCookie>[], + ), + ) + as _i4.Future>); } diff --git a/packages/webview_flutter/webview_flutter/test/webview_widget_test.mocks.dart b/packages/webview_flutter/webview_flutter/test/webview_widget_test.mocks.dart index 838dc93cf7cc..ca6b86014b40 100644 --- a/packages/webview_flutter/webview_flutter/test/webview_widget_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter/test/webview_widget_test.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.5 from annotations +// Mocks generated by Mockito 5.4.6 from annotations // in webview_flutter/test/webview_widget_test.dart. // Do not manually edit this file. @@ -30,6 +30,7 @@ import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i2; // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member class _FakePlatformWebViewControllerCreationParams_0 extends _i1.SmartFake implements _i2.PlatformWebViewControllerCreationParams { @@ -95,6 +96,15 @@ class MockPlatformWebViewController extends _i1.Mock ) as _i7.Future); + @override + _i7.Future loadFileWithParams(_i2.LoadFileParams? params) => + (super.noSuchMethod( + Invocation.method(#loadFileWithParams, [params]), + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) + as _i7.Future); + @override _i7.Future loadFlutterAsset(String? key) => (super.noSuchMethod( diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/AndroidWebkitLibrary.g.kt b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/AndroidWebkitLibrary.g.kt index 71d26653c2e6..812df3899466 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/AndroidWebkitLibrary.g.kt +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/AndroidWebkitLibrary.g.kt @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.4), do not edit directly. +// Autogenerated from Pigeon (v26.1.5), do not edit directly. // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") @@ -155,10 +155,6 @@ class AndroidWebkitLibraryPigeonInstanceManager( */ fun remove(identifier: Long): T? { logWarningIfFinalizationListenerHasStopped() - val instance: Any? = getInstance(identifier) - if (instance is WebViewProxyApi.WebViewPlatformView) { - instance.destroy() - } return strongInstances.remove(identifier) as T? } @@ -1519,6 +1515,18 @@ abstract class PigeonApiCookieManager( accept: Boolean ) + /** + * Gets all the cookies for the given URL. + * + * This may return multiple key-value pairs if multiple cookies are associated with this URL, in + * which case each cookie will be delimited by "; " characters (semicolon followed by a space). + * Each key-value pair will be of the form "key=value". + * + * Note: Any cookies set with the "Partitioned" attribute will only be returned for the top-level + * partition of url. + */ + abstract fun getCookies(pigeon_instance: android.webkit.CookieManager, url: String): String? + companion object { @Suppress("LocalVariableName") fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiCookieManager?) { @@ -1621,6 +1629,29 @@ abstract class PigeonApiCookieManager( channel.setMessageHandler(null) } } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_android.CookieManager.getCookies", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as android.webkit.CookieManager + val urlArg = args[1] as String + val wrapped: List = + try { + listOf(api.getCookies(pigeon_instanceArg, urlArg)) + } catch (exception: Throwable) { + AndroidWebkitLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/CookieManagerProxyApi.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/CookieManagerProxyApi.java index 9c2988e2a54a..38fd34f66905 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/CookieManagerProxyApi.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/CookieManagerProxyApi.java @@ -52,4 +52,9 @@ public void setAcceptThirdPartyCookies( @NonNull CookieManager pigeon_instance, @NonNull WebView webView, boolean accept) { pigeon_instance.setAcceptThirdPartyCookies(webView, accept); } + + @Override + public @NonNull String getCookies(@NonNull CookieManager pigeon_instance, @NonNull String url) { + return pigeon_instance.getCookie(url); + } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/CookieManagerTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/CookieManagerTest.java index 3a9415b04ca8..34939dc8b3a9 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/CookieManagerTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/CookieManagerTest.java @@ -7,6 +7,7 @@ import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.webkit.CookieManager; import android.webkit.ValueCallback; @@ -64,4 +65,35 @@ public void setAcceptThirdPartyCookies() { verify(instance).setAcceptThirdPartyCookies(webView, accept); } + + @Test + public void getCookies_returnsCookieString() { + final PigeonApiCookieManager api = new TestProxyApiRegistrar().getPigeonApiCookieManager(); + + final CookieManager instance = mock(CookieManager.class); + final String domain = "https://flutter.dev"; + final String cookieValue = "session=12345"; + + // Mock the CookieManager to return the cookie string + when(instance.getCookie(domain)).thenReturn(cookieValue); + + final String result = api.getCookies(instance, domain); + + assertEquals(cookieValue, result); + } + + @Test + public void getCookies_returnsEmptyStringIfNull() { + final PigeonApiCookieManager api = new TestProxyApiRegistrar().getPigeonApiCookieManager(); + + final CookieManager instance = mock(CookieManager.class); + final String domain = "https://flutter.dev"; + + // Mock the CookieManager to return null + when(instance.getCookie(domain)).thenReturn(null); + + final String result = api.getCookies(instance, domain); + + assertEquals("", result); + } } diff --git a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart index db3d32723ec6..e3ebadd1bd17 100644 --- a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart @@ -496,9 +496,17 @@ class SampleMenu extends StatelessWidget { } Future _onListCookies(BuildContext context) async { - final cookies = - await webViewController.runJavaScriptReturningResult('document.cookie') - as String; + final Uri? domain = Uri.tryParse( + (await webViewController.currentUrl()) ?? '', + ); + late final List cookies; + + if (domain == null) { + cookies = []; + } else { + cookies = await cookieManager.getCookies(domain); + } + if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( @@ -662,13 +670,12 @@ class SampleMenu extends StatelessWidget { return webViewController.loadHtmlString(kAlertTestPage); } - Widget _getCookieList(String cookies) { - if (cookies == '""') { + Widget _getCookieList(List cookies) { + if (cookies.isEmpty) { return Container(); } - final List cookieList = cookies.split(';'); - final Iterable cookieWidgets = cookieList.map( - (String cookie) => Text(cookie), + final Iterable cookieWidgets = cookies.map( + (WebViewCookie cookie) => Text(cookie.toString()), ); return Column( mainAxisAlignment: MainAxisAlignment.end, diff --git a/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml index e5a643187478..10b62cab12fb 100644 --- a/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml @@ -33,3 +33,7 @@ flutter: - assets/sample_video.mp4 - assets/www/index.html - assets/www/styles/style.css +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + webview_flutter_platform_interface: {path: ../../../../packages/webview_flutter/webview_flutter_platform_interface} diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webkit.g.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webkit.g.dart index 90f5fffb971c..a7ba17f2b10e 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webkit.g.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webkit.g.dart @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.4), do not edit directly. +// Autogenerated from Pigeon (v26.1.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, omit_obvious_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers @@ -1791,6 +1791,41 @@ class CookieManager extends PigeonInternalProxyApiBaseClass { } } + /// Gets all the cookies for the given URL. + /// + /// This may return multiple key-value pairs if multiple cookies are associated with this URL, + /// in which case each cookie will be delimited by "; " characters (semicolon followed by a space). + /// Each key-value pair will be of the form "key=value". + /// + /// Note: Any cookies set with the "Partitioned" attribute will only be returned for the top-level partition of url. + Future getCookies(String url) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecCookieManager; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.webview_flutter_android.CookieManager.getCookies'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, url], + ); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as String?); + } + } + @override CookieManager pigeon_copy() { return CookieManager.pigeon_detached( diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_cookie_manager.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_cookie_manager.dart index 621e9baae048..8bee7516a7e9 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_cookie_manager.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_cookie_manager.dart @@ -87,4 +87,26 @@ class AndroidWebViewCookieManager extends PlatformWebViewCookieManager { .getInstanceWithWeakReference(controller.webViewIdentifier)!; return _cookieManager.setAcceptThirdPartyCookies(webView, accept); } + + @override + Future> getCookies(Uri url) async { + final String? cookies = await _cookieManager.getCookies(url.toString()); + if (cookies == null || cookies.isEmpty) { + return []; + } + + final webViewCookies = []; + for (final String cookie in cookies.split('; ')) { + final List cookieValue = cookie.split('='); + webViewCookies.add( + WebViewCookie( + name: cookieValue.first, + value: cookieValue.last, + domain: url.toString(), + ), + ); + } + + return webViewCookies; + } } diff --git a/packages/webview_flutter/webview_flutter_android/pigeons/android_webkit.dart b/packages/webview_flutter/webview_flutter_android/pigeons/android_webkit.dart index a6c73ab3e030..f5c29f3a99ca 100644 --- a/packages/webview_flutter/webview_flutter_android/pigeons/android_webkit.dart +++ b/packages/webview_flutter/webview_flutter_android/pigeons/android_webkit.dart @@ -261,6 +261,15 @@ abstract class CookieManager { /// Sets whether the `WebView` should allow third party cookies to be set. void setAcceptThirdPartyCookies(WebView webView, bool accept); + + /// Gets all the cookies for the given URL. + /// + /// This may return multiple key-value pairs if multiple cookies are associated with this URL, + /// in which case each cookie will be delimited by "; " characters (semicolon followed by a space). + /// Each key-value pair will be of the form "key=value". + /// + /// Note: Any cookies set with the "Partitioned" attribute will only be returned for the top-level partition of url. + String? getCookies(String url); } /// A View that displays web pages. diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml index 0fb808b5cbe3..b76abd3d64d7 100644 --- a/packages/webview_flutter/webview_flutter_android/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/pubspec.yaml @@ -34,3 +34,7 @@ topics: - html - webview - webview-flutter +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + webview_flutter_platform_interface: {path: ../../../packages/webview_flutter/webview_flutter_platform_interface} diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.mocks.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.mocks.dart index e5776a14a1a0..d9f39c13e04d 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.mocks.dart @@ -78,26 +78,26 @@ class _FakeOffset_6 extends _i1.SmartFake implements _i4.Offset { : super(parent, parentInvocation); } -class _FakePigeonInstanceManager_7 extends _i1.SmartFake - implements _i2.PigeonInstanceManager { - _FakePigeonInstanceManager_7(Object parent, Invocation parentInvocation) +class _FakePlatformViewsServiceProxy_7 extends _i1.SmartFake + implements _i5.PlatformViewsServiceProxy { + _FakePlatformViewsServiceProxy_7(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakePlatformViewsServiceProxy_8 extends _i1.SmartFake - implements _i5.PlatformViewsServiceProxy { - _FakePlatformViewsServiceProxy_8(Object parent, Invocation parentInvocation) +class _FakePlatformWebViewController_8 extends _i1.SmartFake + implements _i3.PlatformWebViewController { + _FakePlatformWebViewController_8(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakePlatformWebViewController_9 extends _i1.SmartFake - implements _i3.PlatformWebViewController { - _FakePlatformWebViewController_9(Object parent, Invocation parentInvocation) +class _FakeSize_9 extends _i1.SmartFake implements _i4.Size { + _FakeSize_9(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeSize_10 extends _i1.SmartFake implements _i4.Size { - _FakeSize_10(Object parent, Invocation parentInvocation) +class _FakePigeonInstanceManager_10 extends _i1.SmartFake + implements _i2.PigeonInstanceManager { + _FakePigeonInstanceManager_10(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } @@ -869,29 +869,14 @@ class MockAndroidWebViewController extends _i1.Mock class MockAndroidWebViewWidgetCreationParams extends _i1.Mock implements _i7.AndroidWebViewWidgetCreationParams { @override - _i2.PigeonInstanceManager get instanceManager => - (super.noSuchMethod( - Invocation.getter(#instanceManager), - returnValue: _FakePigeonInstanceManager_7( - this, - Invocation.getter(#instanceManager), - ), - returnValueForMissingStub: _FakePigeonInstanceManager_7( - this, - Invocation.getter(#instanceManager), - ), - ) - as _i2.PigeonInstanceManager); - - @override _i5.PlatformViewsServiceProxy get platformViewsServiceProxy => (super.noSuchMethod( Invocation.getter(#platformViewsServiceProxy), - returnValue: _FakePlatformViewsServiceProxy_8( + returnValue: _FakePlatformViewsServiceProxy_7( this, Invocation.getter(#platformViewsServiceProxy), ), - returnValueForMissingStub: _FakePlatformViewsServiceProxy_8( + returnValueForMissingStub: _FakePlatformViewsServiceProxy_7( this, Invocation.getter(#platformViewsServiceProxy), ), @@ -911,11 +896,11 @@ class MockAndroidWebViewWidgetCreationParams extends _i1.Mock _i3.PlatformWebViewController get controller => (super.noSuchMethod( Invocation.getter(#controller), - returnValue: _FakePlatformWebViewController_9( + returnValue: _FakePlatformWebViewController_8( this, Invocation.getter(#controller), ), - returnValueForMissingStub: _FakePlatformWebViewController_9( + returnValueForMissingStub: _FakePlatformWebViewController_8( this, Invocation.getter(#controller), ), @@ -1032,10 +1017,10 @@ class MockExpensiveAndroidViewController extends _i1.Mock (super.noSuchMethod( Invocation.method(#setSize, [size]), returnValue: _i8.Future<_i4.Size>.value( - _FakeSize_10(this, Invocation.method(#setSize, [size])), + _FakeSize_9(this, Invocation.method(#setSize, [size])), ), returnValueForMissingStub: _i8.Future<_i4.Size>.value( - _FakeSize_10(this, Invocation.method(#setSize, [size])), + _FakeSize_9(this, Invocation.method(#setSize, [size])), ), ) as _i8.Future<_i4.Size>); @@ -1111,11 +1096,11 @@ class MockFlutterAssetManager extends _i1.Mock _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_7( + returnValue: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), - returnValueForMissingStub: _FakePigeonInstanceManager_7( + returnValueForMissingStub: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), @@ -1177,11 +1162,11 @@ class MockGeolocationPermissionsCallback extends _i1.Mock _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_7( + returnValue: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), - returnValueForMissingStub: _FakePigeonInstanceManager_7( + returnValueForMissingStub: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), @@ -1247,11 +1232,11 @@ class MockJavaScriptChannel extends _i1.Mock implements _i2.JavaScriptChannel { _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_7( + returnValue: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), - returnValueForMissingStub: _FakePigeonInstanceManager_7( + returnValueForMissingStub: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), @@ -1291,11 +1276,11 @@ class MockPermissionRequest extends _i1.Mock implements _i2.PermissionRequest { _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_7( + returnValue: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), - returnValueForMissingStub: _FakePigeonInstanceManager_7( + returnValueForMissingStub: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), @@ -1519,10 +1504,10 @@ class MockSurfaceAndroidViewController extends _i1.Mock (super.noSuchMethod( Invocation.method(#setSize, [size]), returnValue: _i8.Future<_i4.Size>.value( - _FakeSize_10(this, Invocation.method(#setSize, [size])), + _FakeSize_9(this, Invocation.method(#setSize, [size])), ), returnValueForMissingStub: _i8.Future<_i4.Size>.value( - _FakeSize_10(this, Invocation.method(#setSize, [size])), + _FakeSize_9(this, Invocation.method(#setSize, [size])), ), ) as _i8.Future<_i4.Size>); @@ -1652,11 +1637,11 @@ class MockWebChromeClient extends _i1.Mock implements _i2.WebChromeClient { _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_7( + returnValue: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), - returnValueForMissingStub: _FakePigeonInstanceManager_7( + returnValueForMissingStub: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), @@ -1738,11 +1723,11 @@ class MockWebSettings extends _i1.Mock implements _i2.WebSettings { _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_7( + returnValue: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), - returnValueForMissingStub: _FakePigeonInstanceManager_7( + returnValueForMissingStub: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), @@ -1953,11 +1938,11 @@ class MockWebView extends _i1.Mock implements _i2.WebView { _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_7( + returnValue: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), - returnValueForMissingStub: _FakePigeonInstanceManager_7( + returnValueForMissingStub: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), @@ -2259,11 +2244,11 @@ class MockWebViewClient extends _i1.Mock implements _i2.WebViewClient { _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_7( + returnValue: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), - returnValueForMissingStub: _FakePigeonInstanceManager_7( + returnValueForMissingStub: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), @@ -2308,11 +2293,11 @@ class MockWebStorage extends _i1.Mock implements _i2.WebStorage { _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_7( + returnValue: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), - returnValueForMissingStub: _FakePigeonInstanceManager_7( + returnValueForMissingStub: _FakePigeonInstanceManager_10( this, Invocation.getter(#pigeon_instanceManager), ), diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_cookie_manager_test.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_cookie_manager_test.dart index 44695d2eeeca..d5f09d9f63ed 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_cookie_manager_test.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_cookie_manager_test.dart @@ -108,4 +108,93 @@ void main() { verify(mockCookieManager.setAcceptThirdPartyCookies(webView, false)); }); + + test('getCookies should return list of WebViewCookie for a domain', () async { + final mockCookieManager = MockCookieManager(); + + // Mock the return value of getCookies + when( + mockCookieManager.getCookies('https://flutter.dev'), + ).thenAnswer((_) => Future.value('foo=bar; hello=world')); + + final params = + AndroidWebViewCookieManagerCreationParams.fromPlatformWebViewCookieManagerCreationParams( + const PlatformWebViewCookieManagerCreationParams(), + ); + + final cookieManager = AndroidWebViewCookieManager( + params, + cookieManager: mockCookieManager, + ); + + final List cookies = await cookieManager.getCookies( + Uri.parse('https://flutter.dev'), + ); + + expect(cookies.length, 2); + + expect(cookies[0].name, 'foo'); + expect(cookies[0].value, 'bar'); + expect(cookies[0].domain, 'https://flutter.dev'); + + expect(cookies[1].name, 'hello'); + expect(cookies[1].value, 'world'); + expect(cookies[1].domain, 'https://flutter.dev'); + + verify(mockCookieManager.getCookies('https://flutter.dev')).called(1); + }); + + test('getCookies should return empty list if no cookies exist', () async { + final mockCookieManager = MockCookieManager(); + + when( + mockCookieManager.getCookies('https://flutter.dev'), + ).thenAnswer((_) => Future.value('')); + + final params = + AndroidWebViewCookieManagerCreationParams.fromPlatformWebViewCookieManagerCreationParams( + const PlatformWebViewCookieManagerCreationParams(), + ); + + final cookieManager = AndroidWebViewCookieManager( + params, + cookieManager: mockCookieManager, + ); + + final List cookies = await cookieManager.getCookies( + Uri.parse('https://flutter.dev'), + ); + + expect(cookies, isEmpty); + verify(mockCookieManager.getCookies('https://flutter.dev')).called(1); + }); + + test('getCookies should handle single cookie correctly', () async { + final mockCookieManager = MockCookieManager(); + + when( + mockCookieManager.getCookies('https://flutter.dev'), + ).thenAnswer((_) => Future.value('sessionId=abc123')); + + final params = + AndroidWebViewCookieManagerCreationParams.fromPlatformWebViewCookieManagerCreationParams( + const PlatformWebViewCookieManagerCreationParams(), + ); + + final cookieManager = AndroidWebViewCookieManager( + params, + cookieManager: mockCookieManager, + ); + + final List cookies = await cookieManager.getCookies( + Uri.parse('https://flutter.dev'), + ); + + expect(cookies.length, 1); + expect(cookies[0].name, 'sessionId'); + expect(cookies[0].value, 'abc123'); + expect(cookies[0].domain, 'https://flutter.dev'); + + verify(mockCookieManager.getCookies('https://flutter.dev')).called(1); + }); } diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_cookie_manager_test.mocks.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_cookie_manager_test.mocks.dart index b0d4e68f3413..2e05ef28bad9 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_cookie_manager_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_cookie_manager_test.mocks.dart @@ -7,9 +7,10 @@ import 'dart:async' as _i5; import 'dart:ui' as _i4; import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i6; import 'package:webview_flutter_android/src/android_webkit.g.dart' as _i2; import 'package:webview_flutter_android/src/android_webview_controller.dart' - as _i6; + as _i7; import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart' as _i3; @@ -105,6 +106,19 @@ class MockCookieManager extends _i1.Mock implements _i2.CookieManager { ) as _i5.Future); + @override + _i5.Future getCookies(String? domain) => + (super.noSuchMethod( + Invocation.method(#getCookies, [domain]), + returnValue: _i5.Future.value( + _i6.dummyValue( + this, + Invocation.method(#getCookies, [domain]), + ), + ), + ) + as _i5.Future); + @override _i2.CookieManager pigeon_copy() => (super.noSuchMethod( @@ -121,7 +135,7 @@ class MockCookieManager extends _i1.Mock implements _i2.CookieManager { /// /// See the documentation for Mockito's code generation for more information. class MockAndroidWebViewController extends _i1.Mock - implements _i6.AndroidWebViewController { + implements _i7.AndroidWebViewController { MockAndroidWebViewController() { _i1.throwOnMissingStub(this); } @@ -452,7 +466,7 @@ class MockAndroidWebViewController extends _i1.Mock @override _i5.Future setOnShowFileSelector( - _i5.Future> Function(_i6.FileSelectorParams)? + _i5.Future> Function(_i7.FileSelectorParams)? onShowFileSelector, ) => (super.noSuchMethod( @@ -477,8 +491,8 @@ class MockAndroidWebViewController extends _i1.Mock @override _i5.Future setGeolocationPermissionsPromptCallbacks({ - _i6.OnGeolocationPermissionsShowPrompt? onShowPrompt, - _i6.OnGeolocationPermissionsHidePrompt? onHidePrompt, + _i7.OnGeolocationPermissionsShowPrompt? onShowPrompt, + _i7.OnGeolocationPermissionsHidePrompt? onHidePrompt, }) => (super.noSuchMethod( Invocation.method(#setGeolocationPermissionsPromptCallbacks, [], { @@ -492,8 +506,8 @@ class MockAndroidWebViewController extends _i1.Mock @override _i5.Future setCustomWidgetCallbacks({ - required _i6.OnShowCustomWidgetCallback? onShowCustomWidget, - required _i6.OnHideCustomWidgetCallback? onHideCustomWidget, + required _i7.OnShowCustomWidgetCallback? onShowCustomWidget, + required _i7.OnHideCustomWidgetCallback? onHideCustomWidget, }) => (super.noSuchMethod( Invocation.method(#setCustomWidgetCallbacks, [], { @@ -602,7 +616,7 @@ class MockAndroidWebViewController extends _i1.Mock as _i5.Future); @override - _i5.Future setMixedContentMode(_i6.MixedContentMode? mode) => + _i5.Future setMixedContentMode(_i7.MixedContentMode? mode) => (super.noSuchMethod( Invocation.method(#setMixedContentMode, [mode]), returnValue: _i5.Future.value(), @@ -612,7 +626,7 @@ class MockAndroidWebViewController extends _i1.Mock @override _i5.Future isWebViewFeatureSupported( - _i6.WebViewFeatureType? featureType, + _i7.WebViewFeatureType? featureType, ) => (super.noSuchMethod( Invocation.method(#isWebViewFeatureSupported, [featureType]), diff --git a/packages/webview_flutter/webview_flutter_android/test/legacy/webview_android_cookie_manager_test.mocks.dart b/packages/webview_flutter/webview_flutter_android/test/legacy/webview_android_cookie_manager_test.mocks.dart index 772767b56000..56de2872fd8c 100644 --- a/packages/webview_flutter/webview_flutter_android/test/legacy/webview_android_cookie_manager_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_android/test/legacy/webview_android_cookie_manager_test.mocks.dart @@ -6,6 +6,7 @@ import 'dart:async' as _i3; import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i4; import 'package:webview_flutter_android/src/android_webkit.g.dart' as _i2; // ignore_for_file: type=lint @@ -82,6 +83,19 @@ class MockCookieManager extends _i1.Mock implements _i2.CookieManager { ) as _i3.Future); + @override + _i3.Future getCookies(String? domain) => + (super.noSuchMethod( + Invocation.method(#getCookies, [domain]), + returnValue: _i3.Future.value( + _i4.dummyValue( + this, + Invocation.method(#getCookies, [domain]), + ), + ), + ) + as _i3.Future); + @override _i2.CookieManager pigeon_copy() => (super.noSuchMethod( diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/HTTPCookieStoreProxyAPITests.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/HTTPCookieStoreProxyAPITests.swift index b2f559fec544..d0c7c80117c4 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/HTTPCookieStoreProxyAPITests.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/HTTPCookieStoreProxyAPITests.swift @@ -14,11 +14,16 @@ class HTTPCookieStoreProxyAPITests: XCTestCase { let instance: TestCookieStore? = TestCookieStore.customInit() let cookie = HTTPCookie(properties: [ - .name: "foo", .value: "bar", .domain: "http://google.com", .path: "/anything", + .name: "foo", .value: "bar", .domain: "http://google.com", + .path: "/anything", ])! let expect = expectation(description: "Wait for setCookie.") - api.pigeonDelegate.setCookie(pigeonApi: api, pigeonInstance: instance!, cookie: cookie) { + api.pigeonDelegate.setCookie( + pigeonApi: api, + pigeonInstance: instance!, + cookie: cookie + ) { result in switch result { case .success(_): @@ -31,21 +36,58 @@ class HTTPCookieStoreProxyAPITests: XCTestCase { wait(for: [expect], timeout: 1.0) XCTAssertEqual(instance!.setCookieArg, cookie) } + + @MainActor func testGetCookies() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiWKHTTPCookieStore(registrar) + + let cookie1 = HTTPCookie(properties: [ + .name: "foo", .value: "bar", .domain: "google.com", .path: "/", + ])! + let cookie2 = HTTPCookie(properties: [ + .name: "baz", .value: "qux", .domain: "example.com", .path: "/", + ])! + + let instance: TestCookieStore? = TestCookieStore.customInit() + instance!.allCookies = [cookie1, cookie2] + + // Test fetching all cookies + let expectAll = expectation(description: "Wait for getAllCookies.") + api.pigeonDelegate.getAllCookies( + pigeonApi: api, + pigeonInstance: instance! + ) { result in + switch result { + case .success(let cookies): + XCTAssertEqual(cookies.count, 2) + XCTAssertTrue(cookies.contains(cookie1)) + XCTAssertTrue(cookies.contains(cookie2)) + expectAll.fulfill() + case .failure(_): + break + } + } + + wait(for: [expectAll], timeout: 1.0) + } } class TestCookieStore: WKHTTPCookieStore { var setCookieArg: HTTPCookie? = nil + var allCookies: [HTTPCookie] = [] // Workaround to subclass an Objective-C class that has an `init` constructor with NS_UNAVAILABLE static func customInit() -> TestCookieStore { let instance = - TestCookieStore.perform(NSSelectorFromString("new")).takeRetainedValue() as! TestCookieStore + TestCookieStore.perform(NSSelectorFromString("new")) + .takeRetainedValue() as! TestCookieStore return instance } #if compiler(>=6.0) public override func setCookie( - _ cookie: HTTPCookie, completionHandler: (@MainActor () -> Void)? = nil + _ cookie: HTTPCookie, + completionHandler: (@MainActor () -> Void)? = nil ) { setCookieArg = cookie DispatchQueue.main.async { @@ -53,11 +95,22 @@ class TestCookieStore: WKHTTPCookieStore { } } #else - public override func setCookie(_ cookie: HTTPCookie, completionHandler: (() -> Void)? = nil) { + public override func setCookie( + _ cookie: HTTPCookie, + completionHandler: (() -> Void)? = nil + ) { setCookieArg = cookie DispatchQueue.main.async { completionHandler?() } } #endif + + override func getAllCookies( + _ completionHandler: @escaping @MainActor ([HTTPCookie]) -> Void + ) { + DispatchQueue.main.async { + completionHandler(self.allCookies) + } + } } 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 11df2e04329f..081bff28828d 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift @@ -170,11 +170,12 @@ class TestNavigationDelegateApi: PigeonApiProtocolWKNavigationDelegate { func decidePolicyForNavigationAction( pigeonInstance pigeonInstanceArg: WKNavigationDelegate, webView webViewArg: WKWebView, navigationAction navigationActionArg: WKNavigationAction, - completion: @escaping ( - Result< - webview_flutter_wkwebview.NavigationActionPolicy, webview_flutter_wkwebview.PigeonError - > - ) -> Void + completion: + @escaping ( + Result< + webview_flutter_wkwebview.NavigationActionPolicy, webview_flutter_wkwebview.PigeonError + > + ) -> Void ) { decidePolicyForNavigationActionArgs = [webViewArg, navigationActionArg] completion(.success(.allow)) @@ -183,11 +184,12 @@ class TestNavigationDelegateApi: PigeonApiProtocolWKNavigationDelegate { func decidePolicyForNavigationResponse( pigeonInstance pigeonInstanceArg: WKNavigationDelegate, webView webViewArg: WKWebView, navigationResponse navigationResponseArg: WKNavigationResponse, - completion: @escaping ( - Result< - webview_flutter_wkwebview.NavigationResponsePolicy, webview_flutter_wkwebview.PigeonError - > - ) -> Void + completion: + @escaping ( + Result< + webview_flutter_wkwebview.NavigationResponsePolicy, webview_flutter_wkwebview.PigeonError + > + ) -> Void ) { decidePolicyForNavigationResponseArgs = [webViewArg, navigationResponseArg] completion(.success(.cancel)) @@ -219,12 +221,13 @@ class TestNavigationDelegateApi: PigeonApiProtocolWKNavigationDelegate { func didReceiveAuthenticationChallenge( pigeonInstance pigeonInstanceArg: WKNavigationDelegate, webView webViewArg: WKWebView, challenge challengeArg: URLAuthenticationChallenge, - completion: @escaping ( - Result< - webview_flutter_wkwebview.AuthenticationChallengeResponse, - webview_flutter_wkwebview.PigeonError - > - ) -> Void + completion: + @escaping ( + Result< + webview_flutter_wkwebview.AuthenticationChallengeResponse, + webview_flutter_wkwebview.PigeonError + > + ) -> Void ) { didReceiveAuthenticationChallengeArgs = [webViewArg, challengeArg] completion( @@ -241,7 +244,8 @@ class TestWebView: WKWebView { } } -class TestURLAuthenticationChallengeSender: NSObject, URLAuthenticationChallengeSender, @unchecked +class TestURLAuthenticationChallengeSender: NSObject, URLAuthenticationChallengeSender, + @unchecked Sendable { func use(_ credential: URLCredential, for challenge: URLAuthenticationChallenge) { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/HTTPCookieProxyAPIDelegate.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/HTTPCookieProxyAPIDelegate.swift index a5b81998200c..fa52bea9a52c 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/HTTPCookieProxyAPIDelegate.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/HTTPCookieProxyAPIDelegate.swift @@ -110,6 +110,7 @@ class HTTPCookieProxyAPIDelegate: PigeonApiDelegateHTTPCookie { return (newKey, value) } - return Dictionary(uniqueKeysWithValues: keyValueTuples) + // Use newest value in case of duplicates + return Dictionary(keyValueTuples, uniquingKeysWith: { _, last in last }) } } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/HTTPCookieStoreProxyAPIDelegate.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/HTTPCookieStoreProxyAPIDelegate.swift index 74fcf53fb9d6..66aa24cbdb79 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/HTTPCookieStoreProxyAPIDelegate.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/HTTPCookieStoreProxyAPIDelegate.swift @@ -11,11 +11,23 @@ import WebKit /// or handle method calls on the associated native class or an instance of that class. class HTTPCookieStoreProxyAPIDelegate: PigeonApiDelegateWKHTTPCookieStore { func setCookie( - pigeonApi: PigeonApiWKHTTPCookieStore, pigeonInstance: WKHTTPCookieStore, cookie: HTTPCookie, + pigeonApi: PigeonApiWKHTTPCookieStore, + pigeonInstance: WKHTTPCookieStore, + cookie: HTTPCookie, completion: @escaping (Result) -> Void ) { pigeonInstance.setCookie(cookie) { completion(.success(Void())) } } + + func getAllCookies( + pigeonApi: PigeonApiWKHTTPCookieStore, pigeonInstance: WKHTTPCookieStore, + completion: @escaping (Result<[HTTPCookie], any Error>) -> Void + ) { + pigeonInstance.getAllCookies { cookies in + completion(.success(cookies)) + } + } + } 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 ac5f269fff6e..7c407e278a68 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 @@ -233,7 +233,8 @@ public class NavigationDelegateImpl: NSObject, WKNavigationDelegate { #if compiler(>=6.0) public func webView( _ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, - completionHandler: @escaping @MainActor (URLSession.AuthChallengeDisposition, URLCredential?) + completionHandler: + @escaping @MainActor (URLSession.AuthChallengeDisposition, URLCredential?) -> Void ) { @@ -256,7 +257,8 @@ public class NavigationDelegateImpl: NSObject, WKNavigationDelegate { #else public func webView( _ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, - completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> + completionHandler: + @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void ) { registrar.dispatchOnMainThread { onFailure in diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/ProxyAPIRegistrar.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/ProxyAPIRegistrar.swift index 131c8ffde7a5..c4d446d8020c 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/ProxyAPIRegistrar.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/ProxyAPIRegistrar.swift @@ -78,9 +78,10 @@ open class ProxyAPIRegistrar: WebKitLibraryPigeonProxyApiRegistrar { /// Handles calling a Flutter method on the main thread. func dispatchOnMainThread( - execute work: @escaping ( - _ onFailure: @escaping (_ methodName: String, _ error: PigeonError) -> Void - ) -> Void + execute work: + @escaping ( + _ onFailure: @escaping (_ methodName: String, _ error: PigeonError) -> Void + ) -> Void ) { DispatchQueue.main.async { work { methodName, error in 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 d0bea7528c0f..c9345d666bcf 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 @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.4), do not edit directly. +// Autogenerated from Pigeon (v26.1.5), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -6569,6 +6569,10 @@ protocol PigeonApiDelegateWKHTTPCookieStore { func setCookie( pigeonApi: PigeonApiWKHTTPCookieStore, pigeonInstance: WKHTTPCookieStore, cookie: HTTPCookie, completion: @escaping (Result) -> Void) + /// Fetches all stored cookies. + func getAllCookies( + pigeonApi: PigeonApiWKHTTPCookieStore, pigeonInstance: WKHTTPCookieStore, + completion: @escaping (Result<[HTTPCookie], Error>) -> Void) } protocol PigeonApiProtocolWKHTTPCookieStore { @@ -6620,6 +6624,26 @@ final class PigeonApiWKHTTPCookieStore: PigeonApiProtocolWKHTTPCookieStore { } else { setCookieChannel.setMessageHandler(nil) } + let getAllCookiesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.webview_flutter_wkwebview.WKHTTPCookieStore.getAllCookies", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + getAllCookiesChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! WKHTTPCookieStore + api.pigeonDelegate.getAllCookies(pigeonApi: api, pigeonInstance: pigeonInstanceArg) { + result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + getAllCookiesChannel.setMessageHandler(nil) + } } ///Creates a Dart instance of WKHTTPCookieStore and attaches it to [pigeonInstance]. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart index 31473b0dc1a4..50284a98cdca 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart @@ -501,9 +501,17 @@ class SampleMenu extends StatelessWidget { } Future _onListCookies(BuildContext context) async { - final cookies = - await webViewController.runJavaScriptReturningResult('document.cookie') - as String; + final Uri? domain = Uri.tryParse( + (await webViewController.currentUrl()) ?? '', + ); + late final List cookies; + + if (domain == null) { + cookies = []; + } else { + cookies = await cookieManager.getCookies(domain); + } + if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( @@ -642,13 +650,12 @@ class SampleMenu extends StatelessWidget { return webViewController.loadHtmlString(kAlertTestPage); } - Widget _getCookieList(String cookies) { - if (cookies == '""') { + Widget _getCookieList(List cookies) { + if (cookies.isEmpty) { return Container(); } - final List cookieList = cookies.split(';'); - final Iterable cookieWidgets = cookieList.map( - (String cookie) => Text(cookie), + final Iterable cookieWidgets = cookies.map( + (WebViewCookie cookie) => Text(cookie.toString()), ); return Column( mainAxisAlignment: MainAxisAlignment.end, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml index 391af935df1a..d177ae3d11a0 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml @@ -35,3 +35,7 @@ flutter: - assets/www/styles/style.css # Test certificate used to create a test native `SecTrust`. - assets/test_cert.der +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + webview_flutter_platform_interface: {path: ../../../../packages/webview_flutter/webview_flutter_platform_interface} 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 82dd5a93f8ea..cd65b3b9fdf2 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 // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.4), do not edit directly. +// Autogenerated from Pigeon (v26.1.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, omit_obvious_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers @@ -8430,6 +8430,40 @@ class WKHTTPCookieStore extends NSObject { } } + /// Fetches all stored cookies. + Future> getAllCookies() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecWKHTTPCookieStore; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.webview_flutter_wkwebview.WKHTTPCookieStore.getAllCookies'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as List?)!.cast(); + } + } + @override WKHTTPCookieStore pigeon_copy() { return WKHTTPCookieStore.pigeon_detached( diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_cookie_manager.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_cookie_manager.dart index 5556890a39d3..f2ce50c50dc0 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_cookie_manager.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_cookie_manager.dart @@ -73,4 +73,37 @@ class WebKitWebViewCookieManager extends PlatformWebViewCookieManager { return (char < 0x20 || char > 0x3A) && (char < 0x3C || char > 0x7E); }); } + + @override + Future> getCookies(Uri url) async { + final List httpCookies = await _webkitParams + ._websiteDataStore + .httpCookieStore + .getAllCookies(); + + final Iterable> webviewCookies = httpCookies.map(( + cookie, + ) async { + final Map? props = await cookie + .getProperties(); + + if (props == null) { + return null; + } + + final domain = props[HttpCookiePropertyKey.domain].toString(); + if (!domain.contains(url.host)) { + return null; + } + + return WebViewCookie( + name: props[HttpCookiePropertyKey.name].toString(), + value: props[HttpCookiePropertyKey.value].toString(), + domain: domain, + path: props[HttpCookiePropertyKey.path].toString(), + ); + }); + + return (await Future.wait(webviewCookies)).nonNulls.toList(); + } } 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 51b6e680a320..3ab45fcd6b54 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart @@ -1097,6 +1097,10 @@ abstract class WKHTTPCookieStore extends NSObject { /// storage. @async void setCookie(HTTPCookie cookie); + + /// Fetches all stored cookies. + @async + List getAllCookies(); } /// The interface for the delegate of a scroll view. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml index 714304d9b34a..ee08b7d5564e 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml @@ -39,3 +39,7 @@ topics: - html - webview - webview-flutter +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins +dependency_overrides: + webview_flutter_platform_interface: {path: ../../../packages/webview_flutter/webview_flutter_platform_interface} diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_cookie_manager_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_cookie_manager_test.mocks.dart index e02154caacf8..32f3127e2ca5 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_cookie_manager_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_cookie_manager_test.mocks.dart @@ -69,6 +69,16 @@ class MockWKHTTPCookieStore extends _i1.Mock implements _i2.WKHTTPCookieStore { ) as _i3.Future); + @override + _i3.Future> getCookies(String? domain) => + (super.noSuchMethod( + Invocation.method(#getCookies, [domain]), + returnValue: _i3.Future>.value( + <_i2.HTTPCookie>[], + ), + ) + as _i3.Future>); + @override _i2.WKHTTPCookieStore pigeon_copy() => (super.noSuchMethod( diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_cookie_manager_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_cookie_manager_test.dart index e3f15d030a4b..bae0e4d1907d 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_cookie_manager_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_cookie_manager_test.dart @@ -12,7 +12,7 @@ import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart'; import 'webkit_webview_cookie_manager_test.mocks.dart'; -@GenerateMocks([WKWebsiteDataStore, WKHTTPCookieStore]) +@GenerateMocks([WKWebsiteDataStore, WKHTTPCookieStore, HTTPCookie]) void main() { WidgetsFlutterBinding.ensureInitialized(); @@ -105,5 +105,61 @@ void main() { throwsArgumentError, ); }); + + test('getCookies returns cookies correctly', () async { + final mockWKWebsiteDataStore = MockWKWebsiteDataStore(); + final mockCookieStore = MockWKHTTPCookieStore(); + + when(mockWKWebsiteDataStore.httpCookieStore).thenReturn(mockCookieStore); + + // Mock cookies returned by the cookie store + final mockCookie1 = MockHTTPCookie(); + final mockCookie2 = MockHTTPCookie(); + + when(mockCookie1.getProperties()).thenAnswer( + (_) async => { + HttpCookiePropertyKey.name: 'cookie1', + HttpCookiePropertyKey.value: 'value1', + HttpCookiePropertyKey.domain: 'flutter.dev', + HttpCookiePropertyKey.path: '/', + }, + ); + + when(mockCookie2.getProperties()).thenAnswer( + (_) async => { + HttpCookiePropertyKey.name: 'cookie2', + HttpCookiePropertyKey.value: 'value2', + HttpCookiePropertyKey.domain: 'flutter.dev', + HttpCookiePropertyKey.path: '/path', + }, + ); + + when( + mockCookieStore.getCookies('flutter.dev'), + ).thenAnswer((_) async => [mockCookie1, mockCookie2]); + + PigeonOverrides.wKWebsiteDataStore_defaultDataStore = + mockWKWebsiteDataStore; + + final manager = WebKitWebViewCookieManager( + WebKitWebViewCookieManagerCreationParams(), + ); + + final List cookies = await manager.getCookies( + Uri.parse('https://flutter.dev'), + ); + + expect(cookies.length, 2); + + expect(cookies[0].name, 'cookie1'); + expect(cookies[0].value, 'value1'); + expect(cookies[0].domain, 'flutter.dev'); + expect(cookies[0].path, '/'); + + expect(cookies[1].name, 'cookie2'); + expect(cookies[1].value, 'value2'); + expect(cookies[1].domain, 'flutter.dev'); + expect(cookies[1].path, '/path'); + }); }); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_cookie_manager_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_cookie_manager_test.mocks.dart index ed94dc28231c..e748ac106833 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_cookie_manager_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_cookie_manager_test.mocks.dart @@ -41,6 +41,11 @@ class _FakeWKWebsiteDataStore_2 extends _i1.SmartFake : super(parent, parentInvocation); } +class _FakeHTTPCookie_3 extends _i1.SmartFake implements _i2.HTTPCookie { + _FakeHTTPCookie_3(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + /// A class which mocks [WKWebsiteDataStore]. /// /// See the documentation for Mockito's code generation for more information. @@ -159,6 +164,16 @@ class MockWKHTTPCookieStore extends _i1.Mock implements _i2.WKHTTPCookieStore { ) as _i3.Future); + @override + _i3.Future> getCookies(String? domain) => + (super.noSuchMethod( + Invocation.method(#getCookies, [domain]), + returnValue: _i3.Future>.value( + <_i2.HTTPCookie>[], + ), + ) + as _i3.Future>); + @override _i2.WKHTTPCookieStore pigeon_copy() => (super.noSuchMethod( @@ -192,3 +207,65 @@ class MockWKHTTPCookieStore extends _i1.Mock implements _i2.WKHTTPCookieStore { ) as _i3.Future); } + +/// A class which mocks [HTTPCookie]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockHTTPCookie extends _i1.Mock implements _i2.HTTPCookie { + MockHTTPCookie() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => + (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_1( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) + as _i2.PigeonInstanceManager); + + @override + _i3.Future?> getProperties() => + (super.noSuchMethod( + Invocation.method(#getProperties, []), + returnValue: + _i3.Future?>.value(), + ) + as _i3.Future?>); + + @override + _i2.HTTPCookie pigeon_copy() => + (super.noSuchMethod( + Invocation.method(#pigeon_copy, []), + returnValue: _FakeHTTPCookie_3( + this, + Invocation.method(#pigeon_copy, []), + ), + ) + as _i2.HTTPCookie); + + @override + _i3.Future addObserver( + _i2.NSObject? observer, + String? keyPath, + List<_i2.KeyValueObservingOptions>? options, + ) => + (super.noSuchMethod( + Invocation.method(#addObserver, [observer, keyPath, options]), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) + as _i3.Future); + + @override + _i3.Future removeObserver(_i2.NSObject? observer, String? keyPath) => + (super.noSuchMethod( + Invocation.method(#removeObserver, [observer, keyPath]), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) + as _i3.Future); +}