Skip to content

Commit c90dd98

Browse files
[webview_flutter_android] Adds support to accept third party cookies (#3834)
Adds support to accept third party cookies with https://developer.android.com/reference/android/webkit/CookieManager#setAcceptThirdPartyCookies(android.webkit.WebView,%20boolean) This is being added as an Android-specific method since iOS doesn't seem to have an equivalent. See https://developer.apple.com/forums/thread/701327 https://developer.apple.com/forums/thread/16847 This also updates the `CookieManager` wrapping since the `HostApi` needs to access the `InstanceManager` for this method. Fixes flutter/flutter#125569
1 parent 6e9258f commit c90dd98

20 files changed

+1386
-184
lines changed

packages/webview_flutter/webview_flutter_android/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 3.7.0
2+
3+
* Adds support to accept third party cookies. See
4+
`AndroidWebViewCookieManager.setAcceptThirdPartyCookies`.
5+
16
## 3.6.3
27

38
* Updates gradle, AGP and fixes some lint errors.

packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/CookieManagerHostApiImpl.java

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,93 @@
77
import android.os.Build;
88
import android.webkit.CookieManager;
99
import androidx.annotation.NonNull;
10+
import androidx.annotation.VisibleForTesting;
11+
import io.flutter.plugin.common.BinaryMessenger;
1012
import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.CookieManagerHostApi;
13+
import java.util.Objects;
14+
15+
/**
16+
* Host API implementation for `CookieManager`.
17+
*
18+
* <p>This class may handle instantiating and adding native object instances that are attached to a
19+
* Dart instance or handle method calls on the associated native class or an instance of the class.
20+
*/
21+
public class CookieManagerHostApiImpl implements CookieManagerHostApi {
22+
// To ease adding additional methods, this value is added prematurely.
23+
@SuppressWarnings({"unused", "FieldCanBeLocal"})
24+
private final BinaryMessenger binaryMessenger;
25+
26+
private final InstanceManager instanceManager;
27+
private final CookieManagerProxy proxy;
28+
29+
/** Proxy for constructors and static method of `CookieManager`. */
30+
@VisibleForTesting
31+
static class CookieManagerProxy {
32+
/** Handles the Dart static method `MyClass.myStaticMethod`. */
33+
@NonNull
34+
public CookieManager getInstance() {
35+
return CookieManager.getInstance();
36+
}
37+
}
38+
39+
/**
40+
* Constructs a {@link CookieManagerHostApiImpl}.
41+
*
42+
* @param binaryMessenger used to communicate with Dart over asynchronous messages
43+
* @param instanceManager maintains instances stored to communicate with attached Dart objects
44+
*/
45+
public CookieManagerHostApiImpl(
46+
@NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager) {
47+
this(binaryMessenger, instanceManager, new CookieManagerProxy());
48+
}
49+
50+
/**
51+
* Constructs a {@link CookieManagerHostApiImpl}.
52+
*
53+
* @param binaryMessenger used to communicate with Dart over asynchronous messages
54+
* @param instanceManager maintains instances stored to communicate with attached Dart objects
55+
* @param proxy proxy for constructors and static methods of `CookieManager`
56+
*/
57+
public CookieManagerHostApiImpl(
58+
@NonNull BinaryMessenger binaryMessenger,
59+
@NonNull InstanceManager instanceManager,
60+
@NonNull CookieManagerProxy proxy) {
61+
this.binaryMessenger = binaryMessenger;
62+
this.instanceManager = instanceManager;
63+
this.proxy = proxy;
64+
}
1165

12-
class CookieManagerHostApiImpl implements CookieManagerHostApi {
1366
@Override
14-
public void clearCookies(@NonNull GeneratedAndroidWebView.Result<Boolean> result) {
15-
CookieManager cookieManager = CookieManager.getInstance();
67+
public void attachInstance(@NonNull Long instanceIdentifier) {
68+
instanceManager.addDartCreatedInstance(proxy.getInstance(), instanceIdentifier);
69+
}
70+
71+
@Override
72+
public void setCookie(@NonNull Long identifier, @NonNull String url, @NonNull String value) {
73+
getCookieManagerInstance(identifier).setCookie(url, value);
74+
}
75+
76+
@Override
77+
public void removeAllCookies(
78+
@NonNull Long identifier, @NonNull GeneratedAndroidWebView.Result<Boolean> result) {
1679
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
17-
cookieManager.removeAllCookies(result::success);
80+
getCookieManagerInstance(identifier).removeAllCookies(result::success);
1881
} else {
19-
result.success(removeCookiesPreL(cookieManager));
82+
result.success(removeCookiesPreL(getCookieManagerInstance(identifier)));
2083
}
2184
}
2285

2386
@Override
24-
public void setCookie(@NonNull String url, @NonNull String value) {
25-
CookieManager.getInstance().setCookie(url, value);
87+
public void setAcceptThirdPartyCookies(
88+
@NonNull Long identifier, @NonNull Long webViewIdentifier, @NonNull Boolean accept) {
89+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
90+
getCookieManagerInstance(identifier)
91+
.setAcceptThirdPartyCookies(
92+
Objects.requireNonNull(instanceManager.getInstance(webViewIdentifier)), accept);
93+
} else {
94+
throw new UnsupportedOperationException(
95+
"`setAcceptThirdPartyCookies` is unsupported on versions below `Build.VERSION_CODES.LOLLIPOP`.");
96+
}
2697
}
2798

2899
/**
@@ -40,4 +111,9 @@ private boolean removeCookiesPreL(CookieManager cookieManager) {
40111
}
41112
return hasCookies;
42113
}
114+
115+
@NonNull
116+
private CookieManager getCookieManagerInstance(@NonNull Long identifier) {
117+
return Objects.requireNonNull(instanceManager.getInstance(identifier));
118+
}
43119
}

packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java

Lines changed: 86 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
// Autogenerated from Pigeon (v9.2.4), do not edit directly.
4+
// Autogenerated from Pigeon (v9.2.5), do not edit directly.
55
// See also: https://pub.dev/packages/pigeon
66

77
package io.flutter.plugins.webviewflutter;
@@ -589,12 +589,25 @@ public void dispose(@NonNull Long identifierArg, @NonNull Reply<Void> callback)
589589
channelReply -> callback.reply(null));
590590
}
591591
}
592-
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
592+
/**
593+
* Host API for `CookieManager`.
594+
*
595+
* <p>This class may handle instantiating and adding native object instances that are attached to
596+
* a Dart instance or handle method calls on the associated native class or an instance of the
597+
* class.
598+
*
599+
* <p>Generated interface from Pigeon that represents a handler of messages from Flutter.
600+
*/
593601
public interface CookieManagerHostApi {
594-
595-
void clearCookies(@NonNull Result<Boolean> result);
596-
597-
void setCookie(@NonNull String url, @NonNull String value);
602+
/** Handles attaching `CookieManager.instance` to a native instance. */
603+
void attachInstance(@NonNull Long instanceIdentifier);
604+
/** Handles Dart method `CookieManager.setCookie`. */
605+
void setCookie(@NonNull Long identifier, @NonNull String url, @NonNull String value);
606+
/** Handles Dart method `CookieManager.removeAllCookies`. */
607+
void removeAllCookies(@NonNull Long identifier, @NonNull Result<Boolean> result);
608+
/** Handles Dart method `CookieManager.setAcceptThirdPartyCookies`. */
609+
void setAcceptThirdPartyCookies(
610+
@NonNull Long identifier, @NonNull Long webViewIdentifier, @NonNull Boolean accept);
598611

599612
/** The codec used by CookieManagerHostApi. */
600613
static @NonNull MessageCodec<Object> getCodec() {
@@ -610,12 +623,66 @@ static void setup(
610623
BasicMessageChannel<Object> channel =
611624
new BasicMessageChannel<>(
612625
binaryMessenger,
613-
"dev.flutter.pigeon.CookieManagerHostApi.clearCookies",
626+
"dev.flutter.pigeon.CookieManagerHostApi.attachInstance",
627+
getCodec());
628+
if (api != null) {
629+
channel.setMessageHandler(
630+
(message, reply) -> {
631+
ArrayList<Object> wrapped = new ArrayList<Object>();
632+
ArrayList<Object> args = (ArrayList<Object>) message;
633+
Number instanceIdentifierArg = (Number) args.get(0);
634+
try {
635+
api.attachInstance(
636+
(instanceIdentifierArg == null) ? null : instanceIdentifierArg.longValue());
637+
wrapped.add(0, null);
638+
} catch (Throwable exception) {
639+
ArrayList<Object> wrappedError = wrapError(exception);
640+
wrapped = wrappedError;
641+
}
642+
reply.reply(wrapped);
643+
});
644+
} else {
645+
channel.setMessageHandler(null);
646+
}
647+
}
648+
{
649+
BasicMessageChannel<Object> channel =
650+
new BasicMessageChannel<>(
651+
binaryMessenger, "dev.flutter.pigeon.CookieManagerHostApi.setCookie", getCodec());
652+
if (api != null) {
653+
channel.setMessageHandler(
654+
(message, reply) -> {
655+
ArrayList<Object> wrapped = new ArrayList<Object>();
656+
ArrayList<Object> args = (ArrayList<Object>) message;
657+
Number identifierArg = (Number) args.get(0);
658+
String urlArg = (String) args.get(1);
659+
String valueArg = (String) args.get(2);
660+
try {
661+
api.setCookie(
662+
(identifierArg == null) ? null : identifierArg.longValue(), urlArg, valueArg);
663+
wrapped.add(0, null);
664+
} catch (Throwable exception) {
665+
ArrayList<Object> wrappedError = wrapError(exception);
666+
wrapped = wrappedError;
667+
}
668+
reply.reply(wrapped);
669+
});
670+
} else {
671+
channel.setMessageHandler(null);
672+
}
673+
}
674+
{
675+
BasicMessageChannel<Object> channel =
676+
new BasicMessageChannel<>(
677+
binaryMessenger,
678+
"dev.flutter.pigeon.CookieManagerHostApi.removeAllCookies",
614679
getCodec());
615680
if (api != null) {
616681
channel.setMessageHandler(
617682
(message, reply) -> {
618683
ArrayList<Object> wrapped = new ArrayList<Object>();
684+
ArrayList<Object> args = (ArrayList<Object>) message;
685+
Number identifierArg = (Number) args.get(0);
619686
Result<Boolean> resultCallback =
620687
new Result<Boolean>() {
621688
public void success(Boolean result) {
@@ -629,7 +696,8 @@ public void error(Throwable error) {
629696
}
630697
};
631698

632-
api.clearCookies(resultCallback);
699+
api.removeAllCookies(
700+
(identifierArg == null) ? null : identifierArg.longValue(), resultCallback);
633701
});
634702
} else {
635703
channel.setMessageHandler(null);
@@ -638,16 +706,22 @@ public void error(Throwable error) {
638706
{
639707
BasicMessageChannel<Object> channel =
640708
new BasicMessageChannel<>(
641-
binaryMessenger, "dev.flutter.pigeon.CookieManagerHostApi.setCookie", getCodec());
709+
binaryMessenger,
710+
"dev.flutter.pigeon.CookieManagerHostApi.setAcceptThirdPartyCookies",
711+
getCodec());
642712
if (api != null) {
643713
channel.setMessageHandler(
644714
(message, reply) -> {
645715
ArrayList<Object> wrapped = new ArrayList<Object>();
646716
ArrayList<Object> args = (ArrayList<Object>) message;
647-
String urlArg = (String) args.get(0);
648-
String valueArg = (String) args.get(1);
717+
Number identifierArg = (Number) args.get(0);
718+
Number webViewIdentifierArg = (Number) args.get(1);
719+
Boolean acceptArg = (Boolean) args.get(2);
649720
try {
650-
api.setCookie(urlArg, valueArg);
721+
api.setAcceptThirdPartyCookies(
722+
(identifierArg == null) ? null : identifierArg.longValue(),
723+
(webViewIdentifierArg == null) ? null : webViewIdentifierArg.longValue(),
724+
acceptArg);
651725
wrapped.add(0, null);
652726
} catch (Throwable exception) {
653727
ArrayList<Object> wrappedError = wrapError(exception);

packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ private void setUp(
127127
instanceManager, new WebSettingsHostApiImpl.WebSettingsCreator()));
128128
FlutterAssetManagerHostApi.setup(
129129
binaryMessenger, new FlutterAssetManagerHostApiImpl(flutterAssetManager));
130-
CookieManagerHostApi.setup(binaryMessenger, new CookieManagerHostApiImpl());
130+
CookieManagerHostApi.setup(
131+
binaryMessenger, new CookieManagerHostApiImpl(binaryMessenger, instanceManager));
131132
WebStorageHostApi.setup(
132133
binaryMessenger,
133134
new WebStorageHostApiImpl(instanceManager, new WebStorageHostApiImpl.WebStorageCreator()));

packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/CookieManagerHostApiImplTest.java

Lines changed: 0 additions & 87 deletions
This file was deleted.

0 commit comments

Comments
 (0)