From 5579fb3073ef821202f28e8d3fe9c8a355c6ae2c Mon Sep 17 00:00:00 2001 From: Rene Floor Date: Wed, 8 Sep 2021 16:31:36 +0200 Subject: [PATCH 1/4] Add download listener to Android webview --- .../FlutterDownloadListener.java | 24 ++++++++ .../webviewflutter/FlutterWebView.java | 20 +++++-- .../webviewflutter/FlutterWebViewClient.java | 17 ++++++ .../webviewflutter/WebViewBuilder.java | 16 +++++- .../FlutterDownloadListenerTest.java | 40 +++++++++++++ .../FlutterWebViewClientTest.java | 56 +++++++++++++++++++ .../webviewflutter/FlutterWebViewTest.java | 7 ++- .../webviewflutter/WebViewBuilderTest.java | 7 ++- 8 files changed, 178 insertions(+), 9 deletions(-) create mode 100644 packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterDownloadListener.java create mode 100644 packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterDownloadListenerTest.java create mode 100644 packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewClientTest.java diff --git a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterDownloadListener.java b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterDownloadListener.java new file mode 100644 index 000000000000..341c7e263316 --- /dev/null +++ b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterDownloadListener.java @@ -0,0 +1,24 @@ +package io.flutter.plugins.webviewflutter; + +import android.webkit.DownloadListener; +import android.webkit.WebView; + +/** DownloadListener to notify the {@link FlutterWebViewClient} of download starts */ +public class FlutterDownloadListener implements DownloadListener { + final private FlutterWebViewClient webViewClient; + private WebView webView; + + public FlutterDownloadListener(FlutterWebViewClient webViewClient){ + this.webViewClient = webViewClient; + } + + /** Sets the {@link WebView} that the result of the navigation delegate will be send to. */ + public void setWebView(WebView webView){ + this.webView = webView; + } + + @Override + public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) { + webViewClient.notifyDownload(webView, url); + } +} diff --git a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java index a3b681f27980..432b8f3e518e 100644 --- a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java +++ b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java @@ -11,12 +11,14 @@ import android.os.Handler; import android.os.Message; import android.view.View; +import android.webkit.DownloadListener; import android.webkit.WebChromeClient; import android.webkit.WebResourceRequest; import android.webkit.WebStorage; import android.webkit.WebView; import android.webkit.WebViewClient; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; @@ -94,18 +96,23 @@ public void onProgressChanged(WebView view, int progress) { (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); displayListenerProxy.onPreWebViewInitialization(displayManager); + this.methodChannel = methodChannel; + this.methodChannel.setMethodCallHandler(this); + + flutterWebViewClient = new FlutterWebViewClient(methodChannel); + + FlutterDownloadListener flutterDownloadListener = new FlutterDownloadListener(flutterWebViewClient); webView = createWebView( - new WebViewBuilder(context, containerView), params, new FlutterWebChromeClient()); + new WebViewBuilder(context, containerView), params, new FlutterWebChromeClient(), flutterDownloadListener); + flutterDownloadListener.setWebView(webView); + displayListenerProxy.onPostWebViewInitialization(displayManager); platformThreadHandler = new Handler(context.getMainLooper()); - this.methodChannel = methodChannel; - this.methodChannel.setMethodCallHandler(this); - flutterWebViewClient = new FlutterWebViewClient(methodChannel); Map settings = (Map) params.get("settings"); if (settings != null) { applySettings(settings); @@ -156,7 +163,7 @@ public void onProgressChanged(WebView view, int progress) { */ @VisibleForTesting static WebView createWebView( - WebViewBuilder webViewBuilder, Map params, WebChromeClient webChromeClient) { + WebViewBuilder webViewBuilder, Map params, WebChromeClient webChromeClient, @Nullable DownloadListener downloadListener) { boolean usesHybridComposition = Boolean.TRUE.equals(params.get("usesHybridComposition")); webViewBuilder .setUsesHybridComposition(usesHybridComposition) @@ -165,7 +172,8 @@ static WebView createWebView( true) // Always allow automatically opening of windows. .setSupportMultipleWindows(true) // Always support multiple windows. .setWebChromeClient( - webChromeClient); // Always use {@link FlutterWebChromeClient} as web Chrome client. + webChromeClient) + .setDownloadListener(downloadListener);// Always use {@link FlutterWebChromeClient} as web Chrome client. return webViewBuilder.build(); } diff --git a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java index adc84671a701..cc2125284929 100644 --- a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java +++ b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java @@ -115,6 +115,23 @@ boolean shouldOverrideUrlLoading(WebView view, String url) { return true; } + /** + * Notifies the Flutter code that a download should start when a navigation delegate is set. + * + * @param view the webView the result of the navigation delegate will be send to. + * @param url the download url + * + * @return A boolean whether or not the request is forwarded to the Flutter code. + */ + boolean notifyDownload(WebView view, String url) { + if (!hasNavigationDelegate) { + return false; + } + + notifyOnNavigationRequest(url, null, view, true); + return true; + } + private void onPageStarted(WebView view, String url) { Map args = new HashMap<>(); args.put("url", url); diff --git a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewBuilder.java b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewBuilder.java index 6b8cc51febe8..6037ea3b735f 100644 --- a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewBuilder.java +++ b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewBuilder.java @@ -6,6 +6,7 @@ import android.content.Context; import android.view.View; +import android.webkit.DownloadListener; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; @@ -44,6 +45,7 @@ static WebView create(Context context, boolean usesHybridComposition, View conta private boolean supportMultipleWindows; private boolean usesHybridComposition; private WebChromeClient webChromeClient; + private DownloadListener downloadListener; /** * Constructs a new {@link WebViewBuilder} object with a custom implementation of the {@link @@ -122,6 +124,18 @@ public WebViewBuilder setWebChromeClient(@Nullable WebChromeClient webChromeClie return this; } + /** + * Registers the interface to be used when content can not be handled by the rendering engine, + * and should be downloaded instead. This will replace the current handler. + * + * @param downloadListener an implementation of DownloadListener This value may be null. + * @return This builder. This value cannot be {@code null}. + */ + public WebViewBuilder setDownloadListener(@Nullable DownloadListener downloadListener){ + this.downloadListener = downloadListener; + return this; + } + /** * Build the {@link android.webkit.WebView} using the current settings. * @@ -135,7 +149,7 @@ public WebView build() { webSettings.setJavaScriptCanOpenWindowsAutomatically(javaScriptCanOpenWindowsAutomatically); webSettings.setSupportMultipleWindows(supportMultipleWindows); webView.setWebChromeClient(webChromeClient); - + webView.setDownloadListener(downloadListener); return webView; } } diff --git a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterDownloadListenerTest.java b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterDownloadListenerTest.java new file mode 100644 index 000000000000..77f903ca6a12 --- /dev/null +++ b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterDownloadListenerTest.java @@ -0,0 +1,40 @@ +package io.flutter.plugins.webviewflutter; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import android.webkit.WebView; + +import org.junit.Before; +import org.junit.Test; + +public class FlutterDownloadListenerTest { + private FlutterWebViewClient webViewClient; + private WebView webView; + + @Before + public void before() { + webViewClient = mock(FlutterWebViewClient.class); + webView = mock(WebView.class); + } + + @Test + public void onDownloadStart_should_notify_webViewClient(){ + String url = "testurl.com"; + FlutterDownloadListener downloadListener = new FlutterDownloadListener(webViewClient); + downloadListener.onDownloadStart(url, "test", "inline", "data/text", 0); + verify(webViewClient).notifyDownload(nullable(WebView.class), eq(url)); + } + + @Test + public void onDownloadStart_should_pass_webView(){ + FlutterDownloadListener downloadListener = new FlutterDownloadListener(webViewClient); + downloadListener.setWebView(webView); + downloadListener.onDownloadStart("testurl.com", "test", "inline", "data/text", 0); + verify(webViewClient).notifyDownload(eq(webView), anyString()); + } +} diff --git a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewClientTest.java b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewClientTest.java new file mode 100644 index 000000000000..1bf84d584f11 --- /dev/null +++ b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewClientTest.java @@ -0,0 +1,56 @@ +package io.flutter.plugins.webviewflutter; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +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 android.webkit.WebView; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.util.HashMap; + +import io.flutter.plugin.common.MethodChannel; + +public class FlutterWebViewClientTest { + + MethodChannel mockMethodChannel; + WebView mockWebView; + @Before + public void before() { + mockMethodChannel = mock(MethodChannel.class); + mockWebView = mock(WebView.class); + } + + @Test + public void notify_download_should_notifyOnNavigationRequest_when_navigationDelegate_is_set() { + final String url = "testurl.com"; + + FlutterWebViewClient client = new FlutterWebViewClient(mockMethodChannel); + client.createWebViewClient(true); + + client.notifyDownload(mockWebView, url); + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Object.class); + verify(mockMethodChannel).invokeMethod(eq("navigationRequest"), argumentCaptor.capture(), any(MethodChannel.Result.class)); + HashMap map = (HashMap) argumentCaptor.getValue(); + assertEquals(map.get("url"), url); + assertEquals(map.get("isForMainFrame"), true); + } + + @Test + public void notify_download_should_not_notifyOnNavigationRequest_when_navigationDelegate_is_not_set() { + final String url = "testurl.com"; + + FlutterWebViewClient client = new FlutterWebViewClient(mockMethodChannel); + client.createWebViewClient(false); + + client.notifyDownload(mockWebView, url); + verifyNoInteractions(mockMethodChannel); + } +} diff --git a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java index 96cbdece387c..45faf46472fa 100644 --- a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java +++ b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java @@ -11,6 +11,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.webkit.DownloadListener; import android.webkit.WebChromeClient; import android.webkit.WebView; import java.util.HashMap; @@ -20,6 +21,7 @@ public class FlutterWebViewTest { private WebChromeClient mockWebChromeClient; + private DownloadListener mockDownloadListener; private WebViewBuilder mockWebViewBuilder; private WebView mockWebView; @@ -28,6 +30,7 @@ public void before() { mockWebChromeClient = mock(WebChromeClient.class); mockWebViewBuilder = mock(WebViewBuilder.class); mockWebView = mock(WebView.class); + mockDownloadListener = mock(DownloadListener.class); when(mockWebViewBuilder.setDomStorageEnabled(anyBoolean())).thenReturn(mockWebViewBuilder); when(mockWebViewBuilder.setJavaScriptCanOpenWindowsAutomatically(anyBoolean())) @@ -36,6 +39,8 @@ public void before() { when(mockWebViewBuilder.setUsesHybridComposition(anyBoolean())).thenReturn(mockWebViewBuilder); when(mockWebViewBuilder.setWebChromeClient(any(WebChromeClient.class))) .thenReturn(mockWebViewBuilder); + when(mockWebViewBuilder.setDownloadListener(any(DownloadListener.class))) + .thenReturn(mockWebViewBuilder); when(mockWebViewBuilder.build()).thenReturn(mockWebView); } @@ -43,7 +48,7 @@ public void before() { @Test public void createWebView_should_create_webview_with_default_configuration() { FlutterWebView.createWebView( - mockWebViewBuilder, createParameterMap(false), mockWebChromeClient); + mockWebViewBuilder, createParameterMap(false), mockWebChromeClient, mockDownloadListener); verify(mockWebViewBuilder, times(1)).setDomStorageEnabled(true); verify(mockWebViewBuilder, times(1)).setJavaScriptCanOpenWindowsAutomatically(true); diff --git a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewBuilderTest.java b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewBuilderTest.java index 48fbce231ed5..423cb210c392 100644 --- a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewBuilderTest.java +++ b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewBuilderTest.java @@ -9,6 +9,7 @@ import android.content.Context; import android.view.View; +import android.webkit.DownloadListener; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; @@ -60,6 +61,7 @@ public void ctor_test() { public void build_should_set_values() throws IOException { WebSettings mockWebSettings = mock(WebSettings.class); WebChromeClient mockWebChromeClient = mock(WebChromeClient.class); + DownloadListener mockDownloadListener = mock(DownloadListener.class); when(mockWebView.getSettings()).thenReturn(mockWebSettings); @@ -68,7 +70,8 @@ public void build_should_set_values() throws IOException { .setDomStorageEnabled(true) .setJavaScriptCanOpenWindowsAutomatically(true) .setSupportMultipleWindows(true) - .setWebChromeClient(mockWebChromeClient); + .setWebChromeClient(mockWebChromeClient) + .setDownloadListener(mockDownloadListener); WebView webView = builder.build(); @@ -77,6 +80,7 @@ public void build_should_set_values() throws IOException { verify(mockWebSettings).setJavaScriptCanOpenWindowsAutomatically(true); verify(mockWebSettings).setSupportMultipleWindows(true); verify(mockWebView).setWebChromeClient(mockWebChromeClient); + verify(mockWebView).setDownloadListener(mockDownloadListener); } @Test @@ -95,5 +99,6 @@ public void build_should_use_default_values() throws IOException { verify(mockWebSettings).setJavaScriptCanOpenWindowsAutomatically(false); verify(mockWebSettings).setSupportMultipleWindows(false); verify(mockWebView).setWebChromeClient(null); + verify(mockWebView).setDownloadListener(null); } } From d503c8f445d69e54cdb67c106e393a791ce60615 Mon Sep 17 00:00:00 2001 From: Rene Floor Date: Wed, 8 Sep 2021 16:47:37 +0200 Subject: [PATCH 2/4] formatting --- .../FlutterDownloadListener.java | 31 ++++---- .../webviewflutter/FlutterWebView.java | 21 +++-- .../webviewflutter/FlutterWebViewClient.java | 1 - .../webviewflutter/WebViewBuilder.java | 6 +- .../FlutterDownloadListenerTest.java | 44 +++++------ .../FlutterWebViewClientTest.java | 78 +++++++++---------- .../webviewflutter/FlutterWebViewTest.java | 2 +- 7 files changed, 95 insertions(+), 88 deletions(-) diff --git a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterDownloadListener.java b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterDownloadListener.java index 341c7e263316..05127b4b0a9a 100644 --- a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterDownloadListener.java +++ b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterDownloadListener.java @@ -5,20 +5,25 @@ /** DownloadListener to notify the {@link FlutterWebViewClient} of download starts */ public class FlutterDownloadListener implements DownloadListener { - final private FlutterWebViewClient webViewClient; - private WebView webView; + private final FlutterWebViewClient webViewClient; + private WebView webView; - public FlutterDownloadListener(FlutterWebViewClient webViewClient){ - this.webViewClient = webViewClient; - } + public FlutterDownloadListener(FlutterWebViewClient webViewClient) { + this.webViewClient = webViewClient; + } - /** Sets the {@link WebView} that the result of the navigation delegate will be send to. */ - public void setWebView(WebView webView){ - this.webView = webView; - } + /** Sets the {@link WebView} that the result of the navigation delegate will be send to. */ + public void setWebView(WebView webView) { + this.webView = webView; + } - @Override - public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) { - webViewClient.notifyDownload(webView, url); - } + @Override + public void onDownloadStart( + String url, + String userAgent, + String contentDisposition, + String mimetype, + long contentLength) { + webViewClient.notifyDownload(webView, url); + } } diff --git a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java index 432b8f3e518e..4651a5f5ae22 100644 --- a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java +++ b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java @@ -101,18 +101,20 @@ public void onProgressChanged(WebView view, int progress) { flutterWebViewClient = new FlutterWebViewClient(methodChannel); - FlutterDownloadListener flutterDownloadListener = new FlutterDownloadListener(flutterWebViewClient); + FlutterDownloadListener flutterDownloadListener = + new FlutterDownloadListener(flutterWebViewClient); webView = createWebView( - new WebViewBuilder(context, containerView), params, new FlutterWebChromeClient(), flutterDownloadListener); + new WebViewBuilder(context, containerView), + params, + new FlutterWebChromeClient(), + flutterDownloadListener); flutterDownloadListener.setWebView(webView); - displayListenerProxy.onPostWebViewInitialization(displayManager); platformThreadHandler = new Handler(context.getMainLooper()); - Map settings = (Map) params.get("settings"); if (settings != null) { applySettings(settings); @@ -163,7 +165,10 @@ public void onProgressChanged(WebView view, int progress) { */ @VisibleForTesting static WebView createWebView( - WebViewBuilder webViewBuilder, Map params, WebChromeClient webChromeClient, @Nullable DownloadListener downloadListener) { + WebViewBuilder webViewBuilder, + Map params, + WebChromeClient webChromeClient, + @Nullable DownloadListener downloadListener) { boolean usesHybridComposition = Boolean.TRUE.equals(params.get("usesHybridComposition")); webViewBuilder .setUsesHybridComposition(usesHybridComposition) @@ -171,9 +176,9 @@ static WebView createWebView( .setJavaScriptCanOpenWindowsAutomatically( true) // Always allow automatically opening of windows. .setSupportMultipleWindows(true) // Always support multiple windows. - .setWebChromeClient( - webChromeClient) - .setDownloadListener(downloadListener);// Always use {@link FlutterWebChromeClient} as web Chrome client. + .setWebChromeClient(webChromeClient) + .setDownloadListener( + downloadListener); // Always use {@link FlutterWebChromeClient} as web Chrome client. return webViewBuilder.build(); } diff --git a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java index cc2125284929..260ef8e8b15d 100644 --- a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java +++ b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java @@ -120,7 +120,6 @@ boolean shouldOverrideUrlLoading(WebView view, String url) { * * @param view the webView the result of the navigation delegate will be send to. * @param url the download url - * * @return A boolean whether or not the request is forwarded to the Flutter code. */ boolean notifyDownload(WebView view, String url) { diff --git a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewBuilder.java b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewBuilder.java index 6037ea3b735f..d3cd1d57cdae 100644 --- a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewBuilder.java +++ b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewBuilder.java @@ -125,13 +125,13 @@ public WebViewBuilder setWebChromeClient(@Nullable WebChromeClient webChromeClie } /** - * Registers the interface to be used when content can not be handled by the rendering engine, - * and should be downloaded instead. This will replace the current handler. + * Registers the interface to be used when content can not be handled by the rendering engine, and + * should be downloaded instead. This will replace the current handler. * * @param downloadListener an implementation of DownloadListener This value may be null. * @return This builder. This value cannot be {@code null}. */ - public WebViewBuilder setDownloadListener(@Nullable DownloadListener downloadListener){ + public WebViewBuilder setDownloadListener(@Nullable DownloadListener downloadListener) { this.downloadListener = downloadListener; return this; } diff --git a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterDownloadListenerTest.java b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterDownloadListenerTest.java index 77f903ca6a12..6231d1f651ff 100644 --- a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterDownloadListenerTest.java +++ b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterDownloadListenerTest.java @@ -1,6 +1,5 @@ package io.flutter.plugins.webviewflutter; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; @@ -8,33 +7,32 @@ import static org.mockito.Mockito.verify; import android.webkit.WebView; - import org.junit.Before; import org.junit.Test; public class FlutterDownloadListenerTest { - private FlutterWebViewClient webViewClient; - private WebView webView; + private FlutterWebViewClient webViewClient; + private WebView webView; - @Before - public void before() { - webViewClient = mock(FlutterWebViewClient.class); - webView = mock(WebView.class); - } + @Before + public void before() { + webViewClient = mock(FlutterWebViewClient.class); + webView = mock(WebView.class); + } - @Test - public void onDownloadStart_should_notify_webViewClient(){ - String url = "testurl.com"; - FlutterDownloadListener downloadListener = new FlutterDownloadListener(webViewClient); - downloadListener.onDownloadStart(url, "test", "inline", "data/text", 0); - verify(webViewClient).notifyDownload(nullable(WebView.class), eq(url)); - } + @Test + public void onDownloadStart_should_notify_webViewClient() { + String url = "testurl.com"; + FlutterDownloadListener downloadListener = new FlutterDownloadListener(webViewClient); + downloadListener.onDownloadStart(url, "test", "inline", "data/text", 0); + verify(webViewClient).notifyDownload(nullable(WebView.class), eq(url)); + } - @Test - public void onDownloadStart_should_pass_webView(){ - FlutterDownloadListener downloadListener = new FlutterDownloadListener(webViewClient); - downloadListener.setWebView(webView); - downloadListener.onDownloadStart("testurl.com", "test", "inline", "data/text", 0); - verify(webViewClient).notifyDownload(eq(webView), anyString()); - } + @Test + public void onDownloadStart_should_pass_webView() { + FlutterDownloadListener downloadListener = new FlutterDownloadListener(webViewClient); + downloadListener.setWebView(webView); + downloadListener.onDownloadStart("testurl.com", "test", "inline", "data/text", 0); + verify(webViewClient).notifyDownload(eq(webView), anyString()); + } } diff --git a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewClientTest.java b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewClientTest.java index 1bf84d584f11..d4b9df357a6c 100644 --- a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewClientTest.java +++ b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewClientTest.java @@ -1,7 +1,6 @@ package io.flutter.plugins.webviewflutter; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -9,48 +8,49 @@ import static org.mockito.Mockito.verifyNoInteractions; import android.webkit.WebView; - +import io.flutter.plugin.common.MethodChannel; +import java.util.HashMap; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; -import java.util.HashMap; - -import io.flutter.plugin.common.MethodChannel; - public class FlutterWebViewClientTest { - MethodChannel mockMethodChannel; - WebView mockWebView; - @Before - public void before() { - mockMethodChannel = mock(MethodChannel.class); - mockWebView = mock(WebView.class); - } - - @Test - public void notify_download_should_notifyOnNavigationRequest_when_navigationDelegate_is_set() { - final String url = "testurl.com"; - - FlutterWebViewClient client = new FlutterWebViewClient(mockMethodChannel); - client.createWebViewClient(true); - - client.notifyDownload(mockWebView, url); - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Object.class); - verify(mockMethodChannel).invokeMethod(eq("navigationRequest"), argumentCaptor.capture(), any(MethodChannel.Result.class)); - HashMap map = (HashMap) argumentCaptor.getValue(); - assertEquals(map.get("url"), url); - assertEquals(map.get("isForMainFrame"), true); - } - - @Test - public void notify_download_should_not_notifyOnNavigationRequest_when_navigationDelegate_is_not_set() { - final String url = "testurl.com"; - - FlutterWebViewClient client = new FlutterWebViewClient(mockMethodChannel); - client.createWebViewClient(false); - - client.notifyDownload(mockWebView, url); - verifyNoInteractions(mockMethodChannel); - } + MethodChannel mockMethodChannel; + WebView mockWebView; + + @Before + public void before() { + mockMethodChannel = mock(MethodChannel.class); + mockWebView = mock(WebView.class); + } + + @Test + public void notify_download_should_notifyOnNavigationRequest_when_navigationDelegate_is_set() { + final String url = "testurl.com"; + + FlutterWebViewClient client = new FlutterWebViewClient(mockMethodChannel); + client.createWebViewClient(true); + + client.notifyDownload(mockWebView, url); + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Object.class); + verify(mockMethodChannel) + .invokeMethod( + eq("navigationRequest"), argumentCaptor.capture(), any(MethodChannel.Result.class)); + HashMap map = (HashMap) argumentCaptor.getValue(); + assertEquals(map.get("url"), url); + assertEquals(map.get("isForMainFrame"), true); + } + + @Test + public void + notify_download_should_not_notifyOnNavigationRequest_when_navigationDelegate_is_not_set() { + final String url = "testurl.com"; + + FlutterWebViewClient client = new FlutterWebViewClient(mockMethodChannel); + client.createWebViewClient(false); + + client.notifyDownload(mockWebView, url); + verifyNoInteractions(mockMethodChannel); + } } diff --git a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java index 45faf46472fa..56d9db1ee493 100644 --- a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java +++ b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java @@ -40,7 +40,7 @@ public void before() { when(mockWebViewBuilder.setWebChromeClient(any(WebChromeClient.class))) .thenReturn(mockWebViewBuilder); when(mockWebViewBuilder.setDownloadListener(any(DownloadListener.class))) - .thenReturn(mockWebViewBuilder); + .thenReturn(mockWebViewBuilder); when(mockWebViewBuilder.build()).thenReturn(mockWebView); } From aa2b1319ea63c140c56c6febbecec5854e4fce80 Mon Sep 17 00:00:00 2001 From: Rene Floor Date: Wed, 8 Sep 2021 16:55:21 +0200 Subject: [PATCH 3/4] copyright --- .../plugins/webviewflutter/FlutterDownloadListener.java | 4 ++++ .../plugins/webviewflutter/FlutterDownloadListenerTest.java | 4 ++++ .../plugins/webviewflutter/FlutterWebViewClientTest.java | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterDownloadListener.java b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterDownloadListener.java index 05127b4b0a9a..cfad4e315514 100644 --- a/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterDownloadListener.java +++ b/packages/webview_flutter/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterDownloadListener.java @@ -1,3 +1,7 @@ +// 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.DownloadListener; diff --git a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterDownloadListenerTest.java b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterDownloadListenerTest.java index 6231d1f651ff..2c918584ba83 100644 --- a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterDownloadListenerTest.java +++ b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterDownloadListenerTest.java @@ -1,3 +1,7 @@ +// 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.ArgumentMatchers.anyString; diff --git a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewClientTest.java b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewClientTest.java index d4b9df357a6c..86346ac08f16 100644 --- a/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewClientTest.java +++ b/packages/webview_flutter/webview_flutter/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewClientTest.java @@ -1,3 +1,7 @@ +// 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.junit.Assert.assertEquals; From 2c67b5a078214175ead1b30b8479ab1a25c8cb0b Mon Sep 17 00:00:00 2001 From: Rene Floor Date: Wed, 8 Sep 2021 17:06:58 +0200 Subject: [PATCH 4/4] Changelog and pubspec --- packages/webview_flutter/webview_flutter/CHANGELOG.md | 3 ++- packages/webview_flutter/webview_flutter/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/webview_flutter/webview_flutter/CHANGELOG.md b/packages/webview_flutter/webview_flutter/CHANGELOG.md index 361bfd24f3af..1e1d5aa523ba 100644 --- a/packages/webview_flutter/webview_flutter/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 2.0.13 +* Send URL of File to download to the NavigationDelegate on Android just like it is already done on iOS. * Updated Android lint settings. ## 2.0.12 diff --git a/packages/webview_flutter/webview_flutter/pubspec.yaml b/packages/webview_flutter/webview_flutter/pubspec.yaml index cc5d9cdc8b96..3976ff74fef6 100644 --- a/packages/webview_flutter/webview_flutter/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter description: A Flutter plugin that provides a WebView widget on Android and iOS. repository: https://github.com/flutter/plugins/tree/master/packages/webview_flutter/webview_flutter issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 2.0.12 +version: 2.0.13 environment: sdk: ">=2.12.0 <3.0.0"