[webview_flutter] Add supporting interfaces for setting cookies to platform interface. (#4555)
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md index 4e506de..81d4e46 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md
@@ -1,3 +1,9 @@ +## 1.6.0 + +* Adds platform interface for cookie manager. +* Deprecates `clearCookies` in WebViewPlatform in favour of `CookieManager#clearCookies`. +* Expanded `CreationParams` to include cookies to be set at webview creation. + ## 1.5.2 * Mirgrates from analysis_options_legacy.yaml to the more strict analysis_options.yaml.
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart index 043b588..61e0dd7 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart
@@ -216,6 +216,12 @@ .then<bool>((dynamic result) => result! as bool); } + /// Method channel implementation for [WebViewPlatform.setCookie]. + static Future<void> setCookie(WebViewCookie cookie) { + return _cookieManagerChannel.invokeMethod<void>( + 'setCookie', cookie.toJson()); + } + static Map<String, dynamic> _webSettingsToMap(WebSettings? settings) { final Map<String, dynamic> map = <String, dynamic>{}; void _addIfNonNull(String key, dynamic value) { @@ -260,6 +266,9 @@ 'userAgent': creationParams.userAgent, 'autoMediaPlaybackPolicy': creationParams.autoMediaPlaybackPolicy.index, 'usesHybridComposition': usesHybridComposition, + 'cookies': creationParams.cookies + .map((WebViewCookie cookie) => cookie.toJson()) + .toList() }; } }
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/platform_interface.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/platform_interface.dart index 43f967f..a6967a5 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/platform_interface.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/platform_interface.dart
@@ -3,6 +3,7 @@ // found in the LICENSE file. export 'javascript_channel_registry.dart'; +export 'webview_cookie_manager.dart'; export 'webview_platform.dart'; export 'webview_platform_callbacks_handler.dart'; export 'webview_platform_controller.dart';
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_cookie_manager.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_cookie_manager.dart new file mode 100644 index 0000000..d960926 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_cookie_manager.dart
@@ -0,0 +1,50 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; +import 'package:webview_flutter_platform_interface/src/types/webview_cookie.dart'; + +/// Interface for a platform implementation of a cookie manager. +/// +/// Platform implementations should extend this class rather than implement it as `webview_flutter` +/// does not consider newly added methods to be breaking changes. Extending this class +/// (using `extends`) ensures that the subclass will get the default implementation, while +/// platform implementations that `implements` this interface will be broken by newly added +/// [WebViewCookieManagerPlatform] methods. +abstract class WebViewCookieManagerPlatform extends PlatformInterface { + /// Constructs a WebViewCookieManagerPlatform. + WebViewCookieManagerPlatform() : super(token: _token); + + static final Object _token = Object(); + + static WebViewCookieManagerPlatform? _instance; + + /// The instance of [WebViewCookieManagerPlatform] to use. + static WebViewCookieManagerPlatform? get instance => _instance; + + /// Platform-specific plugins should set this with their own platform-specific + /// class that extends [WebViewCookieManagerPlatform] when they register themselves. + static set instance(WebViewCookieManagerPlatform? instance) { + if (instance == null) { + throw AssertionError( + 'Platform interfaces can only be set to a non-null instance'); + } + PlatformInterface.verifyToken(instance, _token); + _instance = instance; + } + + /// Clears all cookies for all [WebView] instances. + /// + /// Returns true if cookies were present before clearing, else false. + Future<bool> clearCookies() { + throw UnimplementedError( + 'clearCookies is not implemented on the current platform'); + } + + /// Sets a cookie for all [WebView] instances. + Future<void> setCookie(WebViewCookie cookie) { + throw UnimplementedError( + 'setCookie is not implemented on the current platform'); + } +}
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform.dart index ca17cb6..a472f00 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform.dart
@@ -59,6 +59,7 @@ /// Clears all cookies for all [WebView] instances. /// /// Returns true if cookies were present before clearing, else false. + @Deprecated('Use `WebViewCookieManagerPlatform.clearCookies` instead.') Future<bool> clearCookies() { throw UnimplementedError( 'WebView clearCookies is not implemented on the current platform');
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/creation_params.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/creation_params.dart index e69f510..e9f5ef5 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/creation_params.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/creation_params.dart
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:webview_flutter_platform_interface/src/types/types.dart'; + import 'auto_media_playback_policy.dart'; import 'web_settings.dart'; @@ -20,6 +22,7 @@ this.userAgent, this.autoMediaPlaybackPolicy = AutoMediaPlaybackPolicy.require_user_action_for_all_media_types, + this.cookies = const <WebViewCookie>[], }) : assert(autoMediaPlaybackPolicy != null); /// The initialUrl to load in the webview. @@ -53,8 +56,11 @@ /// Which restrictions apply on automatic media playback. final AutoMediaPlaybackPolicy autoMediaPlaybackPolicy; + /// The initial set of cookies to set before the webview does its first load. + final List<WebViewCookie> cookies; + @override String toString() { - return 'CreationParams(initialUrl: $initialUrl, settings: $webSettings, javascriptChannelNames: $javascriptChannelNames, UserAgent: $userAgent)'; + return 'CreationParams(initialUrl: $initialUrl, settings: $webSettings, javascriptChannelNames: $javascriptChannelNames, UserAgent: $userAgent, cookies: $cookies)'; } }
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/types.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/types.dart index 8ce8341..f2bcf19 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/types.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/types.dart
@@ -10,4 +10,5 @@ export 'web_resource_error.dart'; export 'web_resource_error_type.dart'; export 'web_settings.dart'; +export 'webview_cookie.dart'; export 'webview_request.dart';
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/webview_cookie.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/webview_cookie.dart new file mode 100644 index 0000000..406c510 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/webview_cookie.dart
@@ -0,0 +1,49 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// A cookie that can be set globally for all web views +/// using [WebViewCookieManagerPlatform]. +class WebViewCookie { + /// Constructs a new [WebViewCookie]. + const WebViewCookie( + {required this.name, + required this.value, + required this.domain, + this.path = '/'}); + + /// The cookie-name of the cookie. + /// + /// Its value should match "cookie-name" in RFC6265bis: + /// https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-02#section-4.1.1 + final String name; + + /// The cookie-value of the cookie. + /// + /// Its value should match "cookie-value" in RFC6265bis: + /// https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-02#section-4.1.1 + final String value; + + /// The domain-value of the cookie. + /// + /// Its value should match "domain-value" in RFC6265bis: + /// https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-02#section-4.1.1 + final String domain; + + /// The path-value of the cookie. + /// Is set to `/` in the constructor by default. + /// + /// Its value should match "path-value" in RFC6265bis: + /// https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-02#section-4.1.1 + final String path; + + /// Serializes the [WebViewCookie] to a Map<String, String>. + Map<String, String> toJson() { + return <String, String>{ + 'name': name, + 'value': value, + 'domain': domain, + 'path': path + }; + } +}
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml b/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml index 318fea6..3c0b5fa 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml
@@ -4,7 +4,7 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview_flutter%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 1.5.2 +version: 1.6.0 environment: sdk: ">=2.12.0 <3.0.0"
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart b/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart index 2db2dfa..0432373 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart
@@ -590,6 +590,26 @@ ], ); }); + + test('setCookie', () async { + await MethodChannelWebViewPlatform.setCookie(const WebViewCookie( + name: 'foo', value: 'bar', domain: 'flutter.dev')); + + expect( + log, + <Matcher>[ + isMethodCall( + 'setCookie', + arguments: <String, String>{ + 'name': 'foo', + 'value': 'bar', + 'domain': 'flutter.dev', + 'path': '/', + }, + ), + ], + ); + }); }); }
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/test/src/platform_interface/webview_cookie_manager_test.dart b/packages/webview_flutter/webview_flutter_platform_interface/test/src/platform_interface/webview_cookie_manager_test.dart new file mode 100644 index 0000000..e0aae21 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_platform_interface/test/src/platform_interface/webview_cookie_manager_test.dart
@@ -0,0 +1,27 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:webview_flutter_platform_interface/src/platform_interface/platform_interface.dart'; +import 'package:webview_flutter_platform_interface/src/types/webview_cookie.dart'; + +void main() { + WebViewCookieManagerPlatform? cookieManager; + + setUp(() { + cookieManager = TestWebViewCookieManagerPlatform(); + }); + + test('clearCookies should throw UnimplementedError', () { + expect(() => cookieManager!.clearCookies(), throwsUnimplementedError); + }); + + test('setCookie should throw UnimplementedError', () { + const WebViewCookie cookie = + WebViewCookie(domain: 'flutter.dev', name: 'foo', value: 'bar'); + expect(() => cookieManager!.setCookie(cookie), throwsUnimplementedError); + }); +} + +class TestWebViewCookieManagerPlatform extends WebViewCookieManagerPlatform {}
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/test/src/types/webview_cookie_test.dart b/packages/webview_flutter/webview_flutter_platform_interface/test/src/types/webview_cookie_test.dart new file mode 100644 index 0000000..f058b86 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_platform_interface/test/src/types/webview_cookie_test.dart
@@ -0,0 +1,21 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:webview_flutter_platform_interface/src/types/types.dart'; + +void main() { + test('WebViewCookie should serialize correctly', () { + WebViewCookie cookie; + Map<String, String> serializedCookie; + // Test serialization + cookie = const WebViewCookie( + name: 'foo', value: 'bar', domain: 'example.com', path: '/test'); + serializedCookie = cookie.toJson(); + expect(serializedCookie['name'], 'foo'); + expect(serializedCookie['value'], 'bar'); + expect(serializedCookie['domain'], 'example.com'); + expect(serializedCookie['path'], '/test'); + }); +}