Skip to content

Commit ae199f1

Browse files
Updated window.flutter_inappwebview.callHandler implementation: if there is an error/exception on Flutter/Dart side, the callHandler will reject the JavaScript promise with the error/exception message, so you can catch it also on JavaScript side, Fixed Android Web Storage Manager deleteAllData and deleteOrigin methods implementation, fix #1462, fix #1475
1 parent 0f1c7e3 commit ae199f1

File tree

71 files changed

+983
-644
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+983
-644
lines changed

CHANGELOG.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
## 6.0.0-beta.23
2+
3+
- Updated `androidx.webkit:webkit` dependency to `1.6.1`
4+
- Updated `androidx.browser:browser` dependency to `1.5.0`
5+
- Updated `androidx.appcompat:appcompat` dependency to `1.6.1`
6+
- Added support for Android `WebViewFeature.GET_COOKIE_INFO`
7+
- Added `requestedWithHeaderOriginAllowList` WebView setting for Android
8+
- Added `isInspectable`, `shouldPrintBackgrounds` WebView settings for iOS and macOS
9+
- Removed `WebViewFeature.REQUESTED_WITH_HEADER_CONTROL`, `ServiceWorkerController.setRequestedWithHeaderMode()`, `ServiceWorkerController.getRequestedWithHeaderMode()`, `InAppWebViewSettings.requestedWithHeaderMode`
10+
- Fixed "Build fail with AGP 8.0" [#1643](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1643)
11+
- Fixed "java.lang.RuntimeException: Unknown feature REQUESTED_WITH_HEADER_CONTROL" [#1611](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1611)
12+
- Fixed "iOS 16.4 WebDebugging WKWebView.isInspectable" [#1629](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1629)
13+
- Fixed some `@available` checks for macOS
14+
15+
## 6.0.0-beta.22
16+
17+
- Updated `window.flutter_inappwebview.callHandler` implementation: if there is an error/exception on Flutter/Dart side, the `callHandler` will reject the JavaScript promise with the error/exception message, so you can catch it also on JavaScript side
18+
- Fixed Android Web Storage Manager `deleteAllData` and `deleteOrigin` methods implementation
19+
- Fixed "Xiaomi store - Conflict of Privacy Permissions, android.permission.MY_READ_INSTALLED_PACKAGES" [#1462](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1462)
20+
- Fixed "Flutter 3.0.5 compilation issue" [#1475](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1475)
21+
122
## 6.0.0-beta.21
223

324
- Fixed "Android plugin version 6 - UserScripts not executing on new tabs." [#1455](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1455)
@@ -174,6 +195,10 @@
174195
- Removed `URLProtectionSpace.iosIsProxy` property
175196
- `historyUrl` and `baseUrl` of `InAppWebViewInitialData` can be `null`
176197

198+
## 5.7.2+3
199+
200+
- Fixed "Xiaomi store - Conflict of Privacy Permissions, android.permission.MY_READ_INSTALLED_PACKAGES" [#1462](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1462)
201+
177202
## 5.7.2+2
178203

179204
- Fixed "Unexpected addWebMessageListener behaviour" [#1422](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1422)

android/build.gradle

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ buildscript {
88
}
99

1010
dependencies {
11-
classpath 'com.android.tools.build:gradle:4.1.0'
11+
classpath 'com.android.tools.build:gradle:8.0.1'
1212
}
1313
}
1414

@@ -22,6 +22,10 @@ rootProject.allprojects {
2222
apply plugin: 'com.android.library'
2323

2424
android {
25+
// Conditional for compatibility with AGP <4.2.
26+
if (project.android.hasProperty("namespace")) {
27+
namespace 'com.pichillilorenzo.flutter_inappwebview'
28+
}
2529
compileSdkVersion 33
2630

2731
defaultConfig {
@@ -45,9 +49,9 @@ android {
4549
}
4650
}
4751
dependencies {
48-
implementation 'androidx.webkit:webkit:1.5.0'
49-
implementation 'androidx.browser:browser:1.4.0'
50-
implementation 'androidx.appcompat:appcompat:1.5.1'
52+
implementation 'androidx.webkit:webkit:1.6.1'
53+
implementation 'androidx.browser:browser:1.5.0'
54+
implementation 'androidx.appcompat:appcompat:1.6.1'
5155
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
5256
}
5357
}

android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyCookieManager.java

Lines changed: 86 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
package com.pichillilorenzo.flutter_inappwebview;
22

33
import android.os.Build;
4+
import android.util.Log;
45
import android.webkit.CookieManager;
56
import android.webkit.CookieSyncManager;
67
import android.webkit.ValueCallback;
78

89
import androidx.annotation.NonNull;
910
import androidx.annotation.Nullable;
11+
import androidx.webkit.CookieManagerCompat;
12+
import androidx.webkit.WebViewFeature;
1013

1114
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
1215

16+
import java.text.DateFormat;
17+
import java.text.ParseException;
1318
import java.text.SimpleDateFormat;
1419
import java.util.ArrayList;
20+
import java.util.Arrays;
21+
import java.util.Collections;
1522
import java.util.Date;
1623
import java.util.HashMap;
1724
import java.util.List;
@@ -30,14 +37,21 @@ public class MyCookieManager extends ChannelDelegateImpl {
3037
@Nullable
3138
public InAppWebViewFlutterPlugin plugin;
3239

33-
public MyCookieManager(final InAppWebViewFlutterPlugin plugin) {
40+
public MyCookieManager(@NonNull final InAppWebViewFlutterPlugin plugin) {
3441
super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME));
3542
this.plugin = plugin;
36-
cookieManager = getCookieManager();
43+
}
44+
45+
public static void init() {
46+
if (cookieManager == null) {
47+
cookieManager = getCookieManager();
48+
}
3749
}
3850

3951
@Override
4052
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
53+
init();
54+
4155
switch (call.method) {
4256
case "setCookie":
4357
{
@@ -192,27 +206,78 @@ public List<Map<String, Object>> getCookies(final String url) {
192206
cookieManager = getCookieManager();
193207
if (cookieManager == null) return cookieListMap;
194208

195-
String cookiesString = cookieManager.getCookie(url);
209+
List<String> cookies = new ArrayList<>();
210+
if (WebViewFeature.isFeatureSupported(WebViewFeature.GET_COOKIE_INFO)) {
211+
cookies = CookieManagerCompat.getCookieInfo(cookieManager, url);
212+
} else {
213+
String cookiesString = cookieManager.getCookie(url);
214+
if (cookiesString != null) {
215+
cookies = Arrays.asList(cookiesString.split(";"));
216+
}
217+
}
196218

197-
if (cookiesString != null) {
198-
String[] cookies = cookiesString.split(";");
199-
for (String cookie : cookies) {
200-
String[] nameValue = cookie.split("=", 2);
201-
String name = nameValue[0].trim();
202-
String value = (nameValue.length > 1) ? nameValue[1].trim() : "";
203-
Map<String, Object> cookieMap = new HashMap<>();
204-
cookieMap.put("name", name);
205-
cookieMap.put("value", value);
206-
cookieMap.put("expiresDate", null);
207-
cookieMap.put("isSessionOnly", null);
208-
cookieMap.put("domain", null);
209-
cookieMap.put("sameSite", null);
210-
cookieMap.put("isSecure", null);
211-
cookieMap.put("isHttpOnly", null);
212-
cookieMap.put("path", null);
213-
214-
cookieListMap.add(cookieMap);
219+
for (String cookie : cookies) {
220+
String[] cookieParams = cookie.split(";");
221+
if (cookieParams.length == 0) continue;
222+
223+
String[] nameValue = cookieParams[0].split("=", 2);
224+
String name = nameValue[0].trim();
225+
String value = (nameValue.length > 1) ? nameValue[1].trim() : "";
226+
227+
Map<String, Object> cookieMap = new HashMap<>();
228+
cookieMap.put("name", name);
229+
cookieMap.put("value", value);
230+
cookieMap.put("expiresDate", null);
231+
cookieMap.put("isSessionOnly", null);
232+
cookieMap.put("domain", null);
233+
cookieMap.put("sameSite", null);
234+
cookieMap.put("isSecure", null);
235+
cookieMap.put("isHttpOnly", null);
236+
cookieMap.put("path", null);
237+
238+
if (WebViewFeature.isFeatureSupported(WebViewFeature.GET_COOKIE_INFO)) {
239+
cookieMap.put("isSecure", false);
240+
cookieMap.put("isHttpOnly", false);
241+
242+
for (int i = 1; i < cookieParams.length; i++) {
243+
String[] cookieParamNameValue = cookieParams[i].split("=", 2);
244+
String cookieParamName = cookieParamNameValue[0].trim();
245+
String cookieParamValue = (cookieParamNameValue.length > 1) ? cookieParamNameValue[1].trim() : "";
246+
247+
if (cookieParamName.equalsIgnoreCase("Expires")) {
248+
try {
249+
final SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss z", Locale.US);
250+
Date expiryDate = sdf.parse(cookieParamValue);
251+
if (expiryDate != null) {
252+
cookieMap.put("expiresDate", expiryDate.getTime());
253+
}
254+
} catch (ParseException e) {
255+
e.printStackTrace();
256+
Log.e(LOG_TAG, e.getMessage());
257+
}
258+
} else if (cookieParamName.equalsIgnoreCase("Max-Age")) {
259+
try {
260+
long maxAge = Long.parseLong(cookieParamValue);
261+
cookieMap.put("expiresDate", System.currentTimeMillis() + maxAge);
262+
} catch (NumberFormatException e) {
263+
e.printStackTrace();
264+
Log.e(LOG_TAG, e.getMessage());
265+
}
266+
} else if (cookieParamName.equalsIgnoreCase("Domain")) {
267+
cookieMap.put("domain", cookieParamValue);
268+
} else if (cookieParamName.equalsIgnoreCase("SameSite")) {
269+
cookieMap.put("sameSite", cookieParamValue);
270+
} else if (cookieParamName.equalsIgnoreCase("Secure")) {
271+
cookieMap.put("isSecure", true);
272+
} else if (cookieParamName.equalsIgnoreCase("HttpOnly")) {
273+
cookieMap.put("isHttpOnly", true);
274+
} else if (cookieParamName.equalsIgnoreCase("Path")) {
275+
cookieMap.put("path", cookieParamValue);
276+
}
277+
}
215278
}
279+
280+
cookieListMap.add(cookieMap);
216281
}
217282
return cookieListMap;
218283

android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyWebStorage.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,27 @@ public class MyWebStorage extends ChannelDelegateImpl {
2525
@Nullable
2626
public InAppWebViewFlutterPlugin plugin;
2727

28-
public MyWebStorage(final InAppWebViewFlutterPlugin plugin) {
28+
public MyWebStorage(@NonNull final InAppWebViewFlutterPlugin plugin) {
2929
super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME));
3030
this.plugin = plugin;
31-
webStorageManager = WebStorage.getInstance();
31+
}
32+
33+
public static void init() {
34+
if (webStorageManager == null) {
35+
webStorageManager = WebStorage.getInstance();
36+
}
3237
}
3338

3439
@Override
3540
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
41+
init();
42+
3643
switch (call.method) {
3744
case "getOrigins":
3845
getOrigins(result);
3946
break;
4047
case "deleteAllData":
41-
if (webStorageManager == null) {
48+
if (webStorageManager != null) {
4249
webStorageManager.deleteAllData();
4350
result.success(true);
4451
} else {
@@ -47,7 +54,7 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
4754
break;
4855
case "deleteOrigin":
4956
{
50-
if (webStorageManager == null) {
57+
if (webStorageManager != null) {
5158
String origin = (String) call.argument("origin");
5259
webStorageManager.deleteOrigin(origin);
5360
result.success(true);

android/src/main/java/com/pichillilorenzo/flutter_inappwebview/WebViewFeatureManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class WebViewFeatureManager extends ChannelDelegateImpl {
1616
@Nullable
1717
public InAppWebViewFlutterPlugin plugin;
1818

19-
public WebViewFeatureManager(final InAppWebViewFlutterPlugin plugin) {
19+
public WebViewFeatureManager(@NonNull final InAppWebViewFlutterPlugin plugin) {
2020
super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME));
2121
this.plugin = plugin;
2222
}

android/src/main/java/com/pichillilorenzo/flutter_inappwebview/credential_database/CredentialDatabaseHandler.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,23 @@ public class CredentialDatabaseHandler extends ChannelDelegateImpl {
3030
@Nullable
3131
public InAppWebViewFlutterPlugin plugin;
3232

33-
public CredentialDatabaseHandler(final InAppWebViewFlutterPlugin plugin) {
33+
public CredentialDatabaseHandler(@NonNull final InAppWebViewFlutterPlugin plugin) {
3434
super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME));
3535
this.plugin = plugin;
36-
credentialDatabase = CredentialDatabase.getInstance(plugin.applicationContext);
36+
}
37+
38+
public static void init(@NonNull InAppWebViewFlutterPlugin plugin) {
39+
if (credentialDatabase == null) {
40+
credentialDatabase = CredentialDatabase.getInstance(plugin.applicationContext);
41+
}
3742
}
3843

3944
@Override
4045
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
46+
if (plugin != null) {
47+
init(plugin);
48+
}
49+
4150
switch (call.method) {
4251
case "getAllAuthCredentials":
4352
{

android/src/main/java/com/pichillilorenzo/flutter_inappwebview/plugin_scripts_js/JavaScriptBridgeJS.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ public class JavaScriptBridgeJS {
220220
" var _callHandlerID = setTimeout(function(){});" +
221221
" window." + JAVASCRIPT_BRIDGE_NAME + "._callHandler(arguments[0], _callHandlerID, JSON.stringify(Array.prototype.slice.call(arguments, 1)));" +
222222
" return new Promise(function(resolve, reject) {" +
223-
" window." + JAVASCRIPT_BRIDGE_NAME + "[_callHandlerID] = resolve;" +
223+
" window." + JAVASCRIPT_BRIDGE_NAME + "[_callHandlerID] = {resolve: resolve, reject: reject};" +
224224
" });" +
225225
" };" +
226226
" }"+
@@ -230,7 +230,7 @@ public class JavaScriptBridgeJS {
230230
" var _callHandlerID = setTimeout(function(){});" +
231231
" window.top." + JAVASCRIPT_BRIDGE_NAME + "._callHandler(arguments[0], _callHandlerID, JSON.stringify(Array.prototype.slice.call(arguments, 1)));" +
232232
" return new Promise(function(resolve, reject) {" +
233-
" window.top." + JAVASCRIPT_BRIDGE_NAME + "[_callHandlerID] = resolve;" +
233+
" window.top." + JAVASCRIPT_BRIDGE_NAME + "[_callHandlerID] = {resolve: resolve, reject: reject};" +
234234
" });" +
235235
" };" +
236236
"}" +

android/src/main/java/com/pichillilorenzo/flutter_inappwebview/proxy/ProxyManager.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,22 @@ public class ProxyManager extends ChannelDelegateImpl {
2525
@Nullable
2626
public InAppWebViewFlutterPlugin plugin;
2727

28-
public ProxyManager(final InAppWebViewFlutterPlugin plugin) {
28+
public ProxyManager(@NonNull final InAppWebViewFlutterPlugin plugin) {
2929
super(new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME));
3030
this.plugin = plugin;
31-
if (WebViewFeature.isFeatureSupported(WebViewFeature.PROXY_OVERRIDE)) {
31+
}
32+
33+
public static void init() {
34+
if (proxyController == null &&
35+
WebViewFeature.isFeatureSupported(WebViewFeature.PROXY_OVERRIDE)) {
3236
proxyController = ProxyController.getInstance();
33-
} else {
34-
proxyController = null;
3537
}
3638
}
3739

3840
@Override
3941
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
42+
init();
43+
4044
switch (call.method) {
4145
case "setProxyOverride":
4246
if (proxyController != null) {

android/src/main/java/com/pichillilorenzo/flutter_inappwebview/service_worker/ServiceWorkerChannelDelegate.java

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.pichillilorenzo.flutter_inappwebview.service_worker;
22

3-
import android.annotation.SuppressLint;
43
import android.os.Build;
54

65
import androidx.annotation.NonNull;
@@ -16,7 +15,6 @@
1615
import com.pichillilorenzo.flutter_inappwebview.types.SyncBaseCallbackResultImpl;
1716
import com.pichillilorenzo.flutter_inappwebview.types.WebResourceRequestExt;
1817
import com.pichillilorenzo.flutter_inappwebview.types.WebResourceResponseExt;
19-
import com.pichillilorenzo.flutter_inappwebview.webview.WebViewChannelDelegate;
2018

2119
import java.util.Map;
2220

@@ -33,9 +31,9 @@ public ServiceWorkerChannelDelegate(@NonNull ServiceWorkerManager serviceWorkerM
3331
this.serviceWorkerManager = serviceWorkerManager;
3432
}
3533

36-
@SuppressLint("RestrictedApi")
3734
@Override
3835
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
36+
ServiceWorkerManager.init();
3937
ServiceWorkerControllerCompat serviceWorkerController = ServiceWorkerManager.serviceWorkerController;
4038
ServiceWorkerWebSettingsCompat serviceWorkerWebSettings = (serviceWorkerController != null) ?
4139
serviceWorkerController.getServiceWorkerWebSettings() : null;
@@ -71,13 +69,6 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
7169
result.success(false);
7270
}
7371
break;
74-
case "getRequestedWithHeaderMode":
75-
if (serviceWorkerWebSettings != null && WebViewFeature.isFeatureSupported(WebViewFeature.REQUESTED_WITH_HEADER_CONTROL)) {
76-
result.success(serviceWorkerWebSettings.getRequestedWithHeaderMode());
77-
} else {
78-
result.success(null);
79-
}
80-
break;
8172
case "getCacheMode":
8273
if (serviceWorkerWebSettings != null && WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_CACHE_MODE)) {
8374
result.success(serviceWorkerWebSettings.getCacheMode());
@@ -113,13 +104,6 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
113104
}
114105
result.success(true);
115106
break;
116-
case "setRequestedWithHeaderMode":
117-
if (serviceWorkerWebSettings != null && WebViewFeature.isFeatureSupported(WebViewFeature.REQUESTED_WITH_HEADER_CONTROL)) {
118-
Integer mode = (Integer) call.argument("mode");
119-
serviceWorkerWebSettings.setRequestedWithHeaderMode(mode);
120-
}
121-
result.success(true);
122-
break;
123107
default:
124108
result.notImplemented();
125109
}

0 commit comments

Comments
 (0)