diff --git a/packages/webview_flutter/webview_flutter/lib/src/webview.dart b/packages/webview_flutter/webview_flutter/lib/src/webview.dart index 6a24d3d4cb2d..cec743cf6bd2 100644 --- a/packages/webview_flutter/webview_flutter/lib/src/webview.dart +++ b/packages/webview_flutter/webview_flutter/lib/src/webview.dart @@ -63,6 +63,8 @@ typedef PageFinishedCallback = void Function(String url); /// Signature for when a [WebView] is loading a page. typedef PageLoadingCallback = void Function(int progress); +typedef ShowFileChooserCallBack = Future> Function(); + /// Signature for when a [WebView] has failed to load a resource. typedef WebResourceErrorCallback = void Function(WebResourceError error); @@ -90,6 +92,7 @@ class WebView extends StatefulWidget { this.onPageStarted, this.onPageFinished, this.onProgress, + this.onShowFileChooser, this.onWebResourceError, this.debuggingEnabled = false, this.gestureNavigationEnabled = false, @@ -238,6 +241,9 @@ class WebView extends StatefulWidget { /// Invoked when a page is loading. final PageLoadingCallback? onProgress; + /// Invoked when a page is loading. + final ShowFileChooserCallBack? onShowFileChooser; + /// Invoked when a web resource has failed to load. /// /// This callback is only called for the main page. @@ -484,6 +490,14 @@ class _PlatformCallbacksHandler implements WebViewPlatformCallbacksHandler { } } + @override + Future> onShowFileChooser() async { + if (_widget.onShowFileChooser != null) { + return await _widget.onShowFileChooser!(); + } + return []; + } + @override void onWebResourceError(WebResourceError error) { if (_widget.onWebResourceError != null) { diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java index afca5ee12747..c7b568656367 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java @@ -1,7 +1,3 @@ -// 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. - // Autogenerated from Pigeon (v1.0.9), do not edit directly. // See also: https://pub.dev/packages/pigeon @@ -2197,6 +2193,22 @@ public void onProgressChanged( callback.reply(null); }); } + + public void onShowFileChooser( + Long instanceIdArg, Long webViewInstanceIdArg, Reply> callback) { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebChromeClientFlutterApi.onShowFileChooser", + getCodec()); + channel.send( + new ArrayList(Arrays.asList(instanceIdArg, webViewInstanceIdArg)), + channelReply -> { + @SuppressWarnings("ConstantConditions") + List output = (List) channelReply; + callback.reply(output); + }); + } } private static class WebStorageHostApiCodec extends StandardMessageCodec { diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebChromeClientFlutterApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebChromeClientFlutterApiImpl.java index 2ab9275b41c3..099d68c9299b 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebChromeClientFlutterApiImpl.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebChromeClientFlutterApiImpl.java @@ -8,6 +8,7 @@ import android.webkit.WebView; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.WebChromeClientFlutterApi; +import java.util.List; /** * Flutter Api implementation for {@link WebChromeClient}. @@ -39,6 +40,15 @@ public void onProgressChanged( callback); } + /** Passes arguments from {@link WebChromeClient#onProgressChanged} to Dart. */ + public void onShowFileChooser( + WebChromeClient webChromeClient, WebView webView, Reply> callback) { + super.onShowFileChooser( + instanceManager.getInstanceId(webChromeClient), + instanceManager.getInstanceId(webView), + callback); + } + /** * Communicates to Dart that the reference to a {@link WebChromeClient}} was removed. * diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebChromeClientHostApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebChromeClientHostApiImpl.java index d2e1e59ce179..fc6d7f815deb 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebChromeClientHostApiImpl.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebChromeClientHostApiImpl.java @@ -4,8 +4,10 @@ package io.flutter.plugins.webviewflutter; +import android.net.Uri; import android.os.Build; import android.os.Message; +import android.webkit.ValueCallback; import android.webkit.WebChromeClient; import android.webkit.WebResourceRequest; import android.webkit.WebView; @@ -14,7 +16,10 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.annotation.VisibleForTesting; +import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.WebChromeClientFlutterApi; import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.WebChromeClientHostApi; +import java.io.File; +import java.util.List; /** * Host api implementation for {@link WebChromeClient}. @@ -100,6 +105,30 @@ public boolean shouldOverrideUrlLoading(WebView windowWebView, String url) { return true; } + @Override + public boolean onShowFileChooser( + WebView view, + ValueCallback filePathCallback, + WebChromeClient.FileChooserParams fileChooserParams) { + if (flutterApi != null) { + flutterApi.onShowFileChooser( + this, + view, + new WebChromeClientFlutterApi.Reply>() { + public void reply(List paths) { + final Uri[] uris = new Uri[paths.size()]; + for (int i = 0; i < uris.length; i++) { + uris[i] = Uri.fromFile(new File(paths.get(i))); + } + filePathCallback.onReceiveValue(uris); + } + }); + return true; + } + filePathCallback.onReceiveValue(null); + return true; + } + @Override public void onProgressChanged(WebView view, int progress) { if (flutterApi != null) { diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart index bd50640919f9..b65998d38a30 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart @@ -781,6 +781,10 @@ abstract class WebChromeClient { /// Notify the host application that a file should be downloaded. void onProgressChanged(WebView webView, int progress) {} + + Future> onShowFileChooser(WebView webView) async { + return []; + } } /// Encompasses parameters to the [WebViewClient.requestLoading] method. diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart index 4a0965eaeac0..772708d7062c 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart @@ -1,7 +1,3 @@ -// 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. - // Autogenerated from Pigeon (v1.0.9), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name @@ -1810,6 +1806,8 @@ abstract class WebChromeClientFlutterApi { void dispose(int instanceId); void onProgressChanged(int instanceId, int webViewInstanceId, int progress); + Future> onShowFileChooser( + int instanceId, int webViewInstanceId); static void setup(WebChromeClientFlutterApi? api, {BinaryMessenger? binaryMessenger}) { { @@ -1858,6 +1856,30 @@ abstract class WebChromeClientFlutterApi { }); } } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebChromeClientFlutterApi.onShowFileChooser', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebChromeClientFlutterApi.onShowFileChooser was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = (args[0] as int?); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebChromeClientFlutterApi.onShowFileChooser was null, expected non-null int.'); + final int? arg_webViewInstanceId = (args[1] as int?); + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebChromeClientFlutterApi.onShowFileChooser was null, expected non-null int.'); + final List output = await api.onShowFileChooser( + arg_instanceId!, arg_webViewInstanceId!); + return output; + }); + } + } } } diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart index 9c980c80d58d..dcd37dcadffe 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart @@ -786,6 +786,25 @@ class WebChromeClientFlutterApiImpl extends WebChromeClientFlutterApi { ); instance!.onProgressChanged(webViewInstance!, progress); } + + @override + Future> onShowFileChooser( + int instanceId, int webViewInstanceId) async { + final WebChromeClient? instance = + instanceManager.getInstance(instanceId) as WebChromeClient?; + final WebView? webViewInstance = + instanceManager.getInstance(webViewInstanceId) as WebView?; + assert( + instance != null, + 'InstanceManager does not contain an WebChromeClient with instanceId: $instanceId', + ); + assert( + webViewInstance != null, + 'InstanceManager does not contain an WebView with instanceId: $webViewInstanceId', + ); + // AFAIRE + return await instance!.onShowFileChooser(webViewInstance!); + } } /// Host api implementation for [WebStorage]. diff --git a/packages/webview_flutter/webview_flutter_android/lib/webview_android_widget.dart b/packages/webview_flutter/webview_flutter_android/lib/webview_android_widget.dart index 28d169c9cb94..edc9a7047ba4 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/webview_android_widget.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/webview_android_widget.dart @@ -389,6 +389,7 @@ class WebViewAndroidPlatformController extends WebViewPlatformController { } Future _setHasProgressTracking(bool hasProgressTracking) async { + webChromeClient._onShowFileChooser = callbacksHandler.onShowFileChooser; if (hasProgressTracking) { webChromeClient._onProgress = callbacksHandler.onProgress; } else { @@ -690,6 +691,7 @@ class WebViewAndroidWebViewClient extends android_webview.WebViewClient { class WebViewAndroidWebChromeClient extends android_webview.WebChromeClient { // Changed by WebViewAndroidPlatformController. void Function(int progress)? _onProgress; + Future> Function()? _onShowFileChooser; @override void onProgressChanged(android_webview.WebView webView, int progress) { @@ -697,6 +699,15 @@ class WebViewAndroidWebChromeClient extends android_webview.WebChromeClient { _onProgress!(progress); } } + + @override + Future> onShowFileChooser( + android_webview.WebView webView) async { + if (_onShowFileChooser != null) { + return await _onShowFileChooser!(); + } + return []; + } } /// Handles constructing [android_webview.WebView]s and calling static methods. diff --git a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart index d3d18f64f97d..b3e2bb2e33dd 100644 --- a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart +++ b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart @@ -221,6 +221,9 @@ abstract class WebChromeClientFlutterApi { void dispose(int instanceId); void onProgressChanged(int instanceId, int webViewInstanceId, int progress); + + @async + List onShowFileChooser(int instanceId, int webViewInstanceId); } @HostApi(dartHostTestHandler: 'TestWebStorageHostApi') diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart index 4ee4b1ddc0b7..88622969e388 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart @@ -1,7 +1,3 @@ -// 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. - // Autogenerated from Pigeon (v1.0.9), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import @@ -12,7 +8,7 @@ import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:webview_flutter_android/src/android_webview.pigeon.dart'; +import '../lib/src/android_webview.pigeon.dart'; class _TestWebViewHostApiCodec extends StandardMessageCodec { const _TestWebViewHostApiCodec(); diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart index bb2a4ac9fb50..b0ad5107112a 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart @@ -51,6 +51,8 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController { case 'onProgress': _platformCallbacksHandler.onProgress(call.arguments['progress'] as int); return null; + //case 'onShowFileChooser': + //return await _platformCallbacksHandler.onShowFileChooser(); case 'onPageStarted': _platformCallbacksHandler .onPageStarted(call.arguments['url']! as String); diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_callbacks_handler.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_callbacks_handler.dart index 44dae2ece434..414bac78fb5d 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_callbacks_handler.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_callbacks_handler.dart @@ -27,6 +27,8 @@ abstract class WebViewPlatformCallbacksHandler { /// /// Only works when [WebSettings.hasProgressTracking] is set to `true`. void onProgress(int progress); + Future> onShowFileChooser(); + /// Report web resource loading error to the host application. void onWebResourceError(WebResourceError error); }