diff --git a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md index 4e506ded26db..81d4e46b6ce9 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 043b5888a69f..61e0dd7e247a 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 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController { .then((dynamic result) => result! as bool); } + /// Method channel implementation for [WebViewPlatform.setCookie]. + static Future setCookie(WebViewCookie cookie) { + return _cookieManagerChannel.invokeMethod( + 'setCookie', cookie.toJson()); + } + static Map _webSettingsToMap(WebSettings? settings) { final Map map = {}; void _addIfNonNull(String key, dynamic value) { @@ -260,6 +266,9 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController { '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 43f967fb13b0..a6967a5410f4 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 000000000000..d960926e419c --- /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 clearCookies() { + throw UnimplementedError( + 'clearCookies is not implemented on the current platform'); + } + + /// Sets a cookie for all [WebView] instances. + Future 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 ca17cb684a53..a472f00d4bd2 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 @@ abstract class WebViewPlatform { /// Clears all cookies for all [WebView] instances. /// /// Returns true if cookies were present before clearing, else false. + @Deprecated('Use `WebViewCookieManagerPlatform.clearCookies` instead.') Future 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 e69f510e32fb..e9f5ef598b1d 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 @@ class CreationParams { this.userAgent, this.autoMediaPlaybackPolicy = AutoMediaPlaybackPolicy.require_user_action_for_all_media_types, + this.cookies = const [], }) : assert(autoMediaPlaybackPolicy != null); /// The initialUrl to load in the webview. @@ -53,8 +56,11 @@ class CreationParams { /// 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 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 8ce834196cd8..f2bcf19f42fd 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 'javascript_mode.dart'; 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 000000000000..406c510afd4b --- /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. + Map toJson() { + return { + '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 318fea614b4d..3c0b5fa34b63 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 @@ repository: https://github.com/flutter/plugins/tree/master/packages/webview_flut 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 2db2dfad4f57..0432373fc8ac 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 @@ void main() { ], ); }); + + test('setCookie', () async { + await MethodChannelWebViewPlatform.setCookie(const WebViewCookie( + name: 'foo', value: 'bar', domain: 'flutter.dev')); + + expect( + log, + [ + isMethodCall( + 'setCookie', + arguments: { + '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 000000000000..e0aae2146abc --- /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 000000000000..f058b8649b96 --- /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 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'); + }); +}