Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

[webview_flutter] Add supporting interfaces for setting cookies to platform interface. #4555

Merged
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,12 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController {
.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) {
Expand Down Expand Up @@ -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()
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Original file line number Diff line number Diff line change
@@ -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');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.')
Copy link
Contributor Author

@BeMacized BeMacized Nov 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ reviewer: Just want to double check if it's ok to deprecate platform interface methods like this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't deprecate methods we're still using; it breaks the tree. (I should have tooling soon that will catch this kind of thing in CI.)

They can be commented as deprecated, and then actually deprecated later once the uses have been removed.

Unless you can fix the call sites right away, we need to revert this part, as this will close not only our tree, but the flutter/flutter tree as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stuartmorgan Alright, I'll quickly submit a PR that changes this annotation to a comment.

Future<bool> clearCookies() {
throw UnimplementedError(
'WebView clearCookies is not implemented on the current platform');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -20,6 +22,7 @@ class CreationParams {
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.
Expand Down Expand Up @@ -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<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)';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Original file line number Diff line number Diff line change
@@ -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.

/// Configuration to use when creating a new [WebViewPlatformController].
///
/// The `autoMediaPlaybackPolicy` parameter must not be null.
BeMacized marked this conversation as resolved.
Show resolved Hide resolved
class WebViewCookie {
/// Construct a new [WebViewCookie].
BeMacized marked this conversation as resolved.
Show resolved Hide resolved
const WebViewCookie(
{required this.name,
required this.value,
required this.domain,
this.path = '/'});

/// The 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 value of the cookie.
BeMacized marked this conversation as resolved.
Show resolved Hide resolved
///
/// 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 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 value of the cookie.
///
/// 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;

/// Serialize a [WebViewCookie] to a Map<String, String>.
BeMacized marked this conversation as resolved.
Show resolved Hide resolved
Map<String, String> toJson() {
return <String, String>{
'name': name,
'value': value,
'domain': domain,
'path': path
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,26 @@ void main() {
],
);
});

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': '/',
},
),
],
);
});
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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 {}
Original file line number Diff line number Diff line change
@@ -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');
});
}