From cf619d047f9a80b44b09867433df9eca7a32b9e3 Mon Sep 17 00:00:00 2001 From: Peter Menten Date: Fri, 15 Mar 2024 12:30:52 +0100 Subject: [PATCH 1/4] Fixes iframe navigation being handled in the main frame when `NavigationDelegate.onNavigationRequest` is present. --- .../webview_flutter_android/CHANGELOG.md | 4 ++ .../WebViewClientHostApiImpl.java | 16 ++++- .../WebViewClientCompatImplTest.java | 21 +++++++ .../webviewflutter/WebViewClientImplTest.java | 21 +++++++ .../webviewflutter/WebViewClientTest.java | 62 ++++++++++++++++++- .../example/lib/main.dart | 4 +- .../webview_flutter_android/pubspec.yaml | 2 +- 7 files changed, 122 insertions(+), 8 deletions(-) create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientImplTest.java diff --git a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md index 44f60d72f469..3e43076fd40e 100644 --- a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.16.1 + +* Fixes iframe navigation being handled in the main frame when `NavigationDelegate.onNavigationRequest` is present. + ## 3.16.0 * Adds onReceivedHttpError WebViewClient callback to support diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java index a2ed499629cb..2d3dbd37f943 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java @@ -88,7 +88,13 @@ public void onReceivedError( public boolean shouldOverrideUrlLoading( @NonNull WebView view, @NonNull WebResourceRequest request) { flutterApi.requestLoading(this, view, request, reply -> {}); - return returnValueForShouldOverrideUrlLoading; + + // Since we cannot call loadUrl for a subframe, we currently only allow the delegate to stop + // navigations that target the main frame, if the request is not for the main frame + // we just return false to allow the navigation. + // + // For more details see: https://github.com/flutter/flutter/issues/25329#issuecomment-464863209 + return request.isForMainFrame() && returnValueForShouldOverrideUrlLoading; } // Legacy codepath for < 24; newer versions use the variant above. @@ -187,7 +193,13 @@ public void onReceivedError( public boolean shouldOverrideUrlLoading( @NonNull WebView view, @NonNull WebResourceRequest request) { flutterApi.requestLoading(this, view, request, reply -> {}); - return returnValueForShouldOverrideUrlLoading; + + // Since we cannot call loadUrl for a subframe, we currently only allow the delegate to stop + // navigations that target the main frame, if the request is not for the main frame + // we just return false to allow the navigation. + // + // For more details see: https://github.com/flutter/flutter/issues/25329#issuecomment-464863209 + return request.isForMainFrame() && returnValueForShouldOverrideUrlLoading; } // Legacy codepath for < Lollipop; newer versions use the variant above. diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java new file mode 100644 index 000000000000..f4cfd0481876 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java @@ -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. + +package io.flutter.plugins.webviewflutter; + +import android.webkit.WebViewClient; + +public class WebViewClientCompatImplTest extends WebViewClientTest { + + @Override + WebViewClient createInstance(WebViewClientFlutterApiImpl flutterApi) { + return new WebViewClientHostApiImpl.WebViewClientCompatImpl(flutterApi); + } + + @Override + void setReturnValueForShouldOverrideUrlLoading(WebViewClient client, boolean value) { + ((WebViewClientHostApiImpl.WebViewClientCompatImpl) client) + .setReturnValueForShouldOverrideUrlLoading(value); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientImplTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientImplTest.java new file mode 100644 index 000000000000..e099a686648e --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientImplTest.java @@ -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. + +package io.flutter.plugins.webviewflutter; + +import android.webkit.WebViewClient; + +public class WebViewClientImplTest extends WebViewClientTest { + + @Override + WebViewClient createInstance(WebViewClientFlutterApiImpl flutterApi) { + return new WebViewClientHostApiImpl.WebViewClientImpl(flutterApi); + } + + @Override + void setReturnValueForShouldOverrideUrlLoading(WebViewClient client, boolean value) { + ((WebViewClientHostApiImpl.WebViewClientImpl) client) + .setReturnValueForShouldOverrideUrlLoading(value); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java index ea40742465f2..cf34c6b62c6a 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java @@ -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.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -28,7 +30,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -public class WebViewClientTest { +public abstract class WebViewClientTest { @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock public WebViewClientFlutterApiImpl mockFlutterApi; @@ -39,7 +41,11 @@ public class WebViewClientTest { InstanceManager instanceManager; WebViewClientHostApiImpl hostApiImpl; - WebViewClientCompatImpl webViewClient; + WebViewClient webViewClient; + + abstract WebViewClient createInstance(WebViewClientFlutterApiImpl flutterApi); + + abstract void setReturnValueForShouldOverrideUrlLoading(WebViewClient client, boolean value); @Before public void setUp() { @@ -51,7 +57,7 @@ public void setUp() { @NonNull public WebViewClient createWebViewClient( @NonNull WebViewClientFlutterApiImpl flutterApi) { - webViewClient = (WebViewClientCompatImpl) super.createWebViewClient(flutterApi); + webViewClient = createInstance(flutterApi); return webViewClient; } }; @@ -74,6 +80,7 @@ public void onPageStarted() { } @Test + @SuppressWarnings("deprecation") public void onReceivedError() { webViewClient.onReceivedError(mockWebView, 32, "description", "https://www.google.com"); verify(mockFlutterApi) @@ -87,12 +94,61 @@ public void onReceivedError() { } @Test + @SuppressWarnings("deprecation") public void urlLoading() { webViewClient.shouldOverrideUrlLoading(mockWebView, "https://www.google.com"); verify(mockFlutterApi) .urlLoading(eq(webViewClient), eq(mockWebView), eq("https://www.google.com"), any()); } + @Test + public void urlLoadingForMainFrame() { + setReturnValueForShouldOverrideUrlLoading(webViewClient, false); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.isForMainFrame()).thenReturn(true); + + assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); + verify(mockFlutterApi) + .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); + } + + @Test + public void urlLoadingForMainFrameWithOverride() { + setReturnValueForShouldOverrideUrlLoading(webViewClient, true); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.isForMainFrame()).thenReturn(true); + + assertTrue(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); + verify(mockFlutterApi) + .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); + } + + @Test + public void urlLoadingNotForMainFrame() { + setReturnValueForShouldOverrideUrlLoading(webViewClient, false); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.isForMainFrame()).thenReturn(false); + + assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); + verify(mockFlutterApi) + .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); + } + + @Test + public void urlLoadingNotForMainFrameWithOverride() { + setReturnValueForShouldOverrideUrlLoading(webViewClient, true); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.isForMainFrame()).thenReturn(false); + + assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); + verify(mockFlutterApi) + .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); + } + @Test public void convertWebResourceRequestWithNullHeaders() { final Uri mockUri = mock(Uri.class); diff --git a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart index 0f2972f23ef1..490e3d44f7ab 100644 --- a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart @@ -23,10 +23,10 @@ const String kNavigationExamplePage = ''' Navigation Delegate Example

-The navigation delegate is set to block navigation to the youtube website. +The navigation delegate is set to block navigation to the pub.dev website.

diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml index 01add9158426..524ce4209a03 100644 --- a/packages/webview_flutter/webview_flutter_android/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_android description: A Flutter plugin that provides a WebView widget on Android. repository: https://github.com/flutter/packages/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.16.0 +version: 3.16.1 environment: sdk: ^3.1.0 From 361c19db5d1c8985091b18b9a7d42519ab98854c Mon Sep 17 00:00:00 2001 From: Peter Menten Date: Thu, 21 Mar 2024 21:19:54 +0100 Subject: [PATCH 2/4] Don't send the request to the flutter api for subframes. Also improve tests and comments --- .../WebViewClientHostApiImpl.java | 28 +-- .../WebViewClientCompatImplTest.java | 208 +++++++++++++++++- .../webviewflutter/WebViewClientImplTest.java | 184 +++++++++++++++- .../webviewflutter/WebViewClientTest.java | 151 +------------ 4 files changed, 394 insertions(+), 177 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java index 2d3dbd37f943..afccf41481d5 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java @@ -87,14 +87,14 @@ public void onReceivedError( @Override public boolean shouldOverrideUrlLoading( @NonNull WebView view, @NonNull WebResourceRequest request) { - flutterApi.requestLoading(this, view, request, reply -> {}); + if (!request.isForMainFrame()) { + // The client is only allowed to stop navigations that target the main frame because + // overridden URLs are passed to `loadUrl` and `loadUrl` cannot load a subframe. + return false; + } - // Since we cannot call loadUrl for a subframe, we currently only allow the delegate to stop - // navigations that target the main frame, if the request is not for the main frame - // we just return false to allow the navigation. - // - // For more details see: https://github.com/flutter/flutter/issues/25329#issuecomment-464863209 - return request.isForMainFrame() && returnValueForShouldOverrideUrlLoading; + flutterApi.requestLoading(this, view, request, reply -> {}); + return returnValueForShouldOverrideUrlLoading; } // Legacy codepath for < 24; newer versions use the variant above. @@ -192,14 +192,14 @@ public void onReceivedError( @Override public boolean shouldOverrideUrlLoading( @NonNull WebView view, @NonNull WebResourceRequest request) { - flutterApi.requestLoading(this, view, request, reply -> {}); + if (!request.isForMainFrame()) { + // The client is only allowed to stop navigations that target the main frame because + // overridden URLs are passed to `loadUrl` and `loadUrl` cannot load a subframe. + return false; + } - // Since we cannot call loadUrl for a subframe, we currently only allow the delegate to stop - // navigations that target the main frame, if the request is not for the main frame - // we just return false to allow the navigation. - // - // For more details see: https://github.com/flutter/flutter/issues/25329#issuecomment-464863209 - return request.isForMainFrame() && returnValueForShouldOverrideUrlLoading; + flutterApi.requestLoading(this, view, request, reply -> {}); + return returnValueForShouldOverrideUrlLoading; } // Legacy codepath for < Lollipop; newer versions use the variant above. diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java index f4cfd0481876..d3849274fbba 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java @@ -4,18 +4,210 @@ 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.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +import android.net.Uri; +import android.webkit.WebResourceRequest; +import android.webkit.WebResourceResponse; +import android.webkit.WebView; import android.webkit.WebViewClient; +import androidx.annotation.NonNull; +import io.flutter.plugins.webviewflutter.WebViewClientHostApiImpl.WebViewClientCompatImpl; +import io.flutter.plugins.webviewflutter.WebViewClientHostApiImpl.WebViewClientCreator; +import java.util.HashMap; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +public class WebViewClientCompatImplTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock public WebViewClientFlutterApiImpl mockFlutterApi; + + @Mock public WebView mockWebView; + + @Mock public WebViewClientCompatImpl mockWebViewClient; + + InstanceManager instanceManager; + WebViewClientHostApiImpl hostApiImpl; + WebViewClientCompatImpl webViewClient; + + @Before + public void setUp() { + instanceManager = InstanceManager.create(identifier -> {}); + + final WebViewClientCreator webViewClientCreator = + new WebViewClientCreator() { + @Override + @NonNull + public WebViewClient createWebViewClient( + @NonNull WebViewClientFlutterApiImpl flutterApi) { + webViewClient = new WebViewClientCompatImpl(flutterApi); + return webViewClient; + } + }; + + hostApiImpl = + new WebViewClientHostApiImpl(instanceManager, webViewClientCreator, mockFlutterApi); + hostApiImpl.create(1L); + } + + @After + public void tearDown() { + instanceManager.stopFinalizationListener(); + } + + @Test + public void onPageStarted() { + webViewClient.onPageStarted(mockWebView, "https://www.google.com", null); + verify(mockFlutterApi) + .onPageStarted(eq(webViewClient), eq(mockWebView), eq("https://www.google.com"), any()); + } + + @Test + public void onReceivedError() { + webViewClient.onReceivedError(mockWebView, 32, "description", "https://www.google.com"); + verify(mockFlutterApi) + .onReceivedError( + eq(webViewClient), + eq(mockWebView), + eq(32L), + eq("description"), + eq("https://www.google.com"), + any()); + } + + @Test + public void urlLoading() { + webViewClient.shouldOverrideUrlLoading(mockWebView, "https://www.google.com"); + verify(mockFlutterApi) + .urlLoading(eq(webViewClient), eq(mockWebView), eq("https://www.google.com"), any()); + } + + @Test + public void urlLoadingForMainFrame() { + webViewClient.setReturnValueForShouldOverrideUrlLoading(false); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.isForMainFrame()).thenReturn(true); + + assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); + verify(mockFlutterApi) + .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); + } -public class WebViewClientCompatImplTest extends WebViewClientTest { + @Test + public void urlLoadingForMainFrameWithOverride() { + webViewClient.setReturnValueForShouldOverrideUrlLoading(true); - @Override - WebViewClient createInstance(WebViewClientFlutterApiImpl flutterApi) { - return new WebViewClientHostApiImpl.WebViewClientCompatImpl(flutterApi); + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.isForMainFrame()).thenReturn(true); + + assertTrue(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); + verify(mockFlutterApi) + .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); + } + + @Test + public void urlLoadingNotForMainFrame() { + webViewClient.setReturnValueForShouldOverrideUrlLoading(false); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.isForMainFrame()).thenReturn(false); + + assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); + verifyNoInteractions(mockFlutterApi); + } + + @Test + public void urlLoadingNotForMainFrameWithOverride() { + webViewClient.setReturnValueForShouldOverrideUrlLoading(true); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.isForMainFrame()).thenReturn(false); + + assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); + verifyNoInteractions(mockFlutterApi); + } + + @Test + public void convertWebResourceRequestWithNullHeaders() { + final Uri mockUri = mock(Uri.class); + when(mockUri.toString()).thenReturn(""); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.getMethod()).thenReturn("method"); + when(mockRequest.getUrl()).thenReturn(mockUri); + when(mockRequest.isForMainFrame()).thenReturn(true); + when(mockRequest.getRequestHeaders()).thenReturn(null); + + final GeneratedAndroidWebView.WebResourceRequestData data = + WebViewClientFlutterApiImpl.createWebResourceRequestData(mockRequest); + assertEquals(data.getRequestHeaders(), new HashMap()); + } + + @Test + public void setReturnValueForShouldOverrideUrlLoading() { + final WebViewClientHostApiImpl webViewClientHostApi = + new WebViewClientHostApiImpl( + instanceManager, + new WebViewClientCreator() { + @NonNull + @Override + public WebViewClient createWebViewClient( + @NonNull WebViewClientFlutterApiImpl flutterApi) { + return mockWebViewClient; + } + }, + mockFlutterApi); + + instanceManager.addDartCreatedInstance(mockWebViewClient, 2); + webViewClientHostApi.setSynchronousReturnValueForShouldOverrideUrlLoading(2L, false); + + verify(mockWebViewClient).setReturnValueForShouldOverrideUrlLoading(false); } - @Override - void setReturnValueForShouldOverrideUrlLoading(WebViewClient client, boolean value) { - ((WebViewClientHostApiImpl.WebViewClientCompatImpl) client) - .setReturnValueForShouldOverrideUrlLoading(value); + @Test + public void doUpdateVisitedHistory() { + webViewClient.doUpdateVisitedHistory(mockWebView, "https://www.google.com", true); + verify(mockFlutterApi) + .doUpdateVisitedHistory( + eq(webViewClient), eq(mockWebView), eq("https://www.google.com"), eq(true), any()); + } + + @Test + public void onReceivedHttpError() { + final Uri mockUri = mock(Uri.class); + when(mockUri.toString()).thenReturn(""); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.getMethod()).thenReturn("method"); + when(mockRequest.getUrl()).thenReturn(mockUri); + when(mockRequest.isForMainFrame()).thenReturn(true); + when(mockRequest.getRequestHeaders()).thenReturn(null); + + final WebResourceResponse mockResponse = mock(WebResourceResponse.class); + when(mockResponse.getStatusCode()).thenReturn(404); + + webViewClient.onReceivedHttpError(mockWebView, mockRequest, mockResponse); + verify(mockFlutterApi) + .onReceivedHttpError( + eq(webViewClient), + eq(mockWebView), + any(WebResourceRequest.class), + any(WebResourceResponse.class), + any()); } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientImplTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientImplTest.java index e099a686648e..492caf4874c7 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientImplTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientImplTest.java @@ -4,18 +4,186 @@ 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.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +import android.net.Uri; +import android.webkit.WebResourceRequest; +import android.webkit.WebResourceResponse; +import android.webkit.WebView; import android.webkit.WebViewClient; +import androidx.annotation.NonNull; +import io.flutter.plugins.webviewflutter.WebViewClientHostApiImpl.WebViewClientCreator; +import java.util.HashMap; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +public class WebViewClientImplTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock public WebViewClientFlutterApiImpl mockFlutterApi; + + @Mock public WebView mockWebView; + + InstanceManager instanceManager; + WebViewClientHostApiImpl hostApiImpl; + WebViewClientHostApiImpl.WebViewClientImpl webViewClient; + + @Before + public void setUp() { + instanceManager = InstanceManager.create(identifier -> {}); + + final WebViewClientCreator webViewClientCreator = + new WebViewClientCreator() { + @Override + @NonNull + public WebViewClient createWebViewClient( + @NonNull WebViewClientFlutterApiImpl flutterApi) { + webViewClient = new WebViewClientHostApiImpl.WebViewClientImpl(flutterApi); + return webViewClient; + } + }; + + hostApiImpl = + new WebViewClientHostApiImpl(instanceManager, webViewClientCreator, mockFlutterApi); + hostApiImpl.create(1L); + } + + @After + public void tearDown() { + instanceManager.stopFinalizationListener(); + } + + @Test + public void onPageStarted() { + webViewClient.onPageStarted(mockWebView, "https://www.google.com", null); + verify(mockFlutterApi) + .onPageStarted(eq(webViewClient), eq(mockWebView), eq("https://www.google.com"), any()); + } + + @Test + public void onReceivedError() { + webViewClient.onReceivedError(mockWebView, 32, "description", "https://www.google.com"); + verify(mockFlutterApi) + .onReceivedError( + eq(webViewClient), + eq(mockWebView), + eq(32L), + eq("description"), + eq("https://www.google.com"), + any()); + } -public class WebViewClientImplTest extends WebViewClientTest { + @Test + public void urlLoading() { + webViewClient.shouldOverrideUrlLoading(mockWebView, "https://www.google.com"); + verify(mockFlutterApi) + .urlLoading(eq(webViewClient), eq(mockWebView), eq("https://www.google.com"), any()); + } + + @Test + public void urlLoadingForMainFrame() { + webViewClient.setReturnValueForShouldOverrideUrlLoading(false); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.isForMainFrame()).thenReturn(true); - @Override - WebViewClient createInstance(WebViewClientFlutterApiImpl flutterApi) { - return new WebViewClientHostApiImpl.WebViewClientImpl(flutterApi); + assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); + verify(mockFlutterApi) + .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); } - @Override - void setReturnValueForShouldOverrideUrlLoading(WebViewClient client, boolean value) { - ((WebViewClientHostApiImpl.WebViewClientImpl) client) - .setReturnValueForShouldOverrideUrlLoading(value); + @Test + public void urlLoadingForMainFrameWithOverride() { + webViewClient.setReturnValueForShouldOverrideUrlLoading(true); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.isForMainFrame()).thenReturn(true); + + assertTrue(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); + verify(mockFlutterApi) + .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); + } + + @Test + public void urlLoadingNotForMainFrame() { + webViewClient.setReturnValueForShouldOverrideUrlLoading(false); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.isForMainFrame()).thenReturn(false); + + assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); + verifyNoInteractions(mockFlutterApi); + } + + @Test + public void urlLoadingNotForMainFrameWithOverride() { + webViewClient.setReturnValueForShouldOverrideUrlLoading(true); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.isForMainFrame()).thenReturn(false); + + assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); + verifyNoInteractions(mockFlutterApi); + } + + @Test + public void convertWebResourceRequestWithNullHeaders() { + final Uri mockUri = mock(Uri.class); + when(mockUri.toString()).thenReturn(""); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.getMethod()).thenReturn("method"); + when(mockRequest.getUrl()).thenReturn(mockUri); + when(mockRequest.isForMainFrame()).thenReturn(true); + when(mockRequest.getRequestHeaders()).thenReturn(null); + + final GeneratedAndroidWebView.WebResourceRequestData data = + WebViewClientFlutterApiImpl.createWebResourceRequestData(mockRequest); + assertEquals(data.getRequestHeaders(), new HashMap()); + } + + @Test + public void doUpdateVisitedHistory() { + webViewClient.doUpdateVisitedHistory(mockWebView, "https://www.google.com", true); + verify(mockFlutterApi) + .doUpdateVisitedHistory( + eq(webViewClient), eq(mockWebView), eq("https://www.google.com"), eq(true), any()); + } + + @Test + public void onReceivedHttpError() { + final Uri mockUri = mock(Uri.class); + when(mockUri.toString()).thenReturn(""); + + final WebResourceRequest mockRequest = mock(WebResourceRequest.class); + when(mockRequest.getMethod()).thenReturn("method"); + when(mockRequest.getUrl()).thenReturn(mockUri); + when(mockRequest.isForMainFrame()).thenReturn(true); + when(mockRequest.getRequestHeaders()).thenReturn(null); + + final WebResourceResponse mockResponse = mock(WebResourceResponse.class); + when(mockResponse.getStatusCode()).thenReturn(404); + + webViewClient.onReceivedHttpError(mockWebView, mockRequest, mockResponse); + verify(mockFlutterApi) + .onReceivedHttpError( + eq(webViewClient), + eq(mockWebView), + any(WebResourceRequest.class), + any(WebResourceResponse.class), + any()); } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java index cf34c6b62c6a..658b623b2034 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java @@ -4,24 +4,13 @@ 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.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import android.net.Uri; -import android.webkit.WebResourceRequest; -import android.webkit.WebResourceResponse; -import android.webkit.WebView; import android.webkit.WebViewClient; import androidx.annotation.NonNull; import io.flutter.plugins.webviewflutter.WebViewClientHostApiImpl.WebViewClientCompatImpl; import io.flutter.plugins.webviewflutter.WebViewClientHostApiImpl.WebViewClientCreator; -import java.util.HashMap; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -30,22 +19,14 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -public abstract class WebViewClientTest { +public class WebViewClientTest { @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock public WebViewClientFlutterApiImpl mockFlutterApi; - @Mock public WebView mockWebView; - - @Mock public WebViewClientCompatImpl mockWebViewClient; - InstanceManager instanceManager; WebViewClientHostApiImpl hostApiImpl; - WebViewClient webViewClient; - - abstract WebViewClient createInstance(WebViewClientFlutterApiImpl flutterApi); - - abstract void setReturnValueForShouldOverrideUrlLoading(WebViewClient client, boolean value); + WebViewClientCompatImpl webViewClient; @Before public void setUp() { @@ -57,7 +38,7 @@ public void setUp() { @NonNull public WebViewClient createWebViewClient( @NonNull WebViewClientFlutterApiImpl flutterApi) { - webViewClient = createInstance(flutterApi); + webViewClient = (WebViewClientCompatImpl) super.createWebViewClient(flutterApi); return webViewClient; } }; @@ -72,101 +53,9 @@ public void tearDown() { instanceManager.stopFinalizationListener(); } - @Test - public void onPageStarted() { - webViewClient.onPageStarted(mockWebView, "https://www.google.com", null); - verify(mockFlutterApi) - .onPageStarted(eq(webViewClient), eq(mockWebView), eq("https://www.google.com"), any()); - } - - @Test - @SuppressWarnings("deprecation") - public void onReceivedError() { - webViewClient.onReceivedError(mockWebView, 32, "description", "https://www.google.com"); - verify(mockFlutterApi) - .onReceivedError( - eq(webViewClient), - eq(mockWebView), - eq(32L), - eq("description"), - eq("https://www.google.com"), - any()); - } - - @Test - @SuppressWarnings("deprecation") - public void urlLoading() { - webViewClient.shouldOverrideUrlLoading(mockWebView, "https://www.google.com"); - verify(mockFlutterApi) - .urlLoading(eq(webViewClient), eq(mockWebView), eq("https://www.google.com"), any()); - } - - @Test - public void urlLoadingForMainFrame() { - setReturnValueForShouldOverrideUrlLoading(webViewClient, false); - - final WebResourceRequest mockRequest = mock(WebResourceRequest.class); - when(mockRequest.isForMainFrame()).thenReturn(true); - - assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); - verify(mockFlutterApi) - .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); - } - - @Test - public void urlLoadingForMainFrameWithOverride() { - setReturnValueForShouldOverrideUrlLoading(webViewClient, true); - - final WebResourceRequest mockRequest = mock(WebResourceRequest.class); - when(mockRequest.isForMainFrame()).thenReturn(true); - - assertTrue(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); - verify(mockFlutterApi) - .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); - } - - @Test - public void urlLoadingNotForMainFrame() { - setReturnValueForShouldOverrideUrlLoading(webViewClient, false); - - final WebResourceRequest mockRequest = mock(WebResourceRequest.class); - when(mockRequest.isForMainFrame()).thenReturn(false); - - assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); - verify(mockFlutterApi) - .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); - } - - @Test - public void urlLoadingNotForMainFrameWithOverride() { - setReturnValueForShouldOverrideUrlLoading(webViewClient, true); - - final WebResourceRequest mockRequest = mock(WebResourceRequest.class); - when(mockRequest.isForMainFrame()).thenReturn(false); - - assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); - verify(mockFlutterApi) - .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); - } - - @Test - public void convertWebResourceRequestWithNullHeaders() { - final Uri mockUri = mock(Uri.class); - when(mockUri.toString()).thenReturn(""); - - final WebResourceRequest mockRequest = mock(WebResourceRequest.class); - when(mockRequest.getMethod()).thenReturn("method"); - when(mockRequest.getUrl()).thenReturn(mockUri); - when(mockRequest.isForMainFrame()).thenReturn(true); - when(mockRequest.getRequestHeaders()).thenReturn(null); - - final GeneratedAndroidWebView.WebResourceRequestData data = - WebViewClientFlutterApiImpl.createWebResourceRequestData(mockRequest); - assertEquals(data.getRequestHeaders(), new HashMap()); - } - @Test public void setReturnValueForShouldOverrideUrlLoading() { + final WebViewClientCompatImpl mockWebViewClient = mock(); final WebViewClientHostApiImpl webViewClientHostApi = new WebViewClientHostApiImpl( instanceManager, @@ -185,36 +74,4 @@ public WebViewClient createWebViewClient( verify(mockWebViewClient).setReturnValueForShouldOverrideUrlLoading(false); } - - @Test - public void doUpdateVisitedHistory() { - webViewClient.doUpdateVisitedHistory(mockWebView, "https://www.google.com", true); - verify(mockFlutterApi) - .doUpdateVisitedHistory( - eq(webViewClient), eq(mockWebView), eq("https://www.google.com"), eq(true), any()); - } - - @Test - public void onReceivedHttpError() { - final Uri mockUri = mock(Uri.class); - when(mockUri.toString()).thenReturn(""); - - final WebResourceRequest mockRequest = mock(WebResourceRequest.class); - when(mockRequest.getMethod()).thenReturn("method"); - when(mockRequest.getUrl()).thenReturn(mockUri); - when(mockRequest.isForMainFrame()).thenReturn(true); - when(mockRequest.getRequestHeaders()).thenReturn(null); - - final WebResourceResponse mockResponse = mock(WebResourceResponse.class); - when(mockResponse.getStatusCode()).thenReturn(404); - - webViewClient.onReceivedHttpError(mockWebView, mockRequest, mockResponse); - verify(mockFlutterApi) - .onReceivedHttpError( - eq(webViewClient), - eq(mockWebView), - any(WebResourceRequest.class), - any(WebResourceResponse.class), - any()); - } } From d1d3bd6163977bd15417918b942fc18c221aa229 Mon Sep 17 00:00:00 2001 From: Peter Menten Date: Wed, 27 Mar 2024 20:36:28 +0100 Subject: [PATCH 3/4] Handle not sending the request to the client in the controller --- .../WebViewClientHostApiImpl.java | 22 +++---- .../WebViewClientCompatImplTest.java | 7 ++- .../webviewflutter/WebViewClientImplTest.java | 7 ++- .../lib/src/android_webview_controller.dart | 6 +- .../android_navigation_delegate_test.dart | 62 +++++++++++++++++++ 5 files changed, 83 insertions(+), 21 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java index afccf41481d5..fdc448279982 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java @@ -87,14 +87,11 @@ public void onReceivedError( @Override public boolean shouldOverrideUrlLoading( @NonNull WebView view, @NonNull WebResourceRequest request) { - if (!request.isForMainFrame()) { - // The client is only allowed to stop navigations that target the main frame because - // overridden URLs are passed to `loadUrl` and `loadUrl` cannot load a subframe. - return false; - } - flutterApi.requestLoading(this, view, request, reply -> {}); - return returnValueForShouldOverrideUrlLoading; + + // The client is only allowed to stop navigations that target the main frame because + // overridden URLs are passed to `loadUrl` and `loadUrl` cannot load a subframe. + return request.isForMainFrame() && returnValueForShouldOverrideUrlLoading; } // Legacy codepath for < 24; newer versions use the variant above. @@ -192,14 +189,11 @@ public void onReceivedError( @Override public boolean shouldOverrideUrlLoading( @NonNull WebView view, @NonNull WebResourceRequest request) { - if (!request.isForMainFrame()) { - // The client is only allowed to stop navigations that target the main frame because - // overridden URLs are passed to `loadUrl` and `loadUrl` cannot load a subframe. - return false; - } - flutterApi.requestLoading(this, view, request, reply -> {}); - return returnValueForShouldOverrideUrlLoading; + + // The client is only allowed to stop navigations that target the main frame because + // overridden URLs are passed to `loadUrl` and `loadUrl` cannot load a subframe. + return request.isForMainFrame() && returnValueForShouldOverrideUrlLoading; } // Legacy codepath for < Lollipop; newer versions use the variant above. diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java index d3849274fbba..8bdb6fd46481 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java @@ -11,7 +11,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import android.net.Uri; @@ -128,7 +127,8 @@ public void urlLoadingNotForMainFrame() { when(mockRequest.isForMainFrame()).thenReturn(false); assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); - verifyNoInteractions(mockFlutterApi); + verify(mockFlutterApi) + .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); } @Test @@ -139,7 +139,8 @@ public void urlLoadingNotForMainFrameWithOverride() { when(mockRequest.isForMainFrame()).thenReturn(false); assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); - verifyNoInteractions(mockFlutterApi); + verify(mockFlutterApi) + .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); } @Test diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientImplTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientImplTest.java index 492caf4874c7..cddd089ab4b8 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientImplTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientImplTest.java @@ -11,7 +11,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import android.net.Uri; @@ -125,7 +124,8 @@ public void urlLoadingNotForMainFrame() { when(mockRequest.isForMainFrame()).thenReturn(false); assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); - verifyNoInteractions(mockFlutterApi); + verify(mockFlutterApi) + .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); } @Test @@ -136,7 +136,8 @@ public void urlLoadingNotForMainFrameWithOverride() { when(mockRequest.isForMainFrame()).thenReturn(false); assertFalse(webViewClient.shouldOverrideUrlLoading(mockWebView, mockRequest)); - verifyNoInteractions(mockFlutterApi); + verify(mockFlutterApi) + .requestLoading(eq(webViewClient), eq(mockWebView), eq(mockRequest), any()); } @Test diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart index f353532bc5dd..d2b67145d2bc 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart @@ -1464,7 +1464,11 @@ class AndroidNavigationDelegate extends PlatformNavigationDelegate { final LoadRequestCallback? onLoadRequest = _onLoadRequest; final NavigationRequestCallback? onNavigationRequest = _onNavigationRequest; - if (onNavigationRequest == null || onLoadRequest == null) { + // The client is only allowed to stop navigations that target the main frame because + // overridden URLs are passed to `loadUrl` and `loadUrl` cannot load a subframe. + if (!isForMainFrame || + onNavigationRequest == null || + onLoadRequest == null) { return; } diff --git a/packages/webview_flutter/webview_flutter_android/test/android_navigation_delegate_test.dart b/packages/webview_flutter/webview_flutter_android/test/android_navigation_delegate_test.dart index 85b99dec2327..1adc7e64356c 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_navigation_delegate_test.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_navigation_delegate_test.dart @@ -163,6 +163,66 @@ void main() { expect(callbackNavigationRequest, isNull); }); + test( + 'onNavigationRequest from requestLoading should be called when request is for main frame', + () { + final AndroidNavigationDelegate androidNavigationDelegate = + AndroidNavigationDelegate(_buildCreationParams()); + + NavigationRequest? callbackNavigationRequest; + androidNavigationDelegate + .setOnNavigationRequest((NavigationRequest navigationRequest) { + callbackNavigationRequest = navigationRequest; + return NavigationDecision.prevent; + }); + + androidNavigationDelegate.setOnLoadRequest((_) async {}); + + CapturingWebViewClient.lastCreatedDelegate.requestLoading!( + android_webview.WebView.detached(), + android_webview.WebResourceRequest( + url: 'https://www.google.com', + isForMainFrame: true, + isRedirect: true, + hasGesture: true, + method: 'GET', + requestHeaders: {'X-Mock': 'mocking'}, + ), + ); + + expect(callbackNavigationRequest, isNotNull); + }); + + test( + 'onNavigationRequest from requestLoading should not be called when request is not for main frame', + () { + final AndroidNavigationDelegate androidNavigationDelegate = + AndroidNavigationDelegate(_buildCreationParams()); + + NavigationRequest? callbackNavigationRequest; + androidNavigationDelegate + .setOnNavigationRequest((NavigationRequest navigationRequest) { + callbackNavigationRequest = navigationRequest; + return NavigationDecision.prevent; + }); + + androidNavigationDelegate.setOnLoadRequest((_) async {}); + + CapturingWebViewClient.lastCreatedDelegate.requestLoading!( + android_webview.WebView.detached(), + android_webview.WebResourceRequest( + url: 'https://www.google.com', + isForMainFrame: false, + isRedirect: true, + hasGesture: true, + method: 'GET', + requestHeaders: {'X-Mock': 'mocking'}, + ), + ); + + expect(callbackNavigationRequest, isNull); + }); + test( 'onLoadRequest from requestLoading should not be called when navigationRequestCallback is not specified', () { @@ -598,6 +658,7 @@ class CapturingWebChromeClient extends android_webview.WebChromeClient { }) : super.detached() { lastCreatedDelegate = this; } + static CapturingWebChromeClient lastCreatedDelegate = CapturingWebChromeClient(); } @@ -611,6 +672,7 @@ class CapturingDownloadListener extends android_webview.DownloadListener { }) : super.detached() { lastCreatedListener = this; } + static CapturingDownloadListener lastCreatedListener = CapturingDownloadListener(onDownloadStart: (_, __, ___, ____, _____) {}); } From 90358477118f165848b1a70dd6c78e5c46c75a6c Mon Sep 17 00:00:00 2001 From: Peter Menten Date: Mon, 15 Apr 2024 16:27:00 +0200 Subject: [PATCH 4/4] Remove redundant test --- .../WebViewClientCompatImplTest.java | 3 +- .../webviewflutter/WebViewClientTest.java | 77 ------------------- 2 files changed, 1 insertion(+), 79 deletions(-) delete mode 100644 packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java index 8bdb6fd46481..fa165238f662 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientCompatImplTest.java @@ -37,8 +37,6 @@ public class WebViewClientCompatImplTest { @Mock public WebView mockWebView; - @Mock public WebViewClientCompatImpl mockWebViewClient; - InstanceManager instanceManager; WebViewClientHostApiImpl hostApiImpl; WebViewClientCompatImpl webViewClient; @@ -161,6 +159,7 @@ public void convertWebResourceRequestWithNullHeaders() { @Test public void setReturnValueForShouldOverrideUrlLoading() { + WebViewClientHostApiImpl.WebViewClientCompatImpl mockWebViewClient = mock(); final WebViewClientHostApiImpl webViewClientHostApi = new WebViewClientHostApiImpl( instanceManager, diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java deleted file mode 100644 index 658b623b2034..000000000000 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java +++ /dev/null @@ -1,77 +0,0 @@ -// 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. - -package io.flutter.plugins.webviewflutter; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import android.webkit.WebViewClient; -import androidx.annotation.NonNull; -import io.flutter.plugins.webviewflutter.WebViewClientHostApiImpl.WebViewClientCompatImpl; -import io.flutter.plugins.webviewflutter.WebViewClientHostApiImpl.WebViewClientCreator; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -public class WebViewClientTest { - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock public WebViewClientFlutterApiImpl mockFlutterApi; - - InstanceManager instanceManager; - WebViewClientHostApiImpl hostApiImpl; - WebViewClientCompatImpl webViewClient; - - @Before - public void setUp() { - instanceManager = InstanceManager.create(identifier -> {}); - - final WebViewClientCreator webViewClientCreator = - new WebViewClientCreator() { - @Override - @NonNull - public WebViewClient createWebViewClient( - @NonNull WebViewClientFlutterApiImpl flutterApi) { - webViewClient = (WebViewClientCompatImpl) super.createWebViewClient(flutterApi); - return webViewClient; - } - }; - - hostApiImpl = - new WebViewClientHostApiImpl(instanceManager, webViewClientCreator, mockFlutterApi); - hostApiImpl.create(1L); - } - - @After - public void tearDown() { - instanceManager.stopFinalizationListener(); - } - - @Test - public void setReturnValueForShouldOverrideUrlLoading() { - final WebViewClientCompatImpl mockWebViewClient = mock(); - final WebViewClientHostApiImpl webViewClientHostApi = - new WebViewClientHostApiImpl( - instanceManager, - new WebViewClientCreator() { - @NonNull - @Override - public WebViewClient createWebViewClient( - @NonNull WebViewClientFlutterApiImpl flutterApi) { - return mockWebViewClient; - } - }, - mockFlutterApi); - - instanceManager.addDartCreatedInstance(mockWebViewClient, 2); - webViewClientHostApi.setSynchronousReturnValueForShouldOverrideUrlLoading(2L, false); - - verify(mockWebViewClient).setReturnValueForShouldOverrideUrlLoading(false); - } -}