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

[webview_flutter_android] Fixes bug where a AndroidNavigationDelegate was required to load a request #6872

Merged
merged 5 commits into from
Dec 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.1.1

* Fixes bug where a `AndroidNavigationDelegate` was required to load a request.

## 3.1.0

* Adds support for selecting Hybrid Composition on versions 23+. Please use
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ public class WebChromeClientHostApiImpl implements WebChromeClientHostApi {
/**
* Implementation of {@link WebChromeClient} that passes arguments of callback methods to Dart.
*/
public static class WebChromeClientImpl extends WebChromeClient {
public static class WebChromeClientImpl extends SecureWebChromeClient {
private final WebChromeClientFlutterApiImpl flutterApi;
@Nullable private WebViewClient webViewClient;

/**
* Creates a {@link WebChromeClient} that passes arguments of callbacks methods to Dart.
Expand All @@ -42,6 +41,19 @@ public WebChromeClientImpl(@NonNull WebChromeClientFlutterApiImpl flutterApi) {
this.flutterApi = flutterApi;
}

@Override
public void onProgressChanged(WebView view, int progress) {
flutterApi.onProgressChanged(this, view, (long) progress, reply -> {});
}
}

/**
* Implementation of {@link WebChromeClient} that only allows secure urls when opening a new
* window.
*/
public static class SecureWebChromeClient extends WebChromeClient {
@Nullable private WebViewClient webViewClient;

@Override
public boolean onCreateWindow(
final WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
Expand Down Expand Up @@ -105,11 +117,6 @@ public boolean shouldOverrideUrlLoading(WebView windowWebView, String url) {
return true;
}

@Override
public void onProgressChanged(WebView view, int progress) {
flutterApi.onProgressChanged(this, view, (long) progress, reply -> {});
}

/**
* Set the {@link WebViewClient} that calls to {@link WebChromeClient#onCreateWindow} are passed
* to.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.WebViewHostApi;
import io.flutter.plugins.webviewflutter.WebChromeClientHostApiImpl.WebChromeClientImpl;
import java.util.Map;
import java.util.Objects;

Expand Down Expand Up @@ -80,7 +79,7 @@ public void setWebContentsDebuggingEnabled(boolean enabled) {
/** Implementation of {@link WebView} that can be used as a Flutter {@link PlatformView}s. */
public static class WebViewPlatformView extends WebView implements PlatformView {
private WebViewClient currentWebViewClient;
private WebChromeClientImpl currentWebChromeClient;
private WebChromeClientHostApiImpl.SecureWebChromeClient currentWebChromeClient;
Copy link
Contributor

Choose a reason for hiding this comment

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

Couldn't the type here just be WebChromeClient since it's only being accessed via overridden methods?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This could be set to WebChromeClient, but then the overridden methods would have to cast this value.


/**
* Creates a {@link WebViewPlatformView}.
Expand All @@ -91,9 +90,7 @@ public WebViewPlatformView(
Context context, BinaryMessenger binaryMessenger, InstanceManager instanceManager) {
super(context);
currentWebViewClient = new WebViewClient();
currentWebChromeClient =
new WebChromeClientImpl(
new WebChromeClientFlutterApiImpl(binaryMessenger, instanceManager));
currentWebChromeClient = new WebChromeClientHostApiImpl.SecureWebChromeClient();

setWebViewClient(currentWebViewClient);
setWebChromeClient(currentWebChromeClient);
Expand All @@ -119,12 +116,21 @@ public void setWebViewClient(WebViewClient webViewClient) {
@Override
public void setWebChromeClient(WebChromeClient client) {
super.setWebChromeClient(client);
if (!(client instanceof WebChromeClientImpl)) {
throw new AssertionError("Client must be a WebChromeClientImpl.");
if (!(client instanceof WebChromeClientHostApiImpl.SecureWebChromeClient)) {
throw new AssertionError("Client must be a SecureWebChromeClient.");
}
currentWebChromeClient = (WebChromeClientImpl) client;
currentWebChromeClient = (WebChromeClientHostApiImpl.SecureWebChromeClient) client;
currentWebChromeClient.setWebViewClient(currentWebViewClient);
}

// When running unit tests, the parent `WebView` class is replaced by a stub that returns null
// for every method. This is overridden so that this returns the current WebChromeClient during
// unit tests. This should only remain overridden as long as `setWebChromeClient` is overridden.
@Nullable
@Override
public WebChromeClient getWebChromeClient() {
return currentWebChromeClient;
}
}

/**
Expand All @@ -135,7 +141,7 @@ public void setWebChromeClient(WebChromeClient client) {
public static class InputAwareWebViewPlatformView extends InputAwareWebView
implements PlatformView {
private WebViewClient currentWebViewClient;
private WebChromeClientImpl currentWebChromeClient;
private WebChromeClientHostApiImpl.SecureWebChromeClient currentWebChromeClient;
Copy link
Contributor

Choose a reason for hiding this comment

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

Same.


/**
* Creates a {@link InputAwareWebViewPlatformView}.
Expand All @@ -149,9 +155,7 @@ public InputAwareWebViewPlatformView(
View containerView) {
super(context, containerView);
currentWebViewClient = new WebViewClient();
currentWebChromeClient =
new WebChromeClientImpl(
new WebChromeClientFlutterApiImpl(binaryMessenger, instanceManager));
currentWebChromeClient = new WebChromeClientHostApiImpl.SecureWebChromeClient();

setWebViewClient(currentWebViewClient);
setWebChromeClient(currentWebChromeClient);
Expand Down Expand Up @@ -198,10 +202,10 @@ public void setWebViewClient(WebViewClient webViewClient) {
@Override
public void setWebChromeClient(WebChromeClient client) {
super.setWebChromeClient(client);
if (!(client instanceof WebChromeClientImpl)) {
throw new AssertionError("Client must be a WebChromeClientImpl.");
if (!(client instanceof WebChromeClientHostApiImpl.SecureWebChromeClient)) {
throw new AssertionError("Client must be a SecureWebChromeClient.");
}
currentWebChromeClient = (WebChromeClientImpl) client;
currentWebChromeClient = (WebChromeClientHostApiImpl.SecureWebChromeClient) client;
currentWebChromeClient.setWebViewClient(currentWebViewClient);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
package io.flutter.plugins.webviewflutter;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
Expand All @@ -18,6 +20,7 @@
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugins.webviewflutter.WebViewHostApiImpl.WebViewPlatformView;
import java.util.HashMap;
import java.util.Objects;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
Expand Down Expand Up @@ -262,4 +265,20 @@ public void setWebChromeClient() {
testHostApiImpl.setWebChromeClient(0L, 1L);
verify(mockWebView).setWebChromeClient(mockWebChromeClient);
}

@Test
public void defaultWebChromeClientIsSecureWebChromeClient() {
final WebViewPlatformView webView = new WebViewPlatformView(mockContext, null, null);
assertTrue(
webView.getWebChromeClient() instanceof WebChromeClientHostApiImpl.SecureWebChromeClient);
assertFalse(
webView.getWebChromeClient() instanceof WebChromeClientHostApiImpl.WebChromeClientImpl);
}

@Test
public void defaultWebChromeClientDoesNotAttemptToCommunicateWithDart() {
final WebViewPlatformView webView = new WebViewPlatformView(mockContext, null, null);
// This shouldn't throw an Exception.
Objects.requireNonNull(webView.getWebChromeClient()).onProgressChanged(webView, 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: webview_flutter_android
description: A Flutter plugin that provides a WebView widget on Android.
repository: https://github.com/flutter/plugins/tree/main/packages/webview_flutter/webview_flutter_android
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
version: 3.1.0
version: 3.1.1

environment:
sdk: ">=2.17.0 <3.0.0"
Expand Down