From 459875ff2e6f3c6edb9cb4509a384b7c7464e852 Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Sat, 3 Dec 2022 15:58:12 +0100 Subject: [PATCH] Updated code docs, Using Android WebViewClientCompat for Chromium-based WebView if the WebView package major version is >= 73 (https://bugs.chromium.org/p/chromium/issues/detail?id=925887), fix #1422 --- CHANGELOG.md | 10 + .../InAppWebViewStatic.java | 30 +- .../types/WebResourceErrorExt.java | 16 + .../in_app_webview/FlutterWebView.java | 3 + .../webview/in_app_webview/InAppWebView.java | 46 +- .../InAppWebViewChromeClient.java | 4 +- .../in_app_webview/InAppWebViewClient.java | 11 +- .../InAppWebViewClientCompat.java | 841 ++++++ .../web_message/WebMessageListener.java | 11 +- .../lib/src/exchangeable_enum_generator.dart | 18 +- .../src/exchangeable_object_generator.dart | 22 +- .../ios/Flutter/flutter_export_environment.sh | 5 +- .../WebMessage/WebMessageListener.swift | 9 +- lib/src/android/webview_asset_loader.g.dart | 4 +- lib/src/android/webview_feature.g.dart | 124 +- .../chrome_safari_browser_settings.g.dart | 388 +-- .../in_app_browser_settings.g.dart | 246 +- .../headless_in_app_webview.dart | 85 +- lib/src/in_app_webview/in_app_webview.dart | 75 +- .../in_app_webview_settings.g.dart | 2340 ++++++++--------- lib/src/in_app_webview/webview.dart | 142 + lib/src/print_job/print_job_settings.g.dart | 746 +++--- .../pull_to_refresh_settings.g.dart | 66 +- lib/src/types/action_mode_menu_item.g.dart | 26 +- lib/src/types/activity_button.g.dart | 12 +- lib/src/types/ajax_request.dart | 2 +- lib/src/types/ajax_request.g.dart | 172 +- lib/src/types/ajax_request_event.g.dart | 14 +- lib/src/types/ajax_request_event_type.g.dart | 24 +- lib/src/types/ajax_request_ready_state.g.dart | 32 +- lib/src/types/android_resource.g.dart | 36 +- lib/src/types/attributed_string.g.dart | 32 +- lib/src/types/cache_mode.g.dart | 52 +- .../types/call_async_javascript_result.g.dart | 14 +- lib/src/types/client_cert_challenge.g.dart | 36 +- lib/src/types/client_cert_response.g.dart | 30 +- .../types/client_cert_response_action.g.dart | 12 +- lib/src/types/compress_format.g.dart | 32 +- lib/src/types/console_message_level.g.dart | 44 +- .../types/content_blocker_action_type.g.dart | 82 +- ...ontent_blocker_trigger_load_context.g.dart | 10 +- ...ntent_blocker_trigger_resource_type.g.dart | 24 +- lib/src/types/cookie.g.dart | 78 +- lib/src/types/create_window_action.g.dart | 28 +- .../types/css_link_html_tag_attributes.g.dart | 64 +- lib/src/types/custom_scheme_response.g.dart | 20 +- .../custom_tabs_navigation_event_type.g.dart | 78 +- .../types/custom_tabs_relation_type.g.dart | 36 +- lib/src/types/custom_tabs_share_state.g.dart | 12 +- lib/src/types/data_detector_types.g.dart | 124 +- lib/src/types/dismiss_button_style.g.dart | 40 +- lib/src/types/download_start_request.g.dart | 42 +- lib/src/types/favicon.g.dart | 26 +- lib/src/types/fetch_request.g.dart | 88 +- .../fetch_request_federated_credential.g.dart | 16 +- .../fetch_request_password_credential.g.dart | 14 +- lib/src/types/find_session.g.dart | 16 +- lib/src/types/force_dark.g.dart | 24 +- lib/src/types/force_dark_strategy.g.dart | 24 +- lib/src/types/form_resubmission_action.g.dart | 12 +- ...ion_permission_show_prompt_response.g.dart | 14 +- lib/src/types/http_auth_response.g.dart | 22 +- .../http_authentication_challenge.g.dart | 66 +- .../types/http_cookie_same_site_policy.g.dart | 12 +- .../in_app_webview_hit_test_result.g.dart | 14 +- ...in_app_webview_hit_test_result_type.g.dart | 44 +- .../types/in_app_webview_initial_data.g.dart | 46 +- lib/src/types/in_app_webview_rect.g.dart | 22 +- lib/src/types/js_alert_request.g.dart | 28 +- lib/src/types/js_alert_response.g.dart | 22 +- lib/src/types/js_before_unload_request.g.dart | 14 +- .../types/js_before_unload_response.g.dart | 38 +- .../js_before_unload_response_action.g.dart | 12 +- lib/src/types/js_confirm_request.g.dart | 28 +- lib/src/types/js_confirm_response.g.dart | 38 +- .../types/js_confirm_response_action.g.dart | 12 +- lib/src/types/js_prompt_request.g.dart | 30 +- lib/src/types/js_prompt_response.g.dart | 56 +- .../types/js_prompt_response_action.g.dart | 12 +- lib/src/types/layout_algorithm.dart | 3 +- lib/src/types/layout_algorithm.g.dart | 22 +- .../layout_in_display_cutout_mode.g.dart | 68 +- lib/src/types/loaded_resource.g.dart | 26 +- lib/src/types/login_request.g.dart | 14 +- lib/src/types/media_capture_state.g.dart | 12 +- lib/src/types/media_playback_state.g.dart | 12 +- lib/src/types/meta_tag.g.dart | 20 +- lib/src/types/mixed_content_mode.g.dart | 30 +- lib/src/types/modal_presentation_style.g.dart | 158 +- lib/src/types/modal_transition_style.g.dart | 28 +- lib/src/types/navigation_action.g.dart | 122 +- lib/src/types/navigation_action_policy.g.dart | 12 +- lib/src/types/navigation_response.g.dart | 44 +- .../types/navigation_response_action.g.dart | 24 +- lib/src/types/navigation_type.g.dart | 72 +- lib/src/types/permission_request.g.dart | 14 +- lib/src/types/permission_resource_type.g.dart | 112 +- lib/src/types/permission_response.g.dart | 30 +- lib/src/types/print_job_attributes.g.dart | 336 +-- lib/src/types/print_job_color_mode.g.dart | 40 +- lib/src/types/print_job_disposition.g.dart | 18 +- lib/src/types/print_job_duplex_mode.g.dart | 42 +- lib/src/types/print_job_info.g.dart | 158 +- lib/src/types/print_job_media_size.g.dart | 386 +-- lib/src/types/print_job_orientation.g.dart | 40 +- lib/src/types/print_job_output_type.g.dart | 16 +- lib/src/types/print_job_page_order.g.dart | 34 +- .../types/print_job_pagination_mode.g.dart | 30 +- lib/src/types/print_job_resolution.g.dart | 18 +- lib/src/types/print_job_state.g.dart | 182 +- lib/src/types/printer.g.dart | 20 +- lib/src/types/renderer_priority.g.dart | 14 +- .../request_focus_node_href_result.g.dart | 20 +- .../types/requested_with_header_mode.g.dart | 12 +- lib/src/types/safe_browsing_response.g.dart | 16 +- lib/src/types/safe_browsing_threat.g.dart | 32 +- lib/src/types/sandbox.g.dart | 10 +- lib/src/types/screenshot_configuration.g.dart | 54 +- .../types/script_html_tag_attributes.g.dart | 44 +- lib/src/types/scrollbar_style.g.dart | 58 +- ...w_content_inset_adjustment_behavior.g.dart | 64 +- .../types/scrollview_deceleration_rate.g.dart | 16 +- .../types/search_result_display_style.g.dart | 12 +- lib/src/types/selection_granularity.g.dart | 24 +- .../should_allow_deprecated_tls_action.g.dart | 24 +- lib/src/types/ssl_error.g.dart | 12 +- lib/src/types/ssl_error_type.g.dart | 314 +-- lib/src/types/tracing_mode.g.dart | 16 +- ...web_activity_immersive_display_mode.g.dart | 13 +- ...ted_web_activity_screen_orientation.g.dart | 76 +- lib/src/types/ui_event_attribution.g.dart | 20 +- lib/src/types/ui_image.g.dart | 12 +- lib/src/types/underline_style.g.dart | 112 +- lib/src/types/url_credential.g.dart | 40 +- .../types/url_credential_persistence.g.dart | 24 +- lib/src/types/url_protection_space.g.dart | 148 +- ...tection_space_http_auth_credentials.g.dart | 16 +- .../url_protection_space_proxy_type.g.dart | 36 +- lib/src/types/url_request.g.dart | 280 +- lib/src/types/url_request_cache_policy.g.dart | 116 +- .../url_request_network_service_type.g.dart | 138 +- lib/src/types/url_response.g.dart | 76 +- .../types/user_preferred_content_mode.g.dart | 20 +- lib/src/types/user_script.g.dart | 54 +- .../types/user_script_injection_time.g.dart | 16 +- .../web_authentication_session_error.g.dart | 14 +- lib/src/types/web_history.g.dart | 14 +- lib/src/types/web_history_item.g.dart | 24 +- lib/src/types/web_resource_error.g.dart | 14 +- lib/src/types/web_resource_error_type.g.dart | 1462 +++++----- lib/src/types/web_resource_request.g.dart | 48 +- lib/src/types/web_resource_response.g.dart | 36 +- lib/src/types/website_data_record.g.dart | 28 +- lib/src/types/website_data_type.g.dart | 218 +- lib/src/types/webview_package_info.g.dart | 28 +- lib/src/types/window_style_mask.g.dart | 126 +- .../window_titlebar_separator_style.g.dart | 36 +- lib/src/web_message/web_message_listener.dart | 10 +- .../WebMessage/WebMessageListener.swift | 9 +- package.json | 4 +- pubspec.yaml | 2 +- 161 files changed, 7290 insertions(+), 6065 deletions(-) create mode 100755 android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewClientCompat.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 77ca8556..9837682e 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.0.0-beta.20 + +- Using Android `WebViewClientCompat` for Chromium-based WebView if the WebView package major version is >= 73 (https://bugs.chromium.org/p/chromium/issues/detail?id=925887) +- Updated code docs +- Fixed "Unexpected addWebMessageListener behaviour" [#1422](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1422) + ## 6.0.0-beta.19 - Updated code docs @@ -164,6 +170,10 @@ - Removed `URLProtectionSpace.iosIsProxy` property - `historyUrl` and `baseUrl` of `InAppWebViewInitialData` can be `null` +## 5.7.2+2 + +- Fixed "Unexpected addWebMessageListener behaviour" [#1422](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1422) + ## 5.7.2+1 - Fixed "Cannot Grant Permission at Android 21" [#1447](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1447) diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewStatic.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewStatic.java index 5b53a048..aadb6d79 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewStatic.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewStatic.java @@ -1,5 +1,6 @@ package com.pichillilorenzo.flutter_inappwebview; +import android.annotation.SuppressLint; import android.content.Context; import android.content.pm.PackageInfo; import android.os.Build; @@ -82,28 +83,15 @@ public class InAppWebViewStatic extends ChannelDelegateImpl { result.success(false); break; case "getCurrentWebViewPackage": - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && plugin != null && (plugin.activity != null || plugin.applicationContext != null)) { - Context context = plugin.activity; + Context context = null; + if (plugin != null) { + context = plugin.activity; if (context == null) { context = plugin.applicationContext; } - result.success(convertWebViewPackageToMap(WebViewCompat.getCurrentWebViewPackage(context))); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - //with Android Lollipop (API 21) they started to update the WebView - //as a separate APK with the PlayStore and they added the - //getLoadedPackageInfo() method to the WebViewFactory class and this - //should handle the Android 7.0 behaviour changes too - try { - Class webViewFactory = Class.forName("android.webkit.WebViewFactory"); - Method method = webViewFactory.getMethod("getLoadedPackageInfo"); - PackageInfo pInfo = (PackageInfo) method.invoke(null); - result.success(convertWebViewPackageToMap(pInfo)); - } catch (Exception e) { - result.success(null); - } - } else { - result.success(null); } + PackageInfo packageInfo = context != null ? WebViewCompat.getCurrentWebViewPackage(context) : null; + result.success(packageInfo != null ? convertWebViewPackageToMap(packageInfo) : null); break; case "setWebContentsDebuggingEnabled": { @@ -135,10 +123,8 @@ public class InAppWebViewStatic extends ChannelDelegateImpl { } } - public Map convertWebViewPackageToMap(PackageInfo webViewPackageInfo) { - if (webViewPackageInfo == null) { - return null; - } + @NonNull + public Map convertWebViewPackageToMap(@NonNull PackageInfo webViewPackageInfo) { HashMap webViewPackageInfoMap = new HashMap<>(); webViewPackageInfoMap.put("versionName", webViewPackageInfo.versionName); diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/WebResourceErrorExt.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/WebResourceErrorExt.java index 7da98f8a..007f26d6 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/WebResourceErrorExt.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/WebResourceErrorExt.java @@ -2,9 +2,12 @@ package com.pichillilorenzo.flutter_inappwebview.types; import android.os.Build; import android.webkit.WebResourceError; +import android.webkit.WebView; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; +import androidx.webkit.WebResourceErrorCompat; +import androidx.webkit.WebViewFeature; import java.util.HashMap; import java.util.Map; @@ -24,6 +27,19 @@ public class WebResourceErrorExt { return new WebResourceErrorExt(error.getErrorCode(), error.getDescription().toString()); } + @RequiresApi(Build.VERSION_CODES.M) + static public WebResourceErrorExt fromWebResourceError(@NonNull WebResourceErrorCompat error) { + int type = -1; + if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE)) { + type = error.getErrorCode(); + } + String description = ""; + if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION)) { + description = error.getDescription().toString(); + } + return new WebResourceErrorExt(type, description); + } + public Map toMap() { Map webResourceErrorMap = new HashMap<>(); webResourceErrorMap.put("type", getType()); diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/FlutterWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/FlutterWebView.java index 32f0d39e..5e0b1c74 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/FlutterWebView.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/FlutterWebView.java @@ -146,6 +146,9 @@ public class FlutterWebView implements PlatformWebView { if (webView.inAppWebViewChromeClient != null) { webView.inAppWebViewChromeClient.dispose(); } + if (webView.inAppWebViewClientCompat != null) { + webView.inAppWebViewClientCompat.dispose(); + } if (webView.inAppWebViewClient != null) { webView.inAppWebViewClient.dispose(); } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebView.java index ad24f259..2eafe26c 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebView.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebView.java @@ -8,6 +8,7 @@ import android.animation.PropertyValuesHolder; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.content.Context; +import android.content.pm.PackageInfo; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -47,6 +48,7 @@ import android.webkit.WebBackForwardList; import android.webkit.WebHistoryItem; import android.webkit.WebSettings; import android.webkit.WebStorage; +import android.webkit.WebViewClient; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import android.widget.TextView; @@ -59,6 +61,7 @@ import androidx.webkit.WebViewCompat; import androidx.webkit.WebViewFeature; import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin; +import com.pichillilorenzo.flutter_inappwebview.InAppWebViewStatic; import com.pichillilorenzo.flutter_inappwebview.R; import com.pichillilorenzo.flutter_inappwebview.Util; import com.pichillilorenzo.flutter_inappwebview.content_blocker.ContentBlocker; @@ -124,6 +127,8 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie @Nullable public InAppWebViewClient inAppWebViewClient; @Nullable + public InAppWebViewClientCompat inAppWebViewClientCompat; + @Nullable public InAppWebViewChromeClient inAppWebViewChromeClient; @Nullable public InAppWebViewRenderProcessClient inAppWebViewRenderProcessClient; @@ -199,6 +204,36 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie } } + public WebViewClient createWebViewClient(InAppBrowserDelegate inAppBrowserDelegate) { + // bug https://bugs.chromium.org/p/chromium/issues/detail?id=925887 + PackageInfo packageInfo = WebViewCompat.getCurrentWebViewPackage(getContext()); + if (packageInfo == null) { + Log.d(LOG_TAG, "Using InAppWebViewClient implementation"); + return new InAppWebViewClient(inAppBrowserDelegate); + } + + boolean isChromiumWebView = "com.android.webview".equals(packageInfo.packageName) || + "com.google.android.webview".equals(packageInfo.packageName) || + "com.android.chrome".equals(packageInfo.packageName); + boolean isChromiumWebViewBugFixed = false; + if (isChromiumWebView) { + String versionName = packageInfo.versionName != null ? packageInfo.versionName : ""; + try { + int majorVersion = versionName.contains(".") ? + Integer.parseInt(versionName.split("\\.")[0]) : 0; + isChromiumWebViewBugFixed = majorVersion >= 73; + } catch (NumberFormatException ignored) {} + } + + if (isChromiumWebViewBugFixed || !isChromiumWebView) { + Log.d(LOG_TAG, "Using InAppWebViewClientCompat implementation"); + return new InAppWebViewClientCompat(inAppBrowserDelegate); + } else { + Log.d(LOG_TAG, "Using InAppWebViewClient implementation"); + return new InAppWebViewClient(inAppBrowserDelegate); + } + } + @SuppressLint("RestrictedApi") public void prepare() { if (plugin != null) { @@ -211,8 +246,14 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie inAppWebViewChromeClient = new InAppWebViewChromeClient(plugin, this, inAppBrowserDelegate); setWebChromeClient(inAppWebViewChromeClient); - inAppWebViewClient = new InAppWebViewClient(inAppBrowserDelegate); - setWebViewClient(inAppWebViewClient); + WebViewClient webViewClient = createWebViewClient(inAppBrowserDelegate); + if (webViewClient instanceof InAppWebViewClientCompat) { + inAppWebViewClientCompat = (InAppWebViewClientCompat) webViewClient; + setWebViewClient(inAppWebViewClientCompat); + } else if (webViewClient instanceof InAppWebViewClient) { + inAppWebViewClient = (InAppWebViewClient) webViewClient; + setWebViewClient(inAppWebViewClient); + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && WebViewFeature.isFeatureSupported(WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE)) { inAppWebViewRenderProcessClient = new InAppWebViewRenderProcessClient(); @@ -1982,6 +2023,7 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie evaluateJavaScriptContentWorldCallbacks.clear(); inAppBrowserDelegate = null; inAppWebViewChromeClient = null; + inAppWebViewClientCompat = null; inAppWebViewClient = null; javaScriptBridgeInterface = null; inAppWebViewRenderProcessClient = null; diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewChromeClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewChromeClient.java index 5834cebd..6cb450a7 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewChromeClient.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewChromeClient.java @@ -731,7 +731,9 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR InAppWebView webView = (InAppWebView) view; - if (webView.inAppWebViewClient != null) { + if (webView.inAppWebViewClientCompat != null) { + webView.inAppWebViewClientCompat.loadCustomJavaScriptOnPageStarted(view); + } else if (webView.inAppWebViewClient != null) { webView.inAppWebViewClient.loadCustomJavaScriptOnPageStarted(view); } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewClient.java index 0fb32b9f..7e52593c 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewClient.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewClient.java @@ -114,7 +114,9 @@ public class InAppWebViewClient extends WebViewClient { return false; } - private void allowShouldOverrideUrlLoading(WebView webView, String url, Map headers, boolean isForMainFrame) { + private void allowShouldOverrideUrlLoading(WebView webView, String url, + @Nullable Map headers, + boolean isForMainFrame) { if (isForMainFrame) { // There isn't any way to load an URL for a frame that is not the main frame, // so call this only on main frame. @@ -124,8 +126,11 @@ public class InAppWebViewClient extends WebViewClient { webView.loadUrl(url); } } - public void onShouldOverrideUrlLoading(final InAppWebView webView, final String url, final String method, final Map headers, - final boolean isForMainFrame, boolean hasGesture, boolean isRedirect) { + public void onShouldOverrideUrlLoading(final InAppWebView webView, final String url, + final String method, + @Nullable final Map headers, + final boolean isForMainFrame, boolean hasGesture, + boolean isRedirect) { URLRequest request = new URLRequest(url, method, null, headers); NavigationAction navigationAction = new NavigationAction( request, diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewClientCompat.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewClientCompat.java new file mode 100755 index 00000000..64d858b4 --- /dev/null +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/in_app_webview/InAppWebViewClientCompat.java @@ -0,0 +1,841 @@ +package com.pichillilorenzo.flutter_inappwebview.webview.in_app_webview; + +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.graphics.Bitmap; +import android.net.Uri; +import android.net.http.SslError; +import android.os.Build; +import android.os.Message; +import android.util.Log; +import android.view.KeyEvent; +import android.webkit.ClientCertRequest; +import android.webkit.CookieManager; +import android.webkit.CookieSyncManager; +import android.webkit.HttpAuthHandler; +import android.webkit.RenderProcessGoneDetail; +import android.webkit.SslErrorHandler; +import android.webkit.ValueCallback; +import android.webkit.WebResourceRequest; +import android.webkit.WebResourceResponse; +import android.webkit.WebView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import androidx.webkit.SafeBrowsingResponseCompat; +import androidx.webkit.WebResourceErrorCompat; +import androidx.webkit.WebResourceRequestCompat; +import androidx.webkit.WebViewClientCompat; +import androidx.webkit.WebViewFeature; + +import com.pichillilorenzo.flutter_inappwebview.Util; +import com.pichillilorenzo.flutter_inappwebview.credential_database.CredentialDatabase; +import com.pichillilorenzo.flutter_inappwebview.in_app_browser.InAppBrowserDelegate; +import com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js.JavaScriptBridgeJS; +import com.pichillilorenzo.flutter_inappwebview.types.ClientCertChallenge; +import com.pichillilorenzo.flutter_inappwebview.types.ClientCertResponse; +import com.pichillilorenzo.flutter_inappwebview.types.CustomSchemeResponse; +import com.pichillilorenzo.flutter_inappwebview.types.HttpAuthResponse; +import com.pichillilorenzo.flutter_inappwebview.types.HttpAuthenticationChallenge; +import com.pichillilorenzo.flutter_inappwebview.types.NavigationAction; +import com.pichillilorenzo.flutter_inappwebview.types.NavigationActionPolicy; +import com.pichillilorenzo.flutter_inappwebview.types.ServerTrustAuthResponse; +import com.pichillilorenzo.flutter_inappwebview.types.ServerTrustChallenge; +import com.pichillilorenzo.flutter_inappwebview.types.URLCredential; +import com.pichillilorenzo.flutter_inappwebview.types.URLProtectionSpace; +import com.pichillilorenzo.flutter_inappwebview.types.URLRequest; +import com.pichillilorenzo.flutter_inappwebview.types.WebResourceErrorExt; +import com.pichillilorenzo.flutter_inappwebview.types.WebResourceRequestExt; +import com.pichillilorenzo.flutter_inappwebview.types.WebResourceResponseExt; +import com.pichillilorenzo.flutter_inappwebview.webview.WebViewChannelDelegate; + +import java.io.ByteArrayInputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; + +public class InAppWebViewClientCompat extends WebViewClientCompat { + + protected static final String LOG_TAG = "IAWebViewClientCompat"; + private InAppBrowserDelegate inAppBrowserDelegate; + private static int previousAuthRequestFailureCount = 0; + private static List credentialsProposed = null; + + public InAppWebViewClientCompat(InAppBrowserDelegate inAppBrowserDelegate) { + super(); + this.inAppBrowserDelegate = inAppBrowserDelegate; + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Override + public boolean shouldOverrideUrlLoading(@NonNull WebView view, @NonNull WebResourceRequest request) { + InAppWebView webView = (InAppWebView) view; + if (webView.customSettings.useShouldOverrideUrlLoading) { + boolean isRedirect = false; + if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT)) { + isRedirect = WebResourceRequestCompat.isRedirect(request); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + isRedirect = request.isRedirect(); + } + onShouldOverrideUrlLoading( + webView, + request.getUrl().toString(), + request.getMethod(), + request.getRequestHeaders(), + request.isForMainFrame(), + request.hasGesture(), + isRedirect); + if (webView.regexToCancelSubFramesLoadingCompiled != null) { + if (request.isForMainFrame()) + return true; + else { + Matcher m = webView.regexToCancelSubFramesLoadingCompiled.matcher(request.getUrl().toString()); + return m.matches(); + } + } else { + // There isn't any way to load an URL for a frame that is not the main frame, + // so if the request is not for the main frame, the navigation is allowed. + return request.isForMainFrame(); + } + } + return false; + } + + @Override + public boolean shouldOverrideUrlLoading(WebView webView, String url) { + InAppWebView inAppWebView = (InAppWebView) webView; + if (inAppWebView.customSettings.useShouldOverrideUrlLoading) { + onShouldOverrideUrlLoading(inAppWebView, url, "GET", null,true, false, false); + return true; + } + return false; + } + + private void allowShouldOverrideUrlLoading(WebView webView, String url, + @Nullable Map headers, + boolean isForMainFrame) { + if (isForMainFrame) { + // There isn't any way to load an URL for a frame that is not the main frame, + // so call this only on main frame. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + webView.loadUrl(url, headers); + else + webView.loadUrl(url); + } + } + public void onShouldOverrideUrlLoading(final InAppWebView webView, final String url, + final String method, + @Nullable final Map headers, + final boolean isForMainFrame, boolean hasGesture, + boolean isRedirect) { + URLRequest request = new URLRequest(url, method, null, headers); + NavigationAction navigationAction = new NavigationAction( + request, + isForMainFrame, + hasGesture, + isRedirect + ); + + final WebViewChannelDelegate.ShouldOverrideUrlLoadingCallback callback = new WebViewChannelDelegate.ShouldOverrideUrlLoadingCallback() { + @Override + public boolean nonNullSuccess(@NonNull NavigationActionPolicy result) { + switch (result) { + case ALLOW: + allowShouldOverrideUrlLoading(webView, url, headers, isForMainFrame); + break; + case CANCEL: + default: + break; + } + return false; + } + + @Override + public void defaultBehaviour(@Nullable NavigationActionPolicy result) { + allowShouldOverrideUrlLoading(webView, url, headers, isForMainFrame); + } + + @Override + public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) { + Log.e(LOG_TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + defaultBehaviour(null); + } + }; + + if (webView.channelDelegate != null) { + webView.channelDelegate.shouldOverrideUrlLoading(navigationAction, callback); + } else { + callback.defaultBehaviour(null); + } + } + + @SuppressLint("RestrictedApi") + public void loadCustomJavaScriptOnPageStarted(WebView view) { + InAppWebView webView = (InAppWebView) view; + + if (!WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)) { + String source = webView.userContentController.generateWrappedCodeForDocumentStart(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + webView.evaluateJavascript(source, (ValueCallback) null); + } else { + webView.loadUrl("javascript:" + source.replaceAll("[\r\n]+", "")); + } + } + } + + public void loadCustomJavaScriptOnPageFinished(WebView view) { + InAppWebView webView = (InAppWebView) view; + + String source = webView.userContentController.generateWrappedCodeForDocumentEnd(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + webView.evaluateJavascript(source, (ValueCallback) null); + } else { + webView.loadUrl("javascript:" + source.replaceAll("[\r\n]+", "")); + } + } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + final InAppWebView webView = (InAppWebView) view; + webView.isLoading = true; + webView.disposeWebMessageChannels(); + webView.userContentController.resetContentWorlds(); + loadCustomJavaScriptOnPageStarted(webView); + + super.onPageStarted(view, url, favicon); + + if (inAppBrowserDelegate != null) { + inAppBrowserDelegate.didStartNavigation(url); + } + + if (webView.channelDelegate != null) { + webView.channelDelegate.onLoadStart(url); + } + } + + public void onPageFinished(WebView view, String url) { + final InAppWebView webView = (InAppWebView) view; + webView.isLoading = false; + loadCustomJavaScriptOnPageFinished(webView); + previousAuthRequestFailureCount = 0; + credentialsProposed = null; + + super.onPageFinished(view, url); + + if (inAppBrowserDelegate != null) { + inAppBrowserDelegate.didFinishNavigation(url); + } + + // WebView not storing cookies reliable to local device storage + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + CookieManager.getInstance().flush(); + } else { + CookieSyncManager.getInstance().sync(); + } + + String js = JavaScriptBridgeJS.PLATFORM_READY_JS_SOURCE; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + webView.evaluateJavascript(js, (ValueCallback) null); + } else { + webView.loadUrl("javascript:" + js.replaceAll("[\r\n]+", "")); + } + + if (webView.channelDelegate != null) { + webView.channelDelegate.onLoadStop(url); + } + } + + @Override + public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) { + super.doUpdateVisitedHistory(view, url, isReload); + + // url argument sometimes doesn't contain the new changed URL, so we get it again from the webview. + url = view.getUrl(); + + if (inAppBrowserDelegate != null) { + inAppBrowserDelegate.didUpdateVisitedHistory(url); + } + + final InAppWebView webView = (InAppWebView) view; + if (webView.channelDelegate != null) { + webView.channelDelegate.onUpdateVisitedHistory(url, isReload); + } + } + + @RequiresApi(api = Build.VERSION_CODES.M) + @Override + public void onReceivedError(@NonNull WebView view, + @NonNull WebResourceRequest request, + @NonNull WebResourceErrorCompat error) { + final InAppWebView webView = (InAppWebView) view; + + if (request.isForMainFrame()) { + if (webView.customSettings.disableDefaultErrorPage) { + webView.stopLoading(); + webView.loadUrl("about:blank"); + } + + webView.isLoading = false; + previousAuthRequestFailureCount = 0; + credentialsProposed = null; + + if (inAppBrowserDelegate != null) { + int type = -1; + if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE)) { + type = error.getErrorCode(); + } + String description = ""; + if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION)) { + description = error.getDescription().toString(); + } + inAppBrowserDelegate.didFailNavigation(request.getUrl().toString(), type, description); + } + } + + if (webView.channelDelegate != null) { + webView.channelDelegate.onReceivedError( + WebResourceRequestExt.fromWebResourceRequest(request), + WebResourceErrorExt.fromWebResourceError(error)); + } + } + + @SuppressLint("RestrictedApi") + @Override + public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { + final InAppWebView webView = (InAppWebView) view; + + if (!WebViewFeature.isFeatureSupported(WebViewFeature.SUPPRESS_ERROR_PAGE) && + webView.customSettings.disableDefaultErrorPage) { + webView.stopLoading(); + webView.loadUrl("about:blank"); + } + + webView.isLoading = false; + previousAuthRequestFailureCount = 0; + credentialsProposed = null; + + if (inAppBrowserDelegate != null) { + inAppBrowserDelegate.didFailNavigation(failingUrl, errorCode, description); + } + + WebResourceRequestExt request = new WebResourceRequestExt( + failingUrl, + null, + false, + false, + true, + "GET"); + + WebResourceErrorExt error = new WebResourceErrorExt( + errorCode, + description + ); + + if (webView.channelDelegate != null) { + webView.channelDelegate.onReceivedError( + request, + error); + } + + super.onReceivedError(view, errorCode, description, failingUrl); + } + + @RequiresApi(api = Build.VERSION_CODES.M) + @Override + public void onReceivedHttpError(@NonNull WebView view, + @NonNull WebResourceRequest request, + @NonNull WebResourceResponse errorResponse) { + super.onReceivedHttpError(view, request, errorResponse); + + final InAppWebView webView = (InAppWebView) view; + if (webView.channelDelegate != null) { + webView.channelDelegate.onReceivedHttpError( + WebResourceRequestExt.fromWebResourceRequest(request), + WebResourceResponseExt.fromWebResourceResponse(errorResponse)); + } + } + + @Override + public void onReceivedHttpAuthRequest(final WebView view, final HttpAuthHandler handler, final String host, final String realm) { + final String url = view.getUrl(); + String protocol = "https"; + int port = 0; + + if (url != null) { + try { + URI uri = new URI(url); + protocol = uri.getScheme(); + port = uri.getPort(); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + } + + previousAuthRequestFailureCount++; + + if (credentialsProposed == null) + credentialsProposed = CredentialDatabase.getInstance(view.getContext()).getHttpAuthCredentials(host, protocol, realm, port); + + URLCredential credentialProposed = null; + if (credentialsProposed != null && credentialsProposed.size() > 0) { + credentialProposed = credentialsProposed.get(0); + } + + URLProtectionSpace protectionSpace = new URLProtectionSpace(host, protocol, realm, port, view.getCertificate(), null); + HttpAuthenticationChallenge challenge = new HttpAuthenticationChallenge(protectionSpace, previousAuthRequestFailureCount, credentialProposed); + + final InAppWebView webView = (InAppWebView) view; + final String finalProtocol = protocol; + final int finalPort = port; + final WebViewChannelDelegate.ReceivedHttpAuthRequestCallback callback = new WebViewChannelDelegate.ReceivedHttpAuthRequestCallback() { + @Override + public boolean nonNullSuccess(@NonNull HttpAuthResponse response) { + Integer action = response.getAction(); + if (action != null) { + switch (action) { + case 1: + String username = response.getUsername(); + String password = response.getPassword(); + boolean permanentPersistence = response.isPermanentPersistence(); + if (permanentPersistence) { + CredentialDatabase.getInstance(view.getContext()) + .setHttpAuthCredential(host, finalProtocol, realm, finalPort, username, password); + } + handler.proceed(username, password); + break; + case 2: + if (credentialsProposed.size() > 0) { + URLCredential credential = credentialsProposed.remove(0); + handler.proceed(credential.getUsername(), credential.getPassword()); + } else { + handler.cancel(); + } + // used custom CredentialDatabase! + // handler.useHttpAuthUsernamePassword(); + break; + case 0: + default: + credentialsProposed = null; + previousAuthRequestFailureCount = 0; + handler.cancel(); + } + + return false; + } + + return true; + } + + @Override + public void defaultBehaviour(@Nullable HttpAuthResponse result) { + InAppWebViewClientCompat.super.onReceivedHttpAuthRequest(view, handler, host, realm); + } + + @Override + public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) { + Log.e(LOG_TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + defaultBehaviour(null); + } + }; + + if (webView.channelDelegate != null) { + webView.channelDelegate.onReceivedHttpAuthRequest(challenge, callback); + } else { + callback.defaultBehaviour(null); + } + } + + @Override + public void onReceivedSslError(final WebView view, final SslErrorHandler handler, final SslError sslError) { + final String url = sslError.getUrl(); + String host = ""; + String protocol = "https"; + int port = 0; + + try { + URI uri = new URI(url); + host = uri.getHost(); + protocol = uri.getScheme(); + port = uri.getPort(); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + + URLProtectionSpace protectionSpace = new URLProtectionSpace(host, protocol, null, port, sslError.getCertificate(), sslError); + ServerTrustChallenge challenge = new ServerTrustChallenge(protectionSpace); + + final InAppWebView webView = (InAppWebView) view; + final WebViewChannelDelegate.ReceivedServerTrustAuthRequestCallback callback = new WebViewChannelDelegate.ReceivedServerTrustAuthRequestCallback() { + @Override + public boolean nonNullSuccess(@NonNull ServerTrustAuthResponse response) { + Integer action = response.getAction(); + if (action != null) { + switch (action) { + case 1: + handler.proceed(); + break; + case 0: + default: + handler.cancel(); + } + + return false; + } + + return true; + } + + @Override + public void defaultBehaviour(@Nullable ServerTrustAuthResponse result) { + InAppWebViewClientCompat.super.onReceivedSslError(view, handler, sslError); + } + + @Override + public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) { + Log.e(LOG_TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + defaultBehaviour(null); + } + }; + + if (webView.channelDelegate != null) { + webView.channelDelegate.onReceivedServerTrustAuthRequest(challenge, callback); + } else { + callback.defaultBehaviour(null); + } + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + @Override + public void onReceivedClientCertRequest(final WebView view, final ClientCertRequest request) { + final String url = view.getUrl(); + final String host = request.getHost(); + String protocol = "https"; + final int port = request.getPort(); + + if (url != null) { + try { + URI uri = new URI(url); + protocol = uri.getScheme(); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + } + + URLProtectionSpace protectionSpace = new URLProtectionSpace(host, protocol, null, port, view.getCertificate(), null); + ClientCertChallenge challenge = new ClientCertChallenge(protectionSpace, request.getPrincipals(), request.getKeyTypes()); + + final InAppWebView webView = (InAppWebView) view; + final WebViewChannelDelegate.ReceivedClientCertRequestCallback callback = new WebViewChannelDelegate.ReceivedClientCertRequestCallback() { + @Override + public boolean nonNullSuccess(@NonNull ClientCertResponse response) { + Integer action = response.getAction(); + if (action != null && webView.plugin != null) { + switch (action) { + case 1: + { + String certificatePath = (String) response.getCertificatePath(); + String certificatePassword = (String) response.getCertificatePassword(); + String keyStoreType = (String) response.getKeyStoreType(); + Util.PrivateKeyAndCertificates privateKeyAndCertificates = + Util.loadPrivateKeyAndCertificate(webView.plugin, certificatePath, certificatePassword, keyStoreType); + if (privateKeyAndCertificates != null) { + request.proceed(privateKeyAndCertificates.privateKey, privateKeyAndCertificates.certificates); + } else { + request.cancel(); + } + } + break; + case 2: + request.ignore(); + break; + case 0: + default: + request.cancel(); + } + + return false; + } + + return true; + } + + @Override + public void defaultBehaviour(@Nullable ClientCertResponse result) { + InAppWebViewClientCompat.super.onReceivedClientCertRequest(view, request); + } + + @Override + public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) { + Log.e(LOG_TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + defaultBehaviour(null); + } + }; + + if (webView.channelDelegate != null) { + webView.channelDelegate.onReceivedClientCertRequest(challenge, callback); + } else { + callback.defaultBehaviour(null); + } + } + + @Override + public void onScaleChanged(WebView view, float oldScale, float newScale) { + super.onScaleChanged(view, oldScale, newScale); + final InAppWebView webView = (InAppWebView) view; + webView.zoomScale = newScale / Util.getPixelDensity(webView.getContext()); + + if (webView.channelDelegate != null) { + webView.channelDelegate.onZoomScaleChanged(oldScale, newScale); + } + } + + @RequiresApi(api = Build.VERSION_CODES.O_MR1) + @Override + public void onSafeBrowsingHit(@NonNull final WebView view, + @NonNull final WebResourceRequest request, + final int threatType, + @NonNull final SafeBrowsingResponseCompat callback) { + final InAppWebView webView = (InAppWebView) view; + final WebViewChannelDelegate.SafeBrowsingHitCallback resultCallback = new WebViewChannelDelegate.SafeBrowsingHitCallback() { + @Override + public boolean nonNullSuccess(@NonNull com.pichillilorenzo.flutter_inappwebview.types.SafeBrowsingResponse response) { + Integer action = response.getAction(); + if (action != null) { + boolean report = response.isReport(); + switch (action) { + case 0: + if (WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY)) { + callback.backToSafety(report); + } else { + return true; + } + break; + case 1: + if (WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED)) { + callback.proceed(report); + } else { + return true; + } + break; + case 2: + default: + if (WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL)) { + callback.showInterstitial(report); + } else { + return true; + } + } + + return false; + } + + return true; + } + + @Override + public void defaultBehaviour(@Nullable com.pichillilorenzo.flutter_inappwebview.types.SafeBrowsingResponse result) { + InAppWebViewClientCompat.super.onSafeBrowsingHit(view, request, threatType, callback); + } + + @Override + public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) { + Log.e(LOG_TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + defaultBehaviour(null); + } + }; + + if (webView.channelDelegate != null) { + webView.channelDelegate.onSafeBrowsingHit(request.getUrl().toString(), threatType, resultCallback); + } else { + resultCallback.defaultBehaviour(null); + } + } + + public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequestExt request) { + final InAppWebView webView = (InAppWebView) view; + + if (webView.webViewAssetLoaderExt != null && webView.webViewAssetLoaderExt.loader != null) { + try { + final Uri uri = Uri.parse(request.getUrl()); + WebResourceResponse webResourceResponse = webView.webViewAssetLoaderExt.loader.shouldInterceptRequest(uri); + if (webResourceResponse != null) { + return webResourceResponse; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (webView.customSettings.useShouldInterceptRequest) { + WebResourceResponseExt response = null; + if (webView.channelDelegate != null) { + try { + response = webView.channelDelegate.shouldInterceptRequest(request); + } catch (InterruptedException e) { + e.printStackTrace(); + return null; + } + } + + if (response != null) { + String contentType = response.getContentType(); + String contentEncoding = response.getContentEncoding(); + byte[] data = response.getData(); + Map responseHeaders = response.getHeaders(); + Integer statusCode = response.getStatusCode(); + String reasonPhrase = response.getReasonPhrase(); + + ByteArrayInputStream inputStream = (data != null) ? new ByteArrayInputStream(data) : null; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && statusCode != null && reasonPhrase != null) { + return new WebResourceResponse(contentType, contentEncoding, statusCode, reasonPhrase, responseHeaders, inputStream); + } else { + return new WebResourceResponse(contentType, contentEncoding, inputStream); + } + } + + return null; + } + + final String url = request.getUrl(); + String scheme = url.split(":")[0].toLowerCase(); + try { + scheme = Uri.parse(request.getUrl()).getScheme(); + } catch (Exception ignored) {} + + if (webView.customSettings.resourceCustomSchemes != null && webView.customSettings.resourceCustomSchemes.contains(scheme)) { + CustomSchemeResponse customSchemeResponse = null; + if (webView.channelDelegate != null) { + try { + customSchemeResponse = webView.channelDelegate.onLoadResourceWithCustomScheme(request); + } catch (InterruptedException e) { + e.printStackTrace(); + return null; + } + } + + if (customSchemeResponse != null) { + WebResourceResponse response = null; + try { + response = webView.contentBlockerHandler.checkUrl(webView, request, customSchemeResponse.getContentType()); + } catch (Exception e) { + e.printStackTrace(); + } + if (response != null) + return response; + return new WebResourceResponse(customSchemeResponse.getContentType(), + customSchemeResponse.getContentType(), + new ByteArrayInputStream(customSchemeResponse.getData())); + } + } + + WebResourceResponse response = null; + if (webView.contentBlockerHandler.getRuleList().size() > 0) { + try { + response = webView.contentBlockerHandler.checkUrl(webView, request); + } catch (Exception e) { + e.printStackTrace(); + } + } + return response; + } + + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, final String url) { + WebResourceRequestExt requestExt = new WebResourceRequestExt( + url, null, false, + false, true, "GET" + ); + return shouldInterceptRequest(view, requestExt); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { + WebResourceRequestExt requestExt = WebResourceRequestExt.fromWebResourceRequest(request); + return shouldInterceptRequest(view, requestExt); + } + + @Override + public void onFormResubmission(final WebView view, final Message dontResend, final Message resend) { + final InAppWebView webView = (InAppWebView) view; + final WebViewChannelDelegate.FormResubmissionCallback callback = new WebViewChannelDelegate.FormResubmissionCallback() { + @Override + public boolean nonNullSuccess(@NonNull Integer action) { + switch (action) { + case 0: + resend.sendToTarget(); + break; + case 1: + default: + dontResend.sendToTarget(); + } + return false; + } + + @Override + public void defaultBehaviour(@Nullable Integer result) { + InAppWebViewClientCompat.super.onFormResubmission(view, dontResend, resend); + } + + @Override + public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) { + Log.e(LOG_TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + defaultBehaviour(null); + } + }; + + if (webView.channelDelegate != null) { + webView.channelDelegate.onFormResubmission(webView.getUrl(), callback); + } else { + callback.defaultBehaviour(null); + } + } + + @Override + public void onPageCommitVisible(@NonNull WebView view, @NonNull String url) { + super.onPageCommitVisible(view, url); + + final InAppWebView webView = (InAppWebView) view; + if (webView.channelDelegate != null) { + webView.channelDelegate.onPageCommitVisible(url); + } + } + + @RequiresApi(api = Build.VERSION_CODES.O) + @Override + public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) { + final InAppWebView webView = (InAppWebView) view; + + if (webView.customSettings.useOnRenderProcessGone && webView.channelDelegate != null) { + boolean didCrash = detail.didCrash(); + int rendererPriorityAtExit = detail.rendererPriorityAtExit(); + webView.channelDelegate.onRenderProcessGone(didCrash, rendererPriorityAtExit); + return true; + } + + return super.onRenderProcessGone(view, detail); + } + + @Override + public void onReceivedLoginRequest(WebView view, String realm, String account, String args) { + final InAppWebView webView = (InAppWebView) view; + if (webView.channelDelegate != null) { + webView.channelDelegate.onReceivedLoginRequest(realm, account, args); + } + } + + @Override + public void onUnhandledKeyEvent(WebView view, KeyEvent event) {} + + public void dispose() { + if (inAppBrowserDelegate != null) { + inAppBrowserDelegate = null; + } + } +} diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/web_message/WebMessageListener.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/web_message/WebMessageListener.java index 1d7dbf80..d36a9966 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/web_message/WebMessageListener.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/webview/web_message/WebMessageListener.java @@ -33,6 +33,8 @@ public class WebMessageListener implements Disposable { protected static final String LOG_TAG = "WebMessageListener"; public static final String METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_web_message_listener_"; + @NonNull + public String id; public String jsObjectName; public Set allowedOriginRules; public WebViewCompat.WebMessageListener listener; @@ -42,12 +44,14 @@ public class WebMessageListener implements Disposable { @Nullable public WebMessageListenerChannelDelegate channelDelegate; - public WebMessageListener(@NonNull InAppWebViewInterface webView, @NonNull BinaryMessenger messenger, + public WebMessageListener(@NonNull String id, + @NonNull InAppWebViewInterface webView, @NonNull BinaryMessenger messenger, @NonNull String jsObjectName, @NonNull Set allowedOriginRules) { + this.id = id; this.webView = webView; this.jsObjectName = jsObjectName; this.allowedOriginRules = allowedOriginRules; - final MethodChannel channel = new MethodChannel(messenger, METHOD_CHANNEL_NAME_PREFIX + this.jsObjectName); + final MethodChannel channel = new MethodChannel(messenger, METHOD_CHANNEL_NAME_PREFIX + this.id + "_" + this.jsObjectName); this.channelDelegate = new WebMessageListenerChannelDelegate(this, channel); if (this.webView instanceof InAppWebView) { @@ -107,12 +111,13 @@ public class WebMessageListener implements Disposable { if (map == null) { return null; } + String id = (String) map.get("id"); String jsObjectName = (String) map.get("jsObjectName"); assert jsObjectName != null; List allowedOriginRuleList = (List) map.get("allowedOriginRules"); assert allowedOriginRuleList != null; Set allowedOriginRules = new HashSet<>(allowedOriginRuleList); - return new WebMessageListener(webView, messenger, jsObjectName, allowedOriginRules); + return new WebMessageListener(id, webView, messenger, jsObjectName, allowedOriginRules); } public void assertOriginRulesValid() throws Exception { diff --git a/dev_packages/generators/lib/src/exchangeable_enum_generator.dart b/dev_packages/generators/lib/src/exchangeable_enum_generator.dart index d5632d8d..ba7c12b1 100644 --- a/dev_packages/generators/lib/src/exchangeable_enum_generator.dart +++ b/dev_packages/generators/lib/src/exchangeable_enum_generator.dart @@ -45,10 +45,16 @@ class ExchangeableEnumGenerator } classBuffer.writeln('class $extClassName {'); - final FieldElement enumValue = visitor.fields.entries + final fieldEntriesSorted = visitor.fields.entries.toList(); + fieldEntriesSorted.sort((a, b) => a.key.compareTo(b.key)); + + final methodEntriesSorted = visitor.methods.entries.toList(); + fieldEntriesSorted.sort((a, b) => a.key.compareTo(b.key)); + + final FieldElement enumValue = fieldEntriesSorted .firstWhere((element) => element.key == "_value") .value; - final FieldElement enumNativeValue = visitor.fields.entries + final FieldElement enumNativeValue = fieldEntriesSorted .firstWhere((element) => element.key == "_nativeValue", orElse: () => MapEntry("_nativeValue", enumValue)) .value; @@ -62,7 +68,7 @@ class ExchangeableEnumGenerator classBuffer.writeln( "factory $extClassName._internalMultiPlatform(${enumValue.type} value, Function nativeValue) => $extClassName._internal(value, nativeValue());"); - for (final entry in visitor.fields.entries) { + for (final entry in fieldEntriesSorted) { final fieldName = entry.key; final fieldElement = entry.value; if (fieldName == "_value" || fieldName == "_nativeValue") { @@ -176,7 +182,7 @@ class ExchangeableEnumGenerator if (annotation.read("valuesProperty").boolValue) { classBuffer.writeln('///Set of all values of [$extClassName].'); classBuffer.writeln('static final Set<$extClassName> values = ['); - for (final entry in visitor.fields.entries) { + for (final entry in fieldEntriesSorted) { final fieldName = entry.key; final fieldElement = entry.value; final isEnumCustomValue = _coreCheckerEnumCustomValue @@ -228,7 +234,7 @@ class ExchangeableEnumGenerator """); } - for (final entry in visitor.methods.entries) { + for (final entry in methodEntriesSorted) { final methodElement = entry.value; if (Util.methodHasIgnore(methodElement)) { continue; @@ -301,7 +307,7 @@ class ExchangeableEnumGenerator classBuffer.writeln('return _value;'); } else { classBuffer.writeln('switch(_value) {'); - for (final entry in visitor.fields.entries) { + for (final entry in fieldEntriesSorted) { final fieldName = entry.key; final fieldElement = entry.value; if (!fieldElement.isPrivate && fieldElement.isStatic) { diff --git a/dev_packages/generators/lib/src/exchangeable_object_generator.dart b/dev_packages/generators/lib/src/exchangeable_object_generator.dart index a4a89207..caa87882 100644 --- a/dev_packages/generators/lib/src/exchangeable_object_generator.dart +++ b/dev_packages/generators/lib/src/exchangeable_object_generator.dart @@ -67,7 +67,17 @@ class ExchangeableObjectGenerator final deprecatedFields = []; final constructorFields = []; final superConstructorFields = []; - for (final entry in visitor.fields.entries) { + + final fieldEntriesSorted = visitor.fields.entries.toList(); + fieldEntriesSorted.sort((a, b) => a.key.compareTo(b.key)); + + final fieldValuesSorted = visitor.fields.values.toList(); + fieldValuesSorted.sort((a, b) => a.name.compareTo(b.name)); + + final methodEntriesSorted = visitor.methods.entries.toList(); + fieldEntriesSorted.sort((a, b) => a.key.compareTo(b.key)); + + for (final entry in fieldEntriesSorted) { final fieldName = entry.key; final fieldElement = entry.value; if (!fieldElement.isPrivate) { @@ -295,7 +305,7 @@ class ExchangeableObjectGenerator if (superClass != null) { fieldElements.addAll(superClass.element2.fields); } - fieldElements.addAll(visitor.fields.values); + fieldElements.addAll(fieldValuesSorted); final nonRequiredFields = []; final requiredFields = []; for (final fieldElement in fieldElements) { @@ -353,7 +363,7 @@ class ExchangeableObjectGenerator classBuffer.writeln('}'); } - for (final entry in visitor.methods.entries) { + for (final entry in methodEntriesSorted) { final methodElement = entry.value; if (Util.methodHasIgnore(methodElement)) { continue; @@ -382,7 +392,7 @@ class ExchangeableObjectGenerator classBuffer.writeln('///Converts instance to a map.'); classBuffer.writeln('Map toMap() {'); classBuffer.writeln('return {'); - for (final entry in visitor.methods.entries) { + for (final entry in methodEntriesSorted) { final methodElement = entry.value; final toMapMergeWith = _coreCheckerObjectMethod .firstAnnotationOf(methodElement) @@ -403,7 +413,7 @@ class ExchangeableObjectGenerator } } } - for (final entry in visitor.fields.entries) { + for (final entry in fieldEntriesSorted) { final fieldElement = entry.value; if (!fieldElement.isPrivate && !fieldElement.hasDeprecated && @@ -475,7 +485,7 @@ class ExchangeableObjectGenerator } } } - for (final entry in visitor.fields.entries) { + for (final entry in fieldEntriesSorted) { final fieldName = entry.key; final fieldElement = entry.value; if (!fieldElement.isPrivate && diff --git a/example/ios/Flutter/flutter_export_environment.sh b/example/ios/Flutter/flutter_export_environment.sh index a7647f6d..68661abb 100755 --- a/example/ios/Flutter/flutter_export_environment.sh +++ b/example/ios/Flutter/flutter_export_environment.sh @@ -3,11 +3,12 @@ export "FLUTTER_ROOT=/Users/lorenzopichilli/fvm/versions/3.3.6" export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example" export "COCOAPODS_PARALLEL_CODE_SIGN=true" -export "FLUTTER_TARGET=lib/main.dart" +export "FLUTTER_TARGET=integration_test/webview_flutter_test.dart" export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NUMBER=1" +export "DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false" -export "PACKAGE_CONFIG=.dart_tool/package_config.json" +export "PACKAGE_CONFIG=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/.dart_tool/package_config.json" diff --git a/ios/Classes/InAppWebView/WebMessage/WebMessageListener.swift b/ios/Classes/InAppWebView/WebMessage/WebMessageListener.swift index 0250013d..6a55170f 100644 --- a/ios/Classes/InAppWebView/WebMessage/WebMessageListener.swift +++ b/ios/Classes/InAppWebView/WebMessage/WebMessageListener.swift @@ -10,16 +10,18 @@ import WebKit public class WebMessageListener : FlutterMethodCallDelegate { static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_web_message_listener_" + var id: String var jsObjectName: String var allowedOriginRules: Set var channelDelegate: WebMessageListenerChannelDelegate? weak var webView: InAppWebView? - public init(jsObjectName: String, allowedOriginRules: Set) { + public init(id: String, jsObjectName: String, allowedOriginRules: Set) { + self.id = id self.jsObjectName = jsObjectName self.allowedOriginRules = allowedOriginRules super.init() - let channel = FlutterMethodChannel(name: WebMessageListener.METHOD_CHANNEL_NAME_PREFIX + self.jsObjectName, + let channel = FlutterMethodChannel(name: WebMessageListener.METHOD_CHANNEL_NAME_PREFIX + self.id + "_" + self.jsObjectName, binaryMessenger: SwiftFlutterPlugin.instance!.registrar!.messenger()) self.channelDelegate = WebMessageListenerChannelDelegate(webMessageListener: self, channel: channel) } @@ -101,7 +103,7 @@ public class WebMessageListener : FlutterMethodCallDelegate { })(); """ webView.configuration.userContentController.addPluginScript(PluginScript( - groupName: "WebMessageListener-" + jsObjectName, + groupName: "WebMessageListener-" + id + "-" + jsObjectName, source: source, injectionTime: .atDocumentStart, forMainFrameOnly: false, @@ -117,6 +119,7 @@ public class WebMessageListener : FlutterMethodCallDelegate { return nil } return WebMessageListener( + id: map["id"] as! String, jsObjectName: map["jsObjectName"] as! String, allowedOriginRules: Set(map["allowedOriginRules"] as! [String]) ) diff --git a/lib/src/android/webview_asset_loader.g.dart b/lib/src/android/webview_asset_loader.g.dart index 751262bb..e95819fd 100644 --- a/lib/src/android/webview_asset_loader.g.dart +++ b/lib/src/android/webview_asset_loader.g.dart @@ -81,9 +81,9 @@ class WebViewAssetLoader { /// ///Implement this interface to handle other use-cases according to your app's needs. abstract class PathHandler { - late final String _type; - late final String _id; late final MethodChannel _channel; + late final String _id; + late final String _type; ///The suffix path to be handled. /// diff --git a/lib/src/android/webview_feature.g.dart b/lib/src/android/webview_feature.g.dart index 0ca4c03e..023f3f2a 100644 --- a/lib/src/android/webview_feature.g.dart +++ b/lib/src/android/webview_feature.g.dart @@ -18,8 +18,10 @@ class WebViewFeature { factory WebViewFeature._internalMultiPlatform( String value, Function nativeValue) => WebViewFeature._internal(value, nativeValue()); - static const _channel = const MethodChannel( - 'com.pichillilorenzo/flutter_inappwebview_webviewfeature'); + + ///This feature covers [InAppWebViewSettings.algorithmicDarkeningAllowed]. + static const ALGORITHMIC_DARKENING = WebViewFeature._internal( + 'ALGORITHMIC_DARKENING', 'ALGORITHMIC_DARKENING'); ///This feature covers [InAppWebViewController.createWebMessageChannel]. static const CREATE_WEB_MESSAGE_CHANNEL = WebViewFeature._internal( @@ -29,6 +31,15 @@ class WebViewFeature { static const DISABLED_ACTION_MODE_MENU_ITEMS = WebViewFeature._internal( 'DISABLED_ACTION_MODE_MENU_ITEMS', 'DISABLED_ACTION_MODE_MENU_ITEMS'); + ///This feature covers [UserScriptInjectionTime.AT_DOCUMENT_START]. + static const DOCUMENT_START_SCRIPT = WebViewFeature._internal( + 'DOCUMENT_START_SCRIPT', 'DOCUMENT_START_SCRIPT'); + + ///This feature covers [InAppWebViewSettings.enterpriseAuthenticationAppLinkPolicyEnabled]. + static const ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY = + WebViewFeature._internal('ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY', + 'ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY'); + ///This feature covers [InAppWebViewSettings.forceDark]. static const FORCE_DARK = WebViewFeature._internal('FORCE_DARK', 'FORCE_DARK'); @@ -37,6 +48,10 @@ class WebViewFeature { static const FORCE_DARK_STRATEGY = WebViewFeature._internal('FORCE_DARK_STRATEGY', 'FORCE_DARK_STRATEGY'); + ///This feature covers [InAppWebViewController.getVariationsHeader]. + static const GET_VARIATIONS_HEADER = WebViewFeature._internal( + 'GET_VARIATIONS_HEADER', 'GET_VARIATIONS_HEADER'); + /// static const GET_WEB_CHROME_CLIENT = WebViewFeature._internal( 'GET_WEB_CHROME_CLIENT', 'GET_WEB_CHROME_CLIENT'); @@ -77,6 +92,10 @@ class WebViewFeature { static const RECEIVE_WEB_RESOURCE_ERROR = WebViewFeature._internal( 'RECEIVE_WEB_RESOURCE_ERROR', 'RECEIVE_WEB_RESOURCE_ERROR'); + ///This feature covers [InAppWebViewSettings.requestedWithHeaderMode]. + static const REQUESTED_WITH_HEADER_CONTROL = WebViewFeature._internal( + 'REQUESTED_WITH_HEADER_CONTROL', 'REQUESTED_WITH_HEADER_CONTROL'); + ///This feature covers [InAppWebViewController.setSafeBrowsingAllowlist]. static const SAFE_BROWSING_ALLOWLIST = WebViewFeature._internal( 'SAFE_BROWSING_ALLOWLIST', 'SAFE_BROWSING_ALLOWLIST'); @@ -145,6 +164,10 @@ class WebViewFeature { static const START_SAFE_BROWSING = WebViewFeature._internal('START_SAFE_BROWSING', 'START_SAFE_BROWSING'); + ///This feature covers [InAppWebViewSettings.willSuppressErrorPage]. + static const SUPPRESS_ERROR_PAGE = + WebViewFeature._internal('SUPPRESS_ERROR_PAGE', 'SUPPRESS_ERROR_PAGE'); + /// static const TRACING_CONTROLLER_BASIC_USAGE = WebViewFeature._internal( 'TRACING_CONTROLLER_BASIC_USAGE', 'TRACING_CONTROLLER_BASIC_USAGE'); @@ -195,38 +218,19 @@ class WebViewFeature { /// static const WEB_VIEW_RENDERER_TERMINATE = WebViewFeature._internal( 'WEB_VIEW_RENDERER_TERMINATE', 'WEB_VIEW_RENDERER_TERMINATE'); - - ///This feature covers [UserScriptInjectionTime.AT_DOCUMENT_START]. - static const DOCUMENT_START_SCRIPT = WebViewFeature._internal( - 'DOCUMENT_START_SCRIPT', 'DOCUMENT_START_SCRIPT'); - - ///This feature covers [InAppWebViewSettings.willSuppressErrorPage]. - static const SUPPRESS_ERROR_PAGE = - WebViewFeature._internal('SUPPRESS_ERROR_PAGE', 'SUPPRESS_ERROR_PAGE'); - - ///This feature covers [InAppWebViewSettings.algorithmicDarkeningAllowed]. - static const ALGORITHMIC_DARKENING = WebViewFeature._internal( - 'ALGORITHMIC_DARKENING', 'ALGORITHMIC_DARKENING'); - - ///This feature covers [InAppWebViewSettings.requestedWithHeaderMode]. - static const REQUESTED_WITH_HEADER_CONTROL = WebViewFeature._internal( - 'REQUESTED_WITH_HEADER_CONTROL', 'REQUESTED_WITH_HEADER_CONTROL'); - - ///This feature covers [InAppWebViewSettings.enterpriseAuthenticationAppLinkPolicyEnabled]. - static const ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY = - WebViewFeature._internal('ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY', - 'ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY'); - - ///This feature covers [InAppWebViewController.getVariationsHeader]. - static const GET_VARIATIONS_HEADER = WebViewFeature._internal( - 'GET_VARIATIONS_HEADER', 'GET_VARIATIONS_HEADER'); + static const _channel = const MethodChannel( + 'com.pichillilorenzo/flutter_inappwebview_webviewfeature'); ///Set of all values of [WebViewFeature]. static final Set values = [ + WebViewFeature.ALGORITHMIC_DARKENING, WebViewFeature.CREATE_WEB_MESSAGE_CHANNEL, WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS, + WebViewFeature.DOCUMENT_START_SCRIPT, + WebViewFeature.ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY, WebViewFeature.FORCE_DARK, WebViewFeature.FORCE_DARK_STRATEGY, + WebViewFeature.GET_VARIATIONS_HEADER, WebViewFeature.GET_WEB_CHROME_CLIENT, WebViewFeature.GET_WEB_VIEW_CLIENT, WebViewFeature.GET_WEB_VIEW_RENDERER, @@ -237,6 +241,7 @@ class WebViewFeature { WebViewFeature.PROXY_OVERRIDE_REVERSE_BYPASS, WebViewFeature.RECEIVE_HTTP_ERROR, WebViewFeature.RECEIVE_WEB_RESOURCE_ERROR, + WebViewFeature.REQUESTED_WITH_HEADER_CONTROL, WebViewFeature.SAFE_BROWSING_ALLOWLIST, WebViewFeature.SAFE_BROWSING_ENABLE, WebViewFeature.SAFE_BROWSING_HIT, @@ -253,6 +258,7 @@ class WebViewFeature { WebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST, WebViewFeature.SHOULD_OVERRIDE_WITH_REDIRECTS, WebViewFeature.START_SAFE_BROWSING, + WebViewFeature.SUPPRESS_ERROR_PAGE, WebViewFeature.TRACING_CONTROLLER_BASIC_USAGE, WebViewFeature.VISUAL_STATE_CALLBACK, WebViewFeature.WEB_MESSAGE_CALLBACK_ON_MESSAGE, @@ -265,12 +271,6 @@ class WebViewFeature { WebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT, WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE, WebViewFeature.WEB_VIEW_RENDERER_TERMINATE, - WebViewFeature.DOCUMENT_START_SCRIPT, - WebViewFeature.SUPPRESS_ERROR_PAGE, - WebViewFeature.ALGORITHMIC_DARKENING, - WebViewFeature.REQUESTED_WITH_HEADER_CONTROL, - WebViewFeature.ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY, - WebViewFeature.GET_VARIATIONS_HEADER, ].toSet(); ///Gets a possible [WebViewFeature] instance from [String] value. @@ -339,8 +339,10 @@ class AndroidWebViewFeature { factory AndroidWebViewFeature._internalMultiPlatform( String value, Function nativeValue) => AndroidWebViewFeature._internal(value, nativeValue()); - static const _channel = const MethodChannel( - 'com.pichillilorenzo/flutter_inappwebview_webviewfeature'); + + ///This feature covers [InAppWebViewSettings.algorithmicDarkeningAllowed]. + static const ALGORITHMIC_DARKENING = AndroidWebViewFeature._internal( + 'ALGORITHMIC_DARKENING', 'ALGORITHMIC_DARKENING'); /// static const CREATE_WEB_MESSAGE_CHANNEL = AndroidWebViewFeature._internal( @@ -351,6 +353,16 @@ class AndroidWebViewFeature { AndroidWebViewFeature._internal( 'DISABLED_ACTION_MODE_MENU_ITEMS', 'DISABLED_ACTION_MODE_MENU_ITEMS'); + ///This feature covers [UserScriptInjectionTime.AT_DOCUMENT_START]. + static const DOCUMENT_START_SCRIPT = AndroidWebViewFeature._internal( + 'DOCUMENT_START_SCRIPT', 'DOCUMENT_START_SCRIPT'); + + ///This feature covers [InAppWebViewSettings.enterpriseAuthenticationAppLinkPolicyEnabled]. + static const ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY = + AndroidWebViewFeature._internal( + 'ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY', + 'ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY'); + /// static const FORCE_DARK = AndroidWebViewFeature._internal('FORCE_DARK', 'FORCE_DARK'); @@ -395,6 +407,10 @@ class AndroidWebViewFeature { static const RECEIVE_WEB_RESOURCE_ERROR = AndroidWebViewFeature._internal( 'RECEIVE_WEB_RESOURCE_ERROR', 'RECEIVE_WEB_RESOURCE_ERROR'); + ///This feature covers [InAppWebViewSettings.requestedWithHeaderMode]. + static const REQUESTED_WITH_HEADER_CONTROL = AndroidWebViewFeature._internal( + 'REQUESTED_WITH_HEADER_CONTROL', 'REQUESTED_WITH_HEADER_CONTROL'); + /// static const SAFE_BROWSING_ALLOWLIST = AndroidWebViewFeature._internal( 'SAFE_BROWSING_ALLOWLIST', 'SAFE_BROWSING_ALLOWLIST'); @@ -465,6 +481,10 @@ class AndroidWebViewFeature { static const START_SAFE_BROWSING = AndroidWebViewFeature._internal( 'START_SAFE_BROWSING', 'START_SAFE_BROWSING'); + ///This feature covers [InAppWebViewSettings.willSuppressErrorPage]. + static const SUPPRESS_ERROR_PAGE = AndroidWebViewFeature._internal( + 'SUPPRESS_ERROR_PAGE', 'SUPPRESS_ERROR_PAGE'); + /// static const TRACING_CONTROLLER_BASIC_USAGE = AndroidWebViewFeature._internal( 'TRACING_CONTROLLER_BASIC_USAGE', 'TRACING_CONTROLLER_BASIC_USAGE'); @@ -517,33 +537,16 @@ class AndroidWebViewFeature { /// static const WEB_VIEW_RENDERER_TERMINATE = AndroidWebViewFeature._internal( 'WEB_VIEW_RENDERER_TERMINATE', 'WEB_VIEW_RENDERER_TERMINATE'); - - ///This feature covers [UserScriptInjectionTime.AT_DOCUMENT_START]. - static const DOCUMENT_START_SCRIPT = AndroidWebViewFeature._internal( - 'DOCUMENT_START_SCRIPT', 'DOCUMENT_START_SCRIPT'); - - ///This feature covers [InAppWebViewSettings.willSuppressErrorPage]. - static const SUPPRESS_ERROR_PAGE = AndroidWebViewFeature._internal( - 'SUPPRESS_ERROR_PAGE', 'SUPPRESS_ERROR_PAGE'); - - ///This feature covers [InAppWebViewSettings.algorithmicDarkeningAllowed]. - static const ALGORITHMIC_DARKENING = AndroidWebViewFeature._internal( - 'ALGORITHMIC_DARKENING', 'ALGORITHMIC_DARKENING'); - - ///This feature covers [InAppWebViewSettings.requestedWithHeaderMode]. - static const REQUESTED_WITH_HEADER_CONTROL = AndroidWebViewFeature._internal( - 'REQUESTED_WITH_HEADER_CONTROL', 'REQUESTED_WITH_HEADER_CONTROL'); - - ///This feature covers [InAppWebViewSettings.enterpriseAuthenticationAppLinkPolicyEnabled]. - static const ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY = - AndroidWebViewFeature._internal( - 'ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY', - 'ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY'); + static const _channel = const MethodChannel( + 'com.pichillilorenzo/flutter_inappwebview_webviewfeature'); ///Set of all values of [AndroidWebViewFeature]. static final Set values = [ + AndroidWebViewFeature.ALGORITHMIC_DARKENING, AndroidWebViewFeature.CREATE_WEB_MESSAGE_CHANNEL, AndroidWebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS, + AndroidWebViewFeature.DOCUMENT_START_SCRIPT, + AndroidWebViewFeature.ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY, AndroidWebViewFeature.FORCE_DARK, AndroidWebViewFeature.FORCE_DARK_STRATEGY, AndroidWebViewFeature.GET_WEB_CHROME_CLIENT, @@ -555,6 +558,7 @@ class AndroidWebViewFeature { AndroidWebViewFeature.PROXY_OVERRIDE, AndroidWebViewFeature.RECEIVE_HTTP_ERROR, AndroidWebViewFeature.RECEIVE_WEB_RESOURCE_ERROR, + AndroidWebViewFeature.REQUESTED_WITH_HEADER_CONTROL, AndroidWebViewFeature.SAFE_BROWSING_ALLOWLIST, AndroidWebViewFeature.SAFE_BROWSING_ENABLE, AndroidWebViewFeature.SAFE_BROWSING_HIT, @@ -571,6 +575,7 @@ class AndroidWebViewFeature { AndroidWebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST, AndroidWebViewFeature.SHOULD_OVERRIDE_WITH_REDIRECTS, AndroidWebViewFeature.START_SAFE_BROWSING, + AndroidWebViewFeature.SUPPRESS_ERROR_PAGE, AndroidWebViewFeature.TRACING_CONTROLLER_BASIC_USAGE, AndroidWebViewFeature.VISUAL_STATE_CALLBACK, AndroidWebViewFeature.WEB_MESSAGE_CALLBACK_ON_MESSAGE, @@ -583,11 +588,6 @@ class AndroidWebViewFeature { AndroidWebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT, AndroidWebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE, AndroidWebViewFeature.WEB_VIEW_RENDERER_TERMINATE, - AndroidWebViewFeature.DOCUMENT_START_SCRIPT, - AndroidWebViewFeature.SUPPRESS_ERROR_PAGE, - AndroidWebViewFeature.ALGORITHMIC_DARKENING, - AndroidWebViewFeature.REQUESTED_WITH_HEADER_CONTROL, - AndroidWebViewFeature.ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY, ].toSet(); ///Gets a possible [AndroidWebViewFeature] instance from [String] value. diff --git a/lib/src/chrome_safari_browser/chrome_safari_browser_settings.g.dart b/lib/src/chrome_safari_browser/chrome_safari_browser_settings.g.dart index 1b3cf8b3..2e7738ca 100644 --- a/lib/src/chrome_safari_browser/chrome_safari_browser_settings.g.dart +++ b/lib/src/chrome_safari_browser/chrome_safari_browser_settings.g.dart @@ -8,95 +8,14 @@ part of 'chrome_safari_browser_settings.dart'; ///Class that represents the settings that can be used for an [ChromeSafariBrowser] window. class ChromeSafariBrowserSettings implements ChromeSafariBrowserOptions { - ///The share state that should be applied to the custom tab. The default value is [CustomTabsShareState.SHARE_STATE_DEFAULT]. + ///An additional button to be shown in `SFSafariViewController`'s toolbar. + ///This allows the user to access powerful functionality from your extension without needing to first show the `UIActivityViewController`. /// - ///**NOTE**: Not available in a Trusted Web Activity. + ///**NOTE**: available on iOS 15.0+. /// ///**Supported Platforms/Implementations**: - ///- Android - CustomTabsShareState? shareState; - - ///Set to `false` if the title shouldn't be shown in the custom tab. The default value is `true`. - /// - ///**NOTE**: Not available in a Trusted Web Activity. - /// - ///**Supported Platforms/Implementations**: - ///- Android - bool? showTitle; - - ///Set the custom background color of the toolbar. - /// - ///**Supported Platforms/Implementations**: - ///- Android - Color? toolbarBackgroundColor; - - ///Sets the navigation bar color. Has no effect on Android API versions below L. - /// - ///**Supported Platforms/Implementations**: - ///- Android - Color? navigationBarColor; - - ///Sets the navigation bar divider color. Has no effect on Android API versions below P. - /// - ///**Supported Platforms/Implementations**: - ///- Android - Color? navigationBarDividerColor; - - ///Sets the color of the secondary toolbar. - /// - ///**Supported Platforms/Implementations**: - ///- Android - Color? secondaryToolbarColor; - - ///Set to `true` to enable the url bar to hide as the user scrolls down on the page. The default value is `false`. - /// - ///**NOTE**: Not available in a Trusted Web Activity. - /// - ///**Supported Platforms/Implementations**: - ///- Android - bool? enableUrlBarHiding; - - ///Set to `true` to enable Instant Apps. The default value is `false`. - /// - ///**NOTE**: Not available in a Trusted Web Activity. - /// - ///**Supported Platforms/Implementations**: - ///- Android - bool? instantAppsEnabled; - - ///Set an explicit application package name that limits - ///the components this Intent will resolve to. If left to the default - ///value of null, all components in all applications will considered. - ///If non-null, the Intent can only match the components in the given - ///application package. - /// - ///**Supported Platforms/Implementations**: - ///- Android - String? packageName; - - ///Set to `true` to enable Keep Alive. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android - bool? keepAliveEnabled; - - ///Set to `true` to launch the Android activity in `singleInstance` mode. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android - bool? isSingleInstance; - - ///Set to `true` to launch the Android intent with the flag `FLAG_ACTIVITY_NO_HISTORY`. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android - bool? noHistory; - - ///Set to `true` to launch the Custom Tab as a Trusted Web Activity. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android - bool? isTrustedWebActivity; + ///- iOS + ActivityButton? activityButton; ///Sets a list of additional trusted origins that the user may navigate or be redirected to from the starting uri. /// @@ -106,38 +25,6 @@ class ChromeSafariBrowserSettings implements ChromeSafariBrowserOptions { ///- Android List? additionalTrustedOrigins; - ///Sets a display mode of a Trusted Web Activity. - /// - ///**NOTE**: Available only in a Trusted Web Activity. - /// - ///**Supported Platforms/Implementations**: - ///- Android - TrustedWebActivityDisplayMode? displayMode; - - ///Sets a screen orientation. This can be used e.g. to enable the locking of an orientation lock type. - /// - ///**NOTE**: Available only in a Trusted Web Activity. - /// - ///**Supported Platforms/Implementations**: - ///- Android - TrustedWebActivityScreenOrientation? screenOrientation; - - ///Sets the start animations. - ///It must contain 2 [AndroidResource], where the first one represents the "enter" animation for the browser - ///and the second one represents the "exit" animation for the application. - /// - ///**Supported Platforms/Implementations**: - ///- Android - List? startAnimations; - - ///Sets the exit animations. - ///It must contain 2 [AndroidResource], where the first one represents the "enter" animation for the application - ///and the second one represents the "exit" animation for the browser. - /// - ///**Supported Platforms/Implementations**: - ///- Android - List? exitAnimations; - ///Adds the necessary flags and extras to signal any browser supporting custom tabs to use the browser UI ///at all times and avoid showing custom tab like UI. ///Calling this with an intent will override any custom tabs related customizations. @@ -147,12 +34,6 @@ class ChromeSafariBrowserSettings implements ChromeSafariBrowserOptions { ///- Android bool? alwaysUseBrowserUI; - ///Set to `true` if Reader mode should be entered automatically when it is available for the webpage. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- iOS - bool? entersReaderIfAvailable; - ///Set to `true` to enable bar collapsing. The default value is `false`. /// ///**Supported Platforms/Implementations**: @@ -167,6 +48,99 @@ class ChromeSafariBrowserSettings implements ChromeSafariBrowserOptions { ///- iOS DismissButtonStyle? dismissButtonStyle; + ///Sets a display mode of a Trusted Web Activity. + /// + ///**NOTE**: Available only in a Trusted Web Activity. + /// + ///**Supported Platforms/Implementations**: + ///- Android + TrustedWebActivityDisplayMode? displayMode; + + ///Set to `true` to enable the url bar to hide as the user scrolls down on the page. The default value is `false`. + /// + ///**NOTE**: Not available in a Trusted Web Activity. + /// + ///**Supported Platforms/Implementations**: + ///- Android + bool? enableUrlBarHiding; + + ///Set to `true` if Reader mode should be entered automatically when it is available for the webpage. The default value is `false`. + /// + ///**Supported Platforms/Implementations**: + ///- iOS + bool? entersReaderIfAvailable; + + ///An event attribution associated with a click that caused this `SFSafariViewController` to be opened. + ///This attribute is ignored if the `SFSafariViewController` url has a scheme of 'http'. + /// + ///**NOTE**: available on iOS 15.2+. + /// + ///**Supported Platforms/Implementations**: + ///- iOS + UIEventAttribution? eventAttribution; + + ///Sets the exit animations. + ///It must contain 2 [AndroidResource], where the first one represents the "enter" animation for the application + ///and the second one represents the "exit" animation for the browser. + /// + ///**Supported Platforms/Implementations**: + ///- Android + List? exitAnimations; + + ///Set to `true` to enable Instant Apps. The default value is `false`. + /// + ///**NOTE**: Not available in a Trusted Web Activity. + /// + ///**Supported Platforms/Implementations**: + ///- Android + bool? instantAppsEnabled; + + ///Set to `true` to launch the Android activity in `singleInstance` mode. The default value is `false`. + /// + ///**Supported Platforms/Implementations**: + ///- Android + bool? isSingleInstance; + + ///Set to `true` to launch the Custom Tab as a Trusted Web Activity. The default value is `false`. + /// + ///**Supported Platforms/Implementations**: + ///- Android + bool? isTrustedWebActivity; + + ///Set to `true` to enable Keep Alive. The default value is `false`. + /// + ///**Supported Platforms/Implementations**: + ///- Android + bool? keepAliveEnabled; + + ///Sets the navigation bar color. Has no effect on Android API versions below L. + /// + ///**Supported Platforms/Implementations**: + ///- Android + Color? navigationBarColor; + + ///Sets the navigation bar divider color. Has no effect on Android API versions below P. + /// + ///**Supported Platforms/Implementations**: + ///- Android + Color? navigationBarDividerColor; + + ///Set to `true` to launch the Android intent with the flag `FLAG_ACTIVITY_NO_HISTORY`. The default value is `false`. + /// + ///**Supported Platforms/Implementations**: + ///- Android + bool? noHistory; + + ///Set an explicit application package name that limits + ///the components this Intent will resolve to. If left to the default + ///value of null, all components in all applications will considered. + ///If non-null, the Intent can only match the components in the given + ///application package. + /// + ///**Supported Platforms/Implementations**: + ///- Android + String? packageName; + ///Set the custom background color of the navigation bar and the toolbar. /// ///**NOTE**: available on iOS 10.0+. @@ -189,29 +163,55 @@ class ChromeSafariBrowserSettings implements ChromeSafariBrowserOptions { ///- iOS ModalPresentationStyle? presentationStyle; + ///Sets a screen orientation. This can be used e.g. to enable the locking of an orientation lock type. + /// + ///**NOTE**: Available only in a Trusted Web Activity. + /// + ///**Supported Platforms/Implementations**: + ///- Android + TrustedWebActivityScreenOrientation? screenOrientation; + + ///Sets the color of the secondary toolbar. + /// + ///**Supported Platforms/Implementations**: + ///- Android + Color? secondaryToolbarColor; + + ///The share state that should be applied to the custom tab. The default value is [CustomTabsShareState.SHARE_STATE_DEFAULT]. + /// + ///**NOTE**: Not available in a Trusted Web Activity. + /// + ///**Supported Platforms/Implementations**: + ///- Android + CustomTabsShareState? shareState; + + ///Set to `false` if the title shouldn't be shown in the custom tab. The default value is `true`. + /// + ///**NOTE**: Not available in a Trusted Web Activity. + /// + ///**Supported Platforms/Implementations**: + ///- Android + bool? showTitle; + + ///Sets the start animations. + ///It must contain 2 [AndroidResource], where the first one represents the "enter" animation for the browser + ///and the second one represents the "exit" animation for the application. + /// + ///**Supported Platforms/Implementations**: + ///- Android + List? startAnimations; + + ///Set the custom background color of the toolbar. + /// + ///**Supported Platforms/Implementations**: + ///- Android + Color? toolbarBackgroundColor; + ///Set to the custom transition style when presenting the WebView. The default value is [ModalTransitionStyle.COVER_VERTICAL]. /// ///**Supported Platforms/Implementations**: ///- iOS ModalTransitionStyle? transitionStyle; - - ///An additional button to be shown in `SFSafariViewController`'s toolbar. - ///This allows the user to access powerful functionality from your extension without needing to first show the `UIActivityViewController`. - /// - ///**NOTE**: available on iOS 15.0+. - /// - ///**Supported Platforms/Implementations**: - ///- iOS - ActivityButton? activityButton; - - ///An event attribution associated with a click that caused this `SFSafariViewController` to be opened. - ///This attribute is ignored if the `SFSafariViewController` url has a scheme of 'http'. - /// - ///**NOTE**: available on iOS 15.2+. - /// - ///**Supported Platforms/Implementations**: - ///- iOS - UIEventAttribution? eventAttribution; ChromeSafariBrowserSettings( {this.shareState = CustomTabsShareState.SHARE_STATE_DEFAULT, this.showTitle = true, @@ -257,8 +257,14 @@ class ChromeSafariBrowserSettings implements ChromeSafariBrowserOptions { return null; } final instance = ChromeSafariBrowserSettings( - toolbarBackgroundColor: map['toolbarBackgroundColor'] != null - ? UtilColor.fromStringRepresentation(map['toolbarBackgroundColor']) + activityButton: ActivityButton.fromMap( + map['activityButton']?.cast()), + displayMode: _deserializeDisplayMode(map['displayMode']), + eventAttribution: UIEventAttribution.fromMap( + map['eventAttribution']?.cast()), + exitAnimations: map['exitAnimations'] != null + ? List.from(map['exitAnimations'] + .map((e) => AndroidResource.fromMap(e?.cast())!)) : null, navigationBarColor: map['navigationBarColor'] != null ? UtilColor.fromStringRepresentation(map['navigationBarColor']) @@ -266,51 +272,45 @@ class ChromeSafariBrowserSettings implements ChromeSafariBrowserOptions { navigationBarDividerColor: map['navigationBarDividerColor'] != null ? UtilColor.fromStringRepresentation(map['navigationBarDividerColor']) : null, - secondaryToolbarColor: map['secondaryToolbarColor'] != null - ? UtilColor.fromStringRepresentation(map['secondaryToolbarColor']) - : null, packageName: map['packageName'], - displayMode: _deserializeDisplayMode(map['displayMode']), - startAnimations: map['startAnimations'] != null - ? List.from(map['startAnimations'] - .map((e) => AndroidResource.fromMap(e?.cast())!)) - : null, - exitAnimations: map['exitAnimations'] != null - ? List.from(map['exitAnimations'] - .map((e) => AndroidResource.fromMap(e?.cast())!)) - : null, preferredBarTintColor: map['preferredBarTintColor'] != null ? UtilColor.fromStringRepresentation(map['preferredBarTintColor']) : null, preferredControlTintColor: map['preferredControlTintColor'] != null ? UtilColor.fromStringRepresentation(map['preferredControlTintColor']) : null, - activityButton: ActivityButton.fromMap( - map['activityButton']?.cast()), - eventAttribution: UIEventAttribution.fromMap( - map['eventAttribution']?.cast()), + secondaryToolbarColor: map['secondaryToolbarColor'] != null + ? UtilColor.fromStringRepresentation(map['secondaryToolbarColor']) + : null, + startAnimations: map['startAnimations'] != null + ? List.from(map['startAnimations'] + .map((e) => AndroidResource.fromMap(e?.cast())!)) + : null, + toolbarBackgroundColor: map['toolbarBackgroundColor'] != null + ? UtilColor.fromStringRepresentation(map['toolbarBackgroundColor']) + : null, ); - instance.shareState = - CustomTabsShareState.fromNativeValue(map['shareState']); - instance.showTitle = map['showTitle']; - instance.enableUrlBarHiding = map['enableUrlBarHiding']; - instance.instantAppsEnabled = map['instantAppsEnabled']; - instance.keepAliveEnabled = map['keepAliveEnabled']; - instance.isSingleInstance = map['isSingleInstance']; - instance.noHistory = map['noHistory']; - instance.isTrustedWebActivity = map['isTrustedWebActivity']; instance.additionalTrustedOrigins = map['additionalTrustedOrigins']?.cast(); - instance.screenOrientation = - TrustedWebActivityScreenOrientation.fromNativeValue( - map['screenOrientation']); instance.alwaysUseBrowserUI = map['alwaysUseBrowserUI']; - instance.entersReaderIfAvailable = map['entersReaderIfAvailable']; instance.barCollapsingEnabled = map['barCollapsingEnabled']; instance.dismissButtonStyle = DismissButtonStyle.fromNativeValue(map['dismissButtonStyle']); + instance.enableUrlBarHiding = map['enableUrlBarHiding']; + instance.entersReaderIfAvailable = map['entersReaderIfAvailable']; + instance.instantAppsEnabled = map['instantAppsEnabled']; + instance.isSingleInstance = map['isSingleInstance']; + instance.isTrustedWebActivity = map['isTrustedWebActivity']; + instance.keepAliveEnabled = map['keepAliveEnabled']; + instance.noHistory = map['noHistory']; instance.presentationStyle = ModalPresentationStyle.fromNativeValue(map['presentationStyle']); + instance.screenOrientation = + TrustedWebActivityScreenOrientation.fromNativeValue( + map['screenOrientation']); + instance.shareState = + CustomTabsShareState.fromNativeValue(map['shareState']); + instance.showTitle = map['showTitle']; instance.transitionStyle = ModalTransitionStyle.fromNativeValue(map['transitionStyle']); return instance; @@ -319,34 +319,34 @@ class ChromeSafariBrowserSettings implements ChromeSafariBrowserOptions { ///Converts instance to a map. Map toMap() { return { - "shareState": shareState?.toNativeValue(), - "showTitle": showTitle, - "toolbarBackgroundColor": toolbarBackgroundColor?.toHex(), - "navigationBarColor": navigationBarColor?.toHex(), - "navigationBarDividerColor": navigationBarDividerColor?.toHex(), - "secondaryToolbarColor": secondaryToolbarColor?.toHex(), - "enableUrlBarHiding": enableUrlBarHiding, - "instantAppsEnabled": instantAppsEnabled, - "packageName": packageName, - "keepAliveEnabled": keepAliveEnabled, - "isSingleInstance": isSingleInstance, - "noHistory": noHistory, - "isTrustedWebActivity": isTrustedWebActivity, + "activityButton": activityButton?.toMap(), "additionalTrustedOrigins": additionalTrustedOrigins, - "displayMode": displayMode?.toMap(), - "screenOrientation": screenOrientation?.toNativeValue(), - "startAnimations": startAnimations?.map((e) => e.toMap()).toList(), - "exitAnimations": exitAnimations?.map((e) => e.toMap()).toList(), "alwaysUseBrowserUI": alwaysUseBrowserUI, - "entersReaderIfAvailable": entersReaderIfAvailable, "barCollapsingEnabled": barCollapsingEnabled, "dismissButtonStyle": dismissButtonStyle?.toNativeValue(), + "displayMode": displayMode?.toMap(), + "enableUrlBarHiding": enableUrlBarHiding, + "entersReaderIfAvailable": entersReaderIfAvailable, + "eventAttribution": eventAttribution?.toMap(), + "exitAnimations": exitAnimations?.map((e) => e.toMap()).toList(), + "instantAppsEnabled": instantAppsEnabled, + "isSingleInstance": isSingleInstance, + "isTrustedWebActivity": isTrustedWebActivity, + "keepAliveEnabled": keepAliveEnabled, + "navigationBarColor": navigationBarColor?.toHex(), + "navigationBarDividerColor": navigationBarDividerColor?.toHex(), + "noHistory": noHistory, + "packageName": packageName, "preferredBarTintColor": preferredBarTintColor?.toHex(), "preferredControlTintColor": preferredControlTintColor?.toHex(), "presentationStyle": presentationStyle?.toNativeValue(), + "screenOrientation": screenOrientation?.toNativeValue(), + "secondaryToolbarColor": secondaryToolbarColor?.toHex(), + "shareState": shareState?.toNativeValue(), + "showTitle": showTitle, + "startAnimations": startAnimations?.map((e) => e.toMap()).toList(), + "toolbarBackgroundColor": toolbarBackgroundColor?.toHex(), "transitionStyle": transitionStyle?.toNativeValue(), - "activityButton": activityButton?.toMap(), - "eventAttribution": eventAttribution?.toMap(), }; } @@ -363,6 +363,6 @@ class ChromeSafariBrowserSettings implements ChromeSafariBrowserOptions { @override String toString() { - return 'ChromeSafariBrowserSettings{shareState: $shareState, showTitle: $showTitle, toolbarBackgroundColor: $toolbarBackgroundColor, navigationBarColor: $navigationBarColor, navigationBarDividerColor: $navigationBarDividerColor, secondaryToolbarColor: $secondaryToolbarColor, enableUrlBarHiding: $enableUrlBarHiding, instantAppsEnabled: $instantAppsEnabled, packageName: $packageName, keepAliveEnabled: $keepAliveEnabled, isSingleInstance: $isSingleInstance, noHistory: $noHistory, isTrustedWebActivity: $isTrustedWebActivity, additionalTrustedOrigins: $additionalTrustedOrigins, displayMode: $displayMode, screenOrientation: $screenOrientation, startAnimations: $startAnimations, exitAnimations: $exitAnimations, alwaysUseBrowserUI: $alwaysUseBrowserUI, entersReaderIfAvailable: $entersReaderIfAvailable, barCollapsingEnabled: $barCollapsingEnabled, dismissButtonStyle: $dismissButtonStyle, preferredBarTintColor: $preferredBarTintColor, preferredControlTintColor: $preferredControlTintColor, presentationStyle: $presentationStyle, transitionStyle: $transitionStyle, activityButton: $activityButton, eventAttribution: $eventAttribution}'; + return 'ChromeSafariBrowserSettings{activityButton: $activityButton, additionalTrustedOrigins: $additionalTrustedOrigins, alwaysUseBrowserUI: $alwaysUseBrowserUI, barCollapsingEnabled: $barCollapsingEnabled, dismissButtonStyle: $dismissButtonStyle, displayMode: $displayMode, enableUrlBarHiding: $enableUrlBarHiding, entersReaderIfAvailable: $entersReaderIfAvailable, eventAttribution: $eventAttribution, exitAnimations: $exitAnimations, instantAppsEnabled: $instantAppsEnabled, isSingleInstance: $isSingleInstance, isTrustedWebActivity: $isTrustedWebActivity, keepAliveEnabled: $keepAliveEnabled, navigationBarColor: $navigationBarColor, navigationBarDividerColor: $navigationBarDividerColor, noHistory: $noHistory, packageName: $packageName, preferredBarTintColor: $preferredBarTintColor, preferredControlTintColor: $preferredControlTintColor, presentationStyle: $presentationStyle, screenOrientation: $screenOrientation, secondaryToolbarColor: $secondaryToolbarColor, shareState: $shareState, showTitle: $showTitle, startAnimations: $startAnimations, toolbarBackgroundColor: $toolbarBackgroundColor, transitionStyle: $transitionStyle}'; } } diff --git a/lib/src/in_app_browser/in_app_browser_settings.g.dart b/lib/src/in_app_browser/in_app_browser_settings.g.dart index ad4d8747..511f7d11 100644 --- a/lib/src/in_app_browser/in_app_browser_settings.g.dart +++ b/lib/src/in_app_browser/in_app_browser_settings.g.dart @@ -9,6 +9,30 @@ part of 'in_app_browser_settings.dart'; ///This class represents all [InAppBrowser] settings available. class InAppBrowserSettings implements BrowserOptions, AndroidOptions, IosOptions { + ///Set to `false` to block the InAppBrowser WebView going back when the user click on the Android back button. The default value is `true`. + /// + ///**Supported Platforms/Implementations**: + ///- Android native WebView + bool? allowGoBackWithBackButton; + + ///Set the custom text for the close button. + /// + ///**Supported Platforms/Implementations**: + ///- iOS + String? closeButtonCaption; + + ///Set the custom color for the close button. + /// + ///**Supported Platforms/Implementations**: + ///- iOS + Color? closeButtonColor; + + ///Set to `false` to not close the InAppBrowser when the user click on the Android back button and the WebView cannot go back to the history. The default value is `true`. + /// + ///**Supported Platforms/Implementations**: + ///- Android native WebView + bool? closeOnCannotGoBack; + ///Set to `true` to create the browser and load the page, but not show it. Omit or set to `false` to have the browser open and load normally. ///The default value is `false`. /// @@ -18,30 +42,6 @@ class InAppBrowserSettings ///- MacOS bool? hidden; - ///Set to `true` to hide the toolbar at the top of the WebView. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- MacOS - bool? hideToolbarTop; - - ///Set the custom background color of the toolbar at the top. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- MacOS - Color? toolbarTopBackgroundColor; - - ///Set to `true` to hide the url bar on the toolbar at the top. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- MacOS - bool? hideUrlBar; - ///Set to `true` to hide the progress bar when the WebView is loading a page. The default value is `false`. /// ///**Supported Platforms/Implementations**: @@ -56,24 +56,33 @@ class InAppBrowserSettings ///- Android native WebView bool? hideTitleBar; - ///Set the action bar's title. + ///Set to `true` to hide the toolbar at the bottom of the WebView. The default value is `false`. + /// + ///**Supported Platforms/Implementations**: + ///- iOS + bool? hideToolbarBottom; + + ///Set to `true` to hide the toolbar at the top of the WebView. The default value is `false`. /// ///**Supported Platforms/Implementations**: ///- Android native WebView + ///- iOS ///- MacOS - String? toolbarTopFixedTitle; + bool? hideToolbarTop; - ///Set to `false` to not close the InAppBrowser when the user click on the Android back button and the WebView cannot go back to the history. The default value is `true`. + ///Set to `true` to hide the url bar on the toolbar at the top. The default value is `false`. /// ///**Supported Platforms/Implementations**: ///- Android native WebView - bool? closeOnCannotGoBack; + ///- iOS + ///- MacOS + bool? hideUrlBar; - ///Set to `false` to block the InAppBrowser WebView going back when the user click on the Android back button. The default value is `true`. + ///Set the custom modal presentation style when presenting the WebView. The default value is [ModalPresentationStyle.FULL_SCREEN]. /// ///**Supported Platforms/Implementations**: - ///- Android native WebView - bool? allowGoBackWithBackButton; + ///- iOS + ModalPresentationStyle? presentationStyle; ///Set to `true` to close the InAppBrowser when the user click on the Android back button. The default value is `false`. /// @@ -81,30 +90,6 @@ class InAppBrowserSettings ///- Android native WebView bool? shouldCloseOnBackButtonPressed; - ///Set to `true` to set the toolbar at the top translucent. The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- iOS - bool? toolbarTopTranslucent; - - ///Set the tint color to apply to the navigation bar background. - /// - ///**Supported Platforms/Implementations**: - ///- iOS - Color? toolbarTopBarTintColor; - - ///Set the tint color to apply to the navigation items and bar button items. - /// - ///**Supported Platforms/Implementations**: - ///- iOS - Color? toolbarTopTintColor; - - ///Set to `true` to hide the toolbar at the bottom of the WebView. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- iOS - bool? hideToolbarBottom; - ///Set the custom background color of the toolbar at the bottom. /// ///**Supported Platforms/Implementations**: @@ -123,23 +108,38 @@ class InAppBrowserSettings ///- iOS bool? toolbarBottomTranslucent; - ///Set the custom text for the close button. + ///Set the custom background color of the toolbar at the top. /// ///**Supported Platforms/Implementations**: + ///- Android native WebView ///- iOS - String? closeButtonCaption; + ///- MacOS + Color? toolbarTopBackgroundColor; - ///Set the custom color for the close button. + ///Set the tint color to apply to the navigation bar background. /// ///**Supported Platforms/Implementations**: ///- iOS - Color? closeButtonColor; + Color? toolbarTopBarTintColor; - ///Set the custom modal presentation style when presenting the WebView. The default value is [ModalPresentationStyle.FULL_SCREEN]. + ///Set the action bar's title. + /// + ///**Supported Platforms/Implementations**: + ///- Android native WebView + ///- MacOS + String? toolbarTopFixedTitle; + + ///Set the tint color to apply to the navigation items and bar button items. /// ///**Supported Platforms/Implementations**: ///- iOS - ModalPresentationStyle? presentationStyle; + Color? toolbarTopTintColor; + + ///Set to `true` to set the toolbar at the top translucent. The default value is `true`. + /// + ///**Supported Platforms/Implementations**: + ///- iOS + bool? toolbarTopTranslucent; ///Set to the custom transition style when presenting the WebView. The default value is [ModalTransitionStyle.COVER_VERTICAL]. /// @@ -147,13 +147,6 @@ class InAppBrowserSettings ///- iOS ModalTransitionStyle? transitionStyle; - ///How the browser window should be added to the main window. - ///The default value is [WindowType.CHILD]. - /// - ///**Supported Platforms/Implementations**: - ///- MacOS - WindowType? windowType; - ///The window’s alpha value. ///The default value is `1.0`. /// @@ -161,6 +154,13 @@ class InAppBrowserSettings ///- MacOS double? windowAlphaValue; + ///Sets the origin and size of the window’s frame rectangle according to a given frame rectangle, + ///thereby setting its position and size onscreen. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + InAppWebViewRect? windowFrame; + ///Flags that describe the window’s current style, such as if it’s resizable or in full-screen mode. /// ///**Supported Platforms/Implementations**: @@ -175,38 +175,38 @@ class InAppBrowserSettings ///- MacOS WindowTitlebarSeparatorStyle? windowTitlebarSeparatorStyle; - ///Sets the origin and size of the window’s frame rectangle according to a given frame rectangle, - ///thereby setting its position and size onscreen. + ///How the browser window should be added to the main window. + ///The default value is [WindowType.CHILD]. /// ///**Supported Platforms/Implementations**: ///- MacOS - InAppWebViewRect? windowFrame; + WindowType? windowType; InAppBrowserSettings( - {this.hidden = false, - this.hideToolbarTop = false, - this.toolbarTopBackgroundColor, - this.hideUrlBar = false, + {this.allowGoBackWithBackButton = true, + this.closeButtonCaption, + this.closeButtonColor, + this.closeOnCannotGoBack = true, + this.hidden = false, this.hideProgressBar = false, this.hideTitleBar = false, - this.toolbarTopFixedTitle, - this.closeOnCannotGoBack = true, - this.allowGoBackWithBackButton = true, - this.shouldCloseOnBackButtonPressed = false, - this.toolbarTopTranslucent = true, - this.toolbarTopTintColor, this.hideToolbarBottom = false, + this.hideToolbarTop = false, + this.hideUrlBar = false, + this.presentationStyle = ModalPresentationStyle.FULL_SCREEN, + this.shouldCloseOnBackButtonPressed = false, this.toolbarBottomBackgroundColor, this.toolbarBottomTintColor, this.toolbarBottomTranslucent = true, - this.closeButtonCaption, - this.closeButtonColor, - this.presentationStyle = ModalPresentationStyle.FULL_SCREEN, + this.toolbarTopBackgroundColor, + this.toolbarTopFixedTitle, + this.toolbarTopTintColor, + this.toolbarTopTranslucent = true, this.transitionStyle = ModalTransitionStyle.COVER_VERTICAL, - this.windowType, this.windowAlphaValue = 1.0, + this.windowFrame, this.windowStyleMask, this.windowTitlebarSeparatorStyle, - this.windowFrame}); + this.windowType}); ///Gets a possible [InAppBrowserSettings] instance from a [Map] value. static InAppBrowserSettings? fromMap(Map? map) { @@ -214,12 +214,9 @@ class InAppBrowserSettings return null; } final instance = InAppBrowserSettings( - toolbarTopBackgroundColor: map['toolbarTopBackgroundColor'] != null - ? UtilColor.fromStringRepresentation(map['toolbarTopBackgroundColor']) - : null, - toolbarTopFixedTitle: map['toolbarTopFixedTitle'], - toolbarTopTintColor: map['toolbarTopTintColor'] != null - ? UtilColor.fromStringRepresentation(map['toolbarTopTintColor']) + closeButtonCaption: map['closeButtonCaption'], + closeButtonColor: map['closeButtonColor'] != null + ? UtilColor.fromStringRepresentation(map['closeButtonColor']) : null, toolbarBottomBackgroundColor: map['toolbarBottomBackgroundColor'] != null ? UtilColor.fromStringRepresentation( @@ -228,35 +225,38 @@ class InAppBrowserSettings toolbarBottomTintColor: map['toolbarBottomTintColor'] != null ? UtilColor.fromStringRepresentation(map['toolbarBottomTintColor']) : null, - closeButtonCaption: map['closeButtonCaption'], - closeButtonColor: map['closeButtonColor'] != null - ? UtilColor.fromStringRepresentation(map['closeButtonColor']) + toolbarTopBackgroundColor: map['toolbarTopBackgroundColor'] != null + ? UtilColor.fromStringRepresentation(map['toolbarTopBackgroundColor']) : null, - windowType: WindowType.fromNativeValue(map['windowType']), + toolbarTopFixedTitle: map['toolbarTopFixedTitle'], + toolbarTopTintColor: map['toolbarTopTintColor'] != null + ? UtilColor.fromStringRepresentation(map['toolbarTopTintColor']) + : null, + windowFrame: + InAppWebViewRect.fromMap(map['windowFrame']?.cast()), windowStyleMask: WindowStyleMask.fromNativeValue(map['windowStyleMask']), windowTitlebarSeparatorStyle: WindowTitlebarSeparatorStyle.fromNativeValue( map['windowTitlebarSeparatorStyle']), - windowFrame: - InAppWebViewRect.fromMap(map['windowFrame']?.cast()), + windowType: WindowType.fromNativeValue(map['windowType']), ); + instance.allowGoBackWithBackButton = map['allowGoBackWithBackButton']; + instance.closeOnCannotGoBack = map['closeOnCannotGoBack']; instance.hidden = map['hidden']; - instance.hideToolbarTop = map['hideToolbarTop']; - instance.hideUrlBar = map['hideUrlBar']; instance.hideProgressBar = map['hideProgressBar']; instance.hideTitleBar = map['hideTitleBar']; - instance.closeOnCannotGoBack = map['closeOnCannotGoBack']; - instance.allowGoBackWithBackButton = map['allowGoBackWithBackButton']; + instance.hideToolbarBottom = map['hideToolbarBottom']; + instance.hideToolbarTop = map['hideToolbarTop']; + instance.hideUrlBar = map['hideUrlBar']; + instance.presentationStyle = + ModalPresentationStyle.fromNativeValue(map['presentationStyle']); instance.shouldCloseOnBackButtonPressed = map['shouldCloseOnBackButtonPressed']; - instance.toolbarTopTranslucent = map['toolbarTopTranslucent']; + instance.toolbarBottomTranslucent = map['toolbarBottomTranslucent']; instance.toolbarTopBarTintColor = map['toolbarTopBarTintColor'] != null ? UtilColor.fromStringRepresentation(map['toolbarTopBarTintColor']) : null; - instance.hideToolbarBottom = map['hideToolbarBottom']; - instance.toolbarBottomTranslucent = map['toolbarBottomTranslucent']; - instance.presentationStyle = - ModalPresentationStyle.fromNativeValue(map['presentationStyle']); + instance.toolbarTopTranslucent = map['toolbarTopTranslucent']; instance.transitionStyle = ModalTransitionStyle.fromNativeValue(map['transitionStyle']); instance.windowAlphaValue = map['windowAlphaValue']; @@ -266,33 +266,33 @@ class InAppBrowserSettings ///Converts instance to a map. Map toMap() { return { + "allowGoBackWithBackButton": allowGoBackWithBackButton, + "closeButtonCaption": closeButtonCaption, + "closeButtonColor": closeButtonColor?.toHex(), + "closeOnCannotGoBack": closeOnCannotGoBack, "hidden": hidden, - "hideToolbarTop": hideToolbarTop, - "toolbarTopBackgroundColor": toolbarTopBackgroundColor?.toHex(), - "hideUrlBar": hideUrlBar, "hideProgressBar": hideProgressBar, "hideTitleBar": hideTitleBar, - "toolbarTopFixedTitle": toolbarTopFixedTitle, - "closeOnCannotGoBack": closeOnCannotGoBack, - "allowGoBackWithBackButton": allowGoBackWithBackButton, - "shouldCloseOnBackButtonPressed": shouldCloseOnBackButtonPressed, - "toolbarTopTranslucent": toolbarTopTranslucent, - "toolbarTopBarTintColor": toolbarTopBarTintColor?.toHex(), - "toolbarTopTintColor": toolbarTopTintColor?.toHex(), "hideToolbarBottom": hideToolbarBottom, + "hideToolbarTop": hideToolbarTop, + "hideUrlBar": hideUrlBar, + "presentationStyle": presentationStyle?.toNativeValue(), + "shouldCloseOnBackButtonPressed": shouldCloseOnBackButtonPressed, "toolbarBottomBackgroundColor": toolbarBottomBackgroundColor?.toHex(), "toolbarBottomTintColor": toolbarBottomTintColor?.toHex(), "toolbarBottomTranslucent": toolbarBottomTranslucent, - "closeButtonCaption": closeButtonCaption, - "closeButtonColor": closeButtonColor?.toHex(), - "presentationStyle": presentationStyle?.toNativeValue(), + "toolbarTopBackgroundColor": toolbarTopBackgroundColor?.toHex(), + "toolbarTopBarTintColor": toolbarTopBarTintColor?.toHex(), + "toolbarTopFixedTitle": toolbarTopFixedTitle, + "toolbarTopTintColor": toolbarTopTintColor?.toHex(), + "toolbarTopTranslucent": toolbarTopTranslucent, "transitionStyle": transitionStyle?.toNativeValue(), - "windowType": windowType?.toNativeValue(), "windowAlphaValue": windowAlphaValue, + "windowFrame": windowFrame?.toMap(), "windowStyleMask": windowStyleMask?.toNativeValue(), "windowTitlebarSeparatorStyle": windowTitlebarSeparatorStyle?.toNativeValue(), - "windowFrame": windowFrame?.toMap(), + "windowType": windowType?.toNativeValue(), }; } @@ -308,6 +308,6 @@ class InAppBrowserSettings @override String toString() { - return 'InAppBrowserSettings{hidden: $hidden, hideToolbarTop: $hideToolbarTop, toolbarTopBackgroundColor: $toolbarTopBackgroundColor, hideUrlBar: $hideUrlBar, hideProgressBar: $hideProgressBar, hideTitleBar: $hideTitleBar, toolbarTopFixedTitle: $toolbarTopFixedTitle, closeOnCannotGoBack: $closeOnCannotGoBack, allowGoBackWithBackButton: $allowGoBackWithBackButton, shouldCloseOnBackButtonPressed: $shouldCloseOnBackButtonPressed, toolbarTopTranslucent: $toolbarTopTranslucent, toolbarTopBarTintColor: $toolbarTopBarTintColor, toolbarTopTintColor: $toolbarTopTintColor, hideToolbarBottom: $hideToolbarBottom, toolbarBottomBackgroundColor: $toolbarBottomBackgroundColor, toolbarBottomTintColor: $toolbarBottomTintColor, toolbarBottomTranslucent: $toolbarBottomTranslucent, closeButtonCaption: $closeButtonCaption, closeButtonColor: $closeButtonColor, presentationStyle: $presentationStyle, transitionStyle: $transitionStyle, windowType: $windowType, windowAlphaValue: $windowAlphaValue, windowStyleMask: $windowStyleMask, windowTitlebarSeparatorStyle: $windowTitlebarSeparatorStyle, windowFrame: $windowFrame}'; + return 'InAppBrowserSettings{allowGoBackWithBackButton: $allowGoBackWithBackButton, closeButtonCaption: $closeButtonCaption, closeButtonColor: $closeButtonColor, closeOnCannotGoBack: $closeOnCannotGoBack, hidden: $hidden, hideProgressBar: $hideProgressBar, hideTitleBar: $hideTitleBar, hideToolbarBottom: $hideToolbarBottom, hideToolbarTop: $hideToolbarTop, hideUrlBar: $hideUrlBar, presentationStyle: $presentationStyle, shouldCloseOnBackButtonPressed: $shouldCloseOnBackButtonPressed, toolbarBottomBackgroundColor: $toolbarBottomBackgroundColor, toolbarBottomTintColor: $toolbarBottomTintColor, toolbarBottomTranslucent: $toolbarBottomTranslucent, toolbarTopBackgroundColor: $toolbarTopBackgroundColor, toolbarTopBarTintColor: $toolbarTopBarTintColor, toolbarTopFixedTitle: $toolbarTopFixedTitle, toolbarTopTintColor: $toolbarTopTintColor, toolbarTopTranslucent: $toolbarTopTranslucent, transitionStyle: $transitionStyle, windowAlphaValue: $windowAlphaValue, windowFrame: $windowFrame, windowStyleMask: $windowStyleMask, windowTitlebarSeparatorStyle: $windowTitlebarSeparatorStyle, windowType: $windowType}'; } } diff --git a/lib/src/in_app_webview/headless_in_app_webview.dart b/lib/src/in_app_webview/headless_in_app_webview.dart index 92c1db75..4718b11c 100644 --- a/lib/src/in_app_webview/headless_in_app_webview.dart +++ b/lib/src/in_app_webview/headless_in_app_webview.dart @@ -17,6 +17,7 @@ import '../pull_to_refresh/pull_to_refresh_controller.dart'; import '../pull_to_refresh/pull_to_refresh_settings.dart'; import '../types/disposable.dart'; +///{@template flutter_inappwebview.HeadlessInAppWebView} ///Class that represents a WebView in headless mode. ///It can be used to run a WebView in background without attaching an `InAppWebView` to the widget tree. /// @@ -27,6 +28,7 @@ import '../types/disposable.dart'; ///- iOS ///- Web ///- MacOS +///{@endtemplate} class HeadlessInAppWebView implements WebView, Disposable { ///View ID. late final String id; @@ -41,7 +43,7 @@ class HeadlessInAppWebView implements WebView, Disposable { ///WebView Controller that can be used to access the [InAppWebViewController] API. late final InAppWebViewController webViewController; - ///The window id of a [CreateWindowAction.windowId]. + ///{@macro flutter_inappwebview.WebView.windowId} final int? windowId; ///The WebView initial size in pixels. @@ -50,8 +52,15 @@ class HeadlessInAppWebView implements WebView, Disposable { ///`Size(-1, -1)` will match both width and height of the current device screen size. /// ///**NOTE for Android**: `Size` width and height values will be converted to `int` values because they cannot have `double` values. + /// + ///**Supported Platforms/Implementations**: + ///- Android native WebView + ///- iOS + ///- Web + ///- MacOS final Size initialSize; + ///{@macro flutter_inappwebview.HeadlessInAppWebView} HeadlessInAppWebView( {this.initialSize = const Size(-1, -1), this.windowId, @@ -357,34 +366,44 @@ class HeadlessInAppWebView implements WebView, Disposable { return MapSize.fromMap(sizeMap); } + ///{@macro flutter_inappwebview.WebView.initialData} @override final InAppWebViewInitialData? initialData; + ///{@macro flutter_inappwebview.WebView.initialFile} @override final String? initialFile; + ///Use [initialSettings] instead. @override @Deprecated('Use initialSettings instead') final InAppWebViewGroupOptions? initialOptions; + ///{@macro flutter_inappwebview.WebView.initialSettings} @override final InAppWebViewSettings? initialSettings; + ///{@macro flutter_inappwebview.WebView.contextMenu} @override final ContextMenu? contextMenu; + ///{@macro flutter_inappwebview.WebView.initialUrlRequest} @override final URLRequest? initialUrlRequest; + ///{@macro flutter_inappwebview.WebView.initialUserScripts} @override final UnmodifiableListView? initialUserScripts; + ///{@macro flutter_inappwebview.WebView.pullToRefreshController} @override final PullToRefreshController? pullToRefreshController; + ///{@macro flutter_inappwebview.WebView.findInteractionController} @override final FindInteractionController? findInteractionController; + ///{@macro flutter_inappwebview.WebView.implementation} @override final WebViewImplementation implementation; @@ -413,10 +432,12 @@ class HeadlessInAppWebView implements WebView, Disposable { Future Function(InAppWebViewController controller, Uri url, SafeBrowsingThreat? threatType)? androidOnSafeBrowsingHit; + ///{@macro flutter_inappwebview.WebView.onPageCommitVisible} @override void Function(InAppWebViewController controller, WebUri? url)? onPageCommitVisible; + ///{@macro flutter_inappwebview.WebView.onTitleChanged} @override void Function(InAppWebViewController controller, String? title)? onTitleChanged; @@ -447,31 +468,38 @@ class HeadlessInAppWebView implements WebView, Disposable { InAppWebViewController controller, URLAuthenticationChallenge challenge)? iosShouldAllowDeprecatedTLS; + ///{@macro flutter_inappwebview.WebView.onAjaxProgress} @override Future Function( InAppWebViewController controller, AjaxRequest ajaxRequest)? onAjaxProgress; + ///{@macro flutter_inappwebview.WebView.onAjaxReadyStateChange} @override Future Function( InAppWebViewController controller, AjaxRequest ajaxRequest)? onAjaxReadyStateChange; + ///{@macro flutter_inappwebview.WebView.onConsoleMessage} @override void Function( InAppWebViewController controller, ConsoleMessage consoleMessage)? onConsoleMessage; + ///{@macro flutter_inappwebview.WebView.onCreateWindow} @override Future Function(InAppWebViewController controller, CreateWindowAction createWindowAction)? onCreateWindow; + ///{@macro flutter_inappwebview.WebView.onCloseWindow} @override void Function(InAppWebViewController controller)? onCloseWindow; + ///{@macro flutter_inappwebview.WebView.onWindowFocus} @override void Function(InAppWebViewController controller)? onWindowFocus; + ///{@macro flutter_inappwebview.WebView.onWindowBlur} @override void Function(InAppWebViewController controller)? onWindowBlur; @@ -480,6 +508,7 @@ class HeadlessInAppWebView implements WebView, Disposable { @override void Function(InAppWebViewController controller, Uri url)? onDownloadStart; + ///{@macro flutter_inappwebview.WebView.onDownloadStartRequest} @override void Function(InAppWebViewController controller, DownloadStartRequest downloadStartRequest)? onDownloadStartRequest; @@ -490,16 +519,19 @@ class HeadlessInAppWebView implements WebView, Disposable { void Function(InAppWebViewController controller, int activeMatchOrdinal, int numberOfMatches, bool isDoneCounting)? onFindResultReceived; + ///{@macro flutter_inappwebview.WebView.onJsAlert} @override Future Function( InAppWebViewController controller, JsAlertRequest jsAlertRequest)? onJsAlert; + ///{@macro flutter_inappwebview.WebView.onJsConfirm} @override Future Function( InAppWebViewController controller, JsConfirmRequest jsConfirmRequest)? onJsConfirm; + ///{@macro flutter_inappwebview.WebView.onJsPrompt} @override Future Function( InAppWebViewController controller, JsPromptRequest jsPromptRequest)? @@ -511,6 +543,7 @@ class HeadlessInAppWebView implements WebView, Disposable { void Function(InAppWebViewController controller, Uri? url, int code, String message)? onLoadError; + ///{@macro flutter_inappwebview.WebView.onReceivedError} @override void Function(InAppWebViewController controller, WebResourceRequest request, WebResourceError error)? onReceivedError; @@ -521,9 +554,12 @@ class HeadlessInAppWebView implements WebView, Disposable { void Function(InAppWebViewController controller, Uri? url, int statusCode, String description)? onLoadHttpError; + ///{@macro flutter_inappwebview.WebView.onReceivedHttpError} + @override void Function(InAppWebViewController controller, WebResourceRequest request, WebResourceResponse errorResponse)? onReceivedHttpError; + ///{@macro flutter_inappwebview.WebView.onLoadResource} @override void Function(InAppWebViewController controller, LoadedResource resource)? onLoadResource; @@ -534,17 +570,21 @@ class HeadlessInAppWebView implements WebView, Disposable { Future Function( InAppWebViewController controller, Uri url)? onLoadResourceCustomScheme; + ///{@macro flutter_inappwebview.WebView.onLoadResourceWithCustomScheme} @override Future Function( InAppWebViewController controller, WebResourceRequest request)? onLoadResourceWithCustomScheme; + ///{@macro flutter_inappwebview.WebView.onLoadStart} @override void Function(InAppWebViewController controller, WebUri? url)? onLoadStart; + ///{@macro flutter_inappwebview.WebView.onLoadStop} @override void Function(InAppWebViewController controller, WebUri? url)? onLoadStop; + ///{@macro flutter_inappwebview.WebView.onLongPressHitTestResult} @override void Function(InAppWebViewController controller, InAppWebViewHitTestResult hitTestResult)? onLongPressHitTestResult; @@ -554,62 +594,77 @@ class HeadlessInAppWebView implements WebView, Disposable { @override void Function(InAppWebViewController controller, Uri? url)? onPrint; + ///{@macro flutter_inappwebview.WebView.onPrintRequest} @override Future Function(InAppWebViewController controller, WebUri? url, PrintJobController? printJobController)? onPrintRequest; + ///{@macro flutter_inappwebview.WebView.onProgressChanged} @override void Function(InAppWebViewController controller, int progress)? onProgressChanged; + ///{@macro flutter_inappwebview.WebView.onReceivedClientCertRequest} @override Future Function(InAppWebViewController controller, URLAuthenticationChallenge challenge)? onReceivedClientCertRequest; + ///{@macro flutter_inappwebview.WebView.onReceivedHttpAuthRequest} @override Future Function(InAppWebViewController controller, URLAuthenticationChallenge challenge)? onReceivedHttpAuthRequest; + ///{@macro flutter_inappwebview.WebView.onReceivedServerTrustAuthRequest} @override Future Function(InAppWebViewController controller, URLAuthenticationChallenge challenge)? onReceivedServerTrustAuthRequest; + ///{@macro flutter_inappwebview.WebView.onScrollChanged} @override void Function(InAppWebViewController controller, int x, int y)? onScrollChanged; + ///{@macro flutter_inappwebview.WebView.onUpdateVisitedHistory} @override void Function(InAppWebViewController controller, WebUri? url, bool? isReload)? onUpdateVisitedHistory; + ///{@macro flutter_inappwebview.WebView.onWebViewCreated} @override void Function(InAppWebViewController controller)? onWebViewCreated; + ///{@macro flutter_inappwebview.WebView.shouldInterceptAjaxRequest} @override Future Function( InAppWebViewController controller, AjaxRequest ajaxRequest)? shouldInterceptAjaxRequest; + ///{@macro flutter_inappwebview.WebView.shouldInterceptFetchRequest} @override Future Function( InAppWebViewController controller, FetchRequest fetchRequest)? shouldInterceptFetchRequest; + ///{@macro flutter_inappwebview.WebView.shouldOverrideUrlLoading} @override Future Function( InAppWebViewController controller, NavigationAction navigationAction)? shouldOverrideUrlLoading; + ///{@macro flutter_inappwebview.WebView.onEnterFullscreen} @override void Function(InAppWebViewController controller)? onEnterFullscreen; + ///{@macro flutter_inappwebview.WebView.onExitFullscreen} @override void Function(InAppWebViewController controller)? onExitFullscreen; + ///{@macro flutter_inappwebview.WebView.onOverScrolled} @override void Function(InAppWebViewController controller, int x, int y, bool clampedX, bool clampedY)? onOverScrolled; + ///{@macro flutter_inappwebview.WebView.onZoomScaleChanged} @override void Function( InAppWebViewController controller, double oldScale, double newScale)? @@ -680,88 +735,108 @@ class HeadlessInAppWebView implements WebView, Disposable { void Function(InAppWebViewController controller, LoginRequest loginRequest)? androidOnReceivedLoginRequest; + ///{@macro flutter_inappwebview.WebView.onDidReceiveServerRedirectForProvisionalNavigation} @override void Function(InAppWebViewController controller)? onDidReceiveServerRedirectForProvisionalNavigation; + ///{@macro flutter_inappwebview.WebView.onFormResubmission} @override Future Function( InAppWebViewController controller, WebUri? url)? onFormResubmission; + ///{@macro flutter_inappwebview.WebView.onGeolocationPermissionsHidePrompt} @override void Function(InAppWebViewController controller)? onGeolocationPermissionsHidePrompt; + ///{@macro flutter_inappwebview.WebView.onGeolocationPermissionsShowPrompt} @override Future Function( InAppWebViewController controller, String origin)? onGeolocationPermissionsShowPrompt; + ///{@macro flutter_inappwebview.WebView.onJsBeforeUnload} @override Future Function(InAppWebViewController controller, JsBeforeUnloadRequest jsBeforeUnloadRequest)? onJsBeforeUnload; + ///{@macro flutter_inappwebview.WebView.onNavigationResponse} @override Future Function(InAppWebViewController controller, NavigationResponse navigationResponse)? onNavigationResponse; + ///{@macro flutter_inappwebview.WebView.onPermissionRequest} @override Future Function(InAppWebViewController controller, PermissionRequest permissionRequest)? onPermissionRequest; + ///{@macro flutter_inappwebview.WebView.onReceivedIcon} @override void Function(InAppWebViewController controller, Uint8List icon)? onReceivedIcon; + ///{@macro flutter_inappwebview.WebView.onReceivedLoginRequest} @override void Function(InAppWebViewController controller, LoginRequest loginRequest)? onReceivedLoginRequest; + ///{@macro flutter_inappwebview.WebView.onPermissionRequestCanceled} @override - final void Function(InAppWebViewController controller, + void Function(InAppWebViewController controller, PermissionRequest permissionRequest)? onPermissionRequestCanceled; + ///{@macro flutter_inappwebview.WebView.onRequestFocus} @override - final void Function(InAppWebViewController controller)? onRequestFocus; + void Function(InAppWebViewController controller)? onRequestFocus; + ///{@macro flutter_inappwebview.WebView.onReceivedTouchIconUrl} @override void Function( InAppWebViewController controller, WebUri url, bool precomposed)? onReceivedTouchIconUrl; + ///{@macro flutter_inappwebview.WebView.onRenderProcessGone} @override void Function( InAppWebViewController controller, RenderProcessGoneDetail detail)? onRenderProcessGone; + ///{@macro flutter_inappwebview.WebView.onRenderProcessResponsive} @override Future Function( InAppWebViewController controller, WebUri? url)? onRenderProcessResponsive; + ///{@macro flutter_inappwebview.WebView.onRenderProcessUnresponsive} @override Future Function( InAppWebViewController controller, WebUri? url)? onRenderProcessUnresponsive; + ///{@macro flutter_inappwebview.WebView.onSafeBrowsingHit} @override Future Function(InAppWebViewController controller, WebUri url, SafeBrowsingThreat? threatType)? onSafeBrowsingHit; + ///{@macro flutter_inappwebview.WebView.onWebContentProcessDidTerminate} @override void Function(InAppWebViewController controller)? onWebContentProcessDidTerminate; + ///{@macro flutter_inappwebview.WebView.shouldAllowDeprecatedTLS} @override Future Function( InAppWebViewController controller, URLAuthenticationChallenge challenge)? shouldAllowDeprecatedTLS; + ///{@macro flutter_inappwebview.WebView.shouldInterceptRequest} @override Future Function( InAppWebViewController controller, WebResourceRequest request)? shouldInterceptRequest; + ///{@macro flutter_inappwebview.WebView.onCameraCaptureStateChanged} @override Future Function( InAppWebViewController controller, @@ -769,6 +844,7 @@ class HeadlessInAppWebView implements WebView, Disposable { MediaCaptureState? newState, )? onCameraCaptureStateChanged; + ///{@macro flutter_inappwebview.WebView.onMicrophoneCaptureStateChanged} @override Future Function( InAppWebViewController controller, @@ -776,8 +852,9 @@ class HeadlessInAppWebView implements WebView, Disposable { MediaCaptureState? newState, )? onMicrophoneCaptureStateChanged; + ///{@macro flutter_inappwebview.WebView.onContentSizeChanged} @override - final void Function(InAppWebViewController controller, Size oldContentSize, + void Function(InAppWebViewController controller, Size oldContentSize, Size newContentSize)? onContentSizeChanged; } diff --git a/lib/src/in_app_webview/in_app_webview.dart b/lib/src/in_app_webview/in_app_webview.dart index e42efcc1..217fb842 100755 --- a/lib/src/in_app_webview/in_app_webview.dart +++ b/lib/src/in_app_webview/in_app_webview.dart @@ -24,12 +24,14 @@ import 'in_app_webview_controller.dart'; import 'in_app_webview_settings.dart'; import '../pull_to_refresh/main.dart'; +///{@template flutter_inappwebview.InAppWebView} ///Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree. /// ///**Supported Platforms/Implementations**: ///- Android native WebView ///- iOS ///- Web +///{@endtemplate} class InAppWebView extends StatefulWidget implements WebView { /// `gestureRecognizers` specifies which gestures should be consumed by the WebView. /// It is possible for other gesture recognizers to be competing with the web view on pointer @@ -40,11 +42,7 @@ class InAppWebView extends StatefulWidget implements WebView { /// were not claimed by any other gesture recognizer. final Set>? gestureRecognizers; - ///The window id of a [CreateWindowAction.windowId]. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS + ///{@macro flutter_inappwebview.WebView.windowId} @override final int? windowId; @@ -56,6 +54,7 @@ class InAppWebView extends StatefulWidget implements WebView { ///- Web final HeadlessInAppWebView? headlessWebView; + ///{@macro flutter_inappwebview.InAppWebView} const InAppWebView({ Key? key, this.windowId, @@ -202,9 +201,11 @@ class InAppWebView extends StatefulWidget implements WebView { Uri url, SafeBrowsingThreat? threatType)? androidOnSafeBrowsingHit; + ///{@macro flutter_inappwebview.WebView.initialData} @override final InAppWebViewInitialData? initialData; + ///{@macro flutter_inappwebview.WebView.initialFile} @override final String? initialFile; @@ -213,31 +214,40 @@ class InAppWebView extends StatefulWidget implements WebView { @Deprecated('Use initialSettings instead') final InAppWebViewGroupOptions? initialOptions; + ///{@macro flutter_inappwebview.WebView.initialSettings} @override final InAppWebViewSettings? initialSettings; + ///{@macro flutter_inappwebview.WebView.initialUrlRequest} @override final URLRequest? initialUrlRequest; + ///{@macro flutter_inappwebview.WebView.implementation} @override final WebViewImplementation implementation; + ///{@macro flutter_inappwebview.WebView.initialUserScripts} @override final UnmodifiableListView? initialUserScripts; + ///{@macro flutter_inappwebview.WebView.pullToRefreshController} @override final PullToRefreshController? pullToRefreshController; + ///{@macro flutter_inappwebview.WebView.findInteractionController} @override final FindInteractionController? findInteractionController; + ///{@macro flutter_inappwebview.WebView.contextMenu} @override final ContextMenu? contextMenu; + ///{@macro flutter_inappwebview.WebView.onPageCommitVisible} @override final void Function(InAppWebViewController controller, WebUri? url)? onPageCommitVisible; + ///{@macro flutter_inappwebview.WebView.onTitleChanged} @override final void Function(InAppWebViewController controller, String? title)? onTitleChanged; @@ -268,31 +278,38 @@ class InAppWebView extends StatefulWidget implements WebView { InAppWebViewController controller, URLAuthenticationChallenge challenge)? iosShouldAllowDeprecatedTLS; + ///{@macro flutter_inappwebview.WebView.onAjaxProgress} @override final Future Function( InAppWebViewController controller, AjaxRequest ajaxRequest)? onAjaxProgress; + ///{@macro flutter_inappwebview.WebView.onAjaxReadyStateChange} @override final Future Function( InAppWebViewController controller, AjaxRequest ajaxRequest)? onAjaxReadyStateChange; + ///{@macro flutter_inappwebview.WebView.onConsoleMessage} @override final void Function( InAppWebViewController controller, ConsoleMessage consoleMessage)? onConsoleMessage; + ///{@macro flutter_inappwebview.WebView.onCreateWindow} @override final Future Function(InAppWebViewController controller, CreateWindowAction createWindowAction)? onCreateWindow; + ///{@macro flutter_inappwebview.WebView.onCloseWindow} @override final void Function(InAppWebViewController controller)? onCloseWindow; + ///{@macro flutter_inappwebview.WebView.onWindowFocus} @override final void Function(InAppWebViewController controller)? onWindowFocus; + ///{@macro flutter_inappwebview.WebView.onWindowBlur} @override final void Function(InAppWebViewController controller)? onWindowBlur; @@ -315,6 +332,7 @@ class InAppWebView extends StatefulWidget implements WebView { final void Function(InAppWebViewController controller, Uri url)? onDownloadStart; + ///{@macro flutter_inappwebview.WebView.onDownloadStartRequest} @override final void Function(InAppWebViewController controller, DownloadStartRequest downloadStartRequest)? onDownloadStartRequest; @@ -325,16 +343,19 @@ class InAppWebView extends StatefulWidget implements WebView { final void Function(InAppWebViewController controller, int activeMatchOrdinal, int numberOfMatches, bool isDoneCounting)? onFindResultReceived; + ///{@macro flutter_inappwebview.WebView.onJsAlert} @override final Future Function( InAppWebViewController controller, JsAlertRequest jsAlertRequest)? onJsAlert; + ///{@macro flutter_inappwebview.WebView.onJsConfirm} @override final Future Function( InAppWebViewController controller, JsConfirmRequest jsConfirmRequest)? onJsConfirm; + ///{@macro flutter_inappwebview.WebView.onJsPrompt} @override final Future Function( InAppWebViewController controller, JsPromptRequest jsPromptRequest)? @@ -346,6 +367,7 @@ class InAppWebView extends StatefulWidget implements WebView { final void Function(InAppWebViewController controller, Uri? url, int code, String message)? onLoadError; + ///{@macro flutter_inappwebview.WebView.onReceivedError} @override final void Function(InAppWebViewController controller, WebResourceRequest request, WebResourceError error)? onReceivedError; @@ -356,12 +378,14 @@ class InAppWebView extends StatefulWidget implements WebView { final void Function(InAppWebViewController controller, Uri? url, int statusCode, String description)? onLoadHttpError; + ///{@macro flutter_inappwebview.WebView.onReceivedHttpError} @override final void Function( InAppWebViewController controller, WebResourceRequest request, WebResourceResponse errorResponse)? onReceivedHttpError; + ///{@macro flutter_inappwebview.WebView.onLoadResource} @override final void Function( InAppWebViewController controller, LoadedResource resource)? @@ -373,19 +397,23 @@ class InAppWebView extends StatefulWidget implements WebView { final Future Function( InAppWebViewController controller, Uri url)? onLoadResourceCustomScheme; + ///{@macro flutter_inappwebview.WebView.onLoadResourceWithCustomScheme} @override final Future Function( InAppWebViewController controller, WebResourceRequest request)? onLoadResourceWithCustomScheme; + ///{@macro flutter_inappwebview.WebView.onLoadStart} @override final void Function(InAppWebViewController controller, WebUri? url)? onLoadStart; + ///{@macro flutter_inappwebview.WebView.onLoadStop} @override final void Function(InAppWebViewController controller, WebUri? url)? onLoadStop; + ///{@macro flutter_inappwebview.WebView.onLongPressHitTestResult} @override final void Function(InAppWebViewController controller, InAppWebViewHitTestResult hitTestResult)? onLongPressHitTestResult; @@ -395,64 +423,79 @@ class InAppWebView extends StatefulWidget implements WebView { @override final void Function(InAppWebViewController controller, Uri? url)? onPrint; + ///{@macro flutter_inappwebview.WebView.onPrintRequest} @override final Future Function(InAppWebViewController controller, WebUri? url, PrintJobController? printJobController)? onPrintRequest; + ///{@macro flutter_inappwebview.WebView.onProgressChanged} @override final void Function(InAppWebViewController controller, int progress)? onProgressChanged; + ///{@macro flutter_inappwebview.WebView.onReceivedClientCertRequest} @override final Future Function(InAppWebViewController controller, URLAuthenticationChallenge challenge)? onReceivedClientCertRequest; + ///{@macro flutter_inappwebview.WebView.onReceivedHttpAuthRequest} @override final Future Function(InAppWebViewController controller, URLAuthenticationChallenge challenge)? onReceivedHttpAuthRequest; + ///{@macro flutter_inappwebview.WebView.onReceivedServerTrustAuthRequest} @override final Future Function( InAppWebViewController controller, URLAuthenticationChallenge challenge)? onReceivedServerTrustAuthRequest; + ///{@macro flutter_inappwebview.WebView.onScrollChanged} @override final void Function(InAppWebViewController controller, int x, int y)? onScrollChanged; + ///{@macro flutter_inappwebview.WebView.onUpdateVisitedHistory} @override final void Function( InAppWebViewController controller, WebUri? url, bool? isReload)? onUpdateVisitedHistory; + ///{@macro flutter_inappwebview.WebView.onWebViewCreated} @override final void Function(InAppWebViewController controller)? onWebViewCreated; + ///{@macro flutter_inappwebview.WebView.shouldInterceptAjaxRequest} @override final Future Function( InAppWebViewController controller, AjaxRequest ajaxRequest)? shouldInterceptAjaxRequest; + ///{@macro flutter_inappwebview.WebView.shouldInterceptFetchRequest} @override final Future Function( InAppWebViewController controller, FetchRequest fetchRequest)? shouldInterceptFetchRequest; + ///{@macro flutter_inappwebview.WebView.shouldOverrideUrlLoading} @override final Future Function( InAppWebViewController controller, NavigationAction navigationAction)? shouldOverrideUrlLoading; + ///{@macro flutter_inappwebview.WebView.onEnterFullscreen} @override final void Function(InAppWebViewController controller)? onEnterFullscreen; + ///{@macro flutter_inappwebview.WebView.onExitFullscreen} @override final void Function(InAppWebViewController controller)? onExitFullscreen; + ///{@macro flutter_inappwebview.WebView.onOverScrolled} @override final void Function(InAppWebViewController controller, int x, int y, bool clampedX, bool clampedY)? onOverScrolled; + ///{@macro flutter_inappwebview.WebView.onZoomScaleChanged} @override final void Function( InAppWebViewController controller, double oldScale, double newScale)? @@ -513,93 +556,113 @@ class InAppWebView extends StatefulWidget implements WebView { InAppWebViewController controller, LoginRequest loginRequest)? androidOnReceivedLoginRequest; + ///{@macro flutter_inappwebview.WebView.onDidReceiveServerRedirectForProvisionalNavigation} @override final void Function(InAppWebViewController controller)? onDidReceiveServerRedirectForProvisionalNavigation; + ///{@macro flutter_inappwebview.WebView.onFormResubmission} @override final Future Function( InAppWebViewController controller, WebUri? url)? onFormResubmission; + ///{@macro flutter_inappwebview.WebView.onGeolocationPermissionsHidePrompt} @override final void Function(InAppWebViewController controller)? onGeolocationPermissionsHidePrompt; + ///{@macro flutter_inappwebview.WebView.onGeolocationPermissionsShowPrompt} @override final Future Function( InAppWebViewController controller, String origin)? onGeolocationPermissionsShowPrompt; + ///{@macro flutter_inappwebview.WebView.onJsBeforeUnload} @override final Future Function( InAppWebViewController controller, JsBeforeUnloadRequest jsBeforeUnloadRequest)? onJsBeforeUnload; + ///{@macro flutter_inappwebview.WebView.onNavigationResponse} @override final Future Function( InAppWebViewController controller, NavigationResponse navigationResponse)? onNavigationResponse; + ///{@macro flutter_inappwebview.WebView.onPermissionRequest} @override final Future Function(InAppWebViewController controller, PermissionRequest permissionRequest)? onPermissionRequest; + ///{@macro flutter_inappwebview.WebView.onReceivedIcon} @override final void Function(InAppWebViewController controller, Uint8List icon)? onReceivedIcon; + ///{@macro flutter_inappwebview.WebView.onReceivedLoginRequest} @override final void Function( InAppWebViewController controller, LoginRequest loginRequest)? onReceivedLoginRequest; + ///{@macro flutter_inappwebview.WebView.onPermissionRequestCanceled} @override final void Function(InAppWebViewController controller, PermissionRequest permissionRequest)? onPermissionRequestCanceled; + ///{@macro flutter_inappwebview.WebView.onRequestFocus} @override final void Function(InAppWebViewController controller)? onRequestFocus; + ///{@macro flutter_inappwebview.WebView.onReceivedTouchIconUrl} @override final void Function( InAppWebViewController controller, WebUri url, bool precomposed)? onReceivedTouchIconUrl; + ///{@macro flutter_inappwebview.WebView.onRenderProcessGone} @override final void Function( InAppWebViewController controller, RenderProcessGoneDetail detail)? onRenderProcessGone; + ///{@macro flutter_inappwebview.WebView.onRenderProcessResponsive} @override final Future Function( InAppWebViewController controller, WebUri? url)? onRenderProcessResponsive; + ///{@macro flutter_inappwebview.WebView.onRenderProcessUnresponsive} @override final Future Function( InAppWebViewController controller, WebUri? url)? onRenderProcessUnresponsive; + ///{@macro flutter_inappwebview.WebView.onSafeBrowsingHit} @override final Future Function( InAppWebViewController controller, WebUri url, SafeBrowsingThreat? threatType)? onSafeBrowsingHit; + ///{@macro flutter_inappwebview.WebView.onWebContentProcessDidTerminate} @override final void Function(InAppWebViewController controller)? onWebContentProcessDidTerminate; + ///{@macro flutter_inappwebview.WebView.shouldAllowDeprecatedTLS} @override final Future Function( InAppWebViewController controller, URLAuthenticationChallenge challenge)? shouldAllowDeprecatedTLS; + ///{@macro flutter_inappwebview.WebView.shouldInterceptRequest} @override final Future Function( InAppWebViewController controller, WebResourceRequest request)? shouldInterceptRequest; + ///{@macro flutter_inappwebview.WebView.onCameraCaptureStateChanged} @override final Future Function( InAppWebViewController controller, @@ -607,6 +670,7 @@ class InAppWebView extends StatefulWidget implements WebView { MediaCaptureState? newState, )? onCameraCaptureStateChanged; + ///{@macro flutter_inappwebview.WebView.onMicrophoneCaptureStateChanged} @override final Future Function( InAppWebViewController controller, @@ -614,6 +678,7 @@ class InAppWebView extends StatefulWidget implements WebView { MediaCaptureState? newState, )? onMicrophoneCaptureStateChanged; + ///{@macro flutter_inappwebview.WebView.onContentSizeChanged} @override final void Function(InAppWebViewController controller, Size oldContentSize, Size newContentSize)? onContentSizeChanged; diff --git a/lib/src/in_app_webview/in_app_webview_settings.g.dart b/lib/src/in_app_webview/in_app_webview_settings.g.dart index 220ec1fa..89e05d80 100644 --- a/lib/src/in_app_webview/in_app_webview_settings.g.dart +++ b/lib/src/in_app_webview/in_app_webview_settings.g.dart @@ -8,226 +8,55 @@ part of 'in_app_webview_settings.dart'; ///This class represents all the WebView settings available. class InAppWebViewSettings { - ///Set to `true` to be able to listen at the [WebView.shouldOverrideUrlLoading] event. + ///A Boolean value indicating whether the WebView ignores an accessibility request to invert its colors. + ///The default value is `false`. /// - ///If the [WebView.shouldOverrideUrlLoading] event is implemented and this value is `null`, - ///it will be automatically inferred as `true`, otherwise, the default value is `false`. - ///This logic will not be applied for [InAppBrowser], where you must set the value manually. + ///**Supported Platforms/Implementations**: + ///- iOS 11.0+ ([Official API - UIView.accessibilityIgnoresInvertColors](https://developer.apple.com/documentation/uikit/uiview/2865843-accessibilityignoresinvertcolors)) + bool? accessibilityIgnoresInvertColors; + + ///Control whether algorithmic darkening is allowed. + /// + ///WebView always sets the media query `prefers-color-scheme` according to the app's theme attribute `isLightTheme`, + ///i.e. `prefers-color-scheme` is light if `isLightTheme` is `true` or not specified, otherwise it is `dark`. + ///This means that the web content's light or dark style will be applied automatically to match the app's theme if the content supports it. + /// + ///Algorithmic darkening is disallowed by default. + /// + ///If the app's theme is dark and it allows algorithmic darkening, + ///WebView will attempt to darken web content using an algorithm, + ///if the content doesn't define its own dark styles and doesn't explicitly disable darkening. + /// + ///**NOTE for Android native WebView**: available on Android only if [WebViewFeature.ALGORITHMIC_DARKENING] feature is supported. + /// + ///**Supported Platforms/Implementations**: + ///- Android native WebView 29+ ([Official API - WebSettingsCompat.setAlgorithmicDarkeningAllowed](https://developer.android.com/reference/androidx/webkit/WebSettingsCompat#setAlgorithmicDarkeningAllowed(android.webkit.WebSettings,boolean))) + bool? algorithmicDarkeningAllowed; + + ///Set to `true` to allow audio playing when the app goes in background or the screen is locked or another app is opened. + ///However, there will be no controls in the notification bar or on the lockscreen. + ///Also, make sure to not call [InAppWebViewController.pause], otherwise it will stop audio playing. + ///The default value is `false`. + /// + ///**IMPORTANT NOTE**: if you use this setting, your app could be rejected by the Google Play Store. + ///For example, if you allow background playing of YouTube videos, which is a violation of the YouTube API Terms of Service. /// ///**Supported Platforms/Implementations**: ///- Android native WebView - ///- iOS - ///- MacOS - bool? useShouldOverrideUrlLoading; + bool? allowBackgroundAudioPlaying; - ///Set to `true` to be able to listen at the [WebView.onLoadResource] event. - /// - ///If the [WebView.onLoadResource] event is implemented and this value is `null`, - ///it will be automatically inferred as `true`, otherwise, the default value is `false`. - ///This logic will not be applied for [InAppBrowser], where you must set the value manually. + ///Enables or disables content URL access within WebView. Content URL access allows WebView to load content from a content provider installed in the system. The default value is `true`. /// ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- MacOS - bool? useOnLoadResource; + ///- Android native WebView ([Official API - WebSettings.setAllowContentAccess](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setAllowContentAccess(boolean))) + bool? allowContentAccess; - ///Set to `true` to be able to listen at the [WebView.onDownloadStartRequest] event. - /// - ///If the [WebView.onDownloadStartRequest] event is implemented and this value is `null`, - ///it will be automatically inferred as `true`, otherwise, the default value is `false`. - ///This logic will not be applied for [InAppBrowser], where you must set the value manually. + ///Enables or disables file access within WebView. Note that this enables or disables file system access only. + ///Assets and resources are still accessible using `file:///android_asset` and `file:///android_res`. The default value is `true`. /// ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- MacOS - bool? useOnDownloadStart; - - ///Set to `true` to have all the browser's cache cleared before the new WebView is opened. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- MacOS - bool? clearCache; - - ///Sets the user-agent for the WebView. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setUserAgentString](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setUserAgentString(java.lang.String))) - ///- iOS ([Official API - WKWebView.customUserAgent](https://developer.apple.com/documentation/webkit/wkwebview/1414950-customuseragent)) - ///- MacOS ([Official API - WKWebView.customUserAgent](https://developer.apple.com/documentation/webkit/wkwebview/1414950-customuseragent)) - String? userAgent; - - ///Append to the existing user-agent. Setting userAgent will override this. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS ([Official API - WKWebViewConfiguration.applicationNameForUserAgent](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/1395665-applicationnameforuseragent)) - ///- MacOS ([Official API - WKWebViewConfiguration.applicationNameForUserAgent](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/1395665-applicationnameforuseragent)) - String? applicationNameForUserAgent; - - ///Set to `true` to enable JavaScript. The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setJavaScriptEnabled](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setJavaScriptEnabled(boolean))) - ///- iOS ([Official API - WKWebpagePreferences.allowsContentJavaScript](https://developer.apple.com/documentation/webkit/wkwebpagepreferences/3552422-allowscontentjavascript/)) - ///- MacOS ([Official API - WKWebpagePreferences.allowsContentJavaScript](https://developer.apple.com/documentation/webkit/wkwebpagepreferences/3552422-allowscontentjavascript/)) - ///- Web - bool? javaScriptEnabled; - - ///Set to `true` to allow JavaScript open windows without user interaction. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setJavaScriptCanOpenWindowsAutomatically](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setJavaScriptCanOpenWindowsAutomatically(boolean))) - ///- iOS ([Official API - WKPreferences.javaScriptCanOpenWindowsAutomatically](https://developer.apple.com/documentation/webkit/wkpreferences/1536573-javascriptcanopenwindowsautomati/)) - ///- MacOS ([Official API - WKPreferences.javaScriptCanOpenWindowsAutomatically](https://developer.apple.com/documentation/webkit/wkpreferences/1536573-javascriptcanopenwindowsautomati/)) - ///- Web but iframe requires same origin - bool? javaScriptCanOpenWindowsAutomatically; - - ///Set to `true` to prevent HTML5 audio or video from autoplaying. The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setMediaPlaybackRequiresUserGesture](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setMediaPlaybackRequiresUserGesture(boolean))) - ///- iOS ([Official API - WKWebViewConfiguration.mediaTypesRequiringUserActionForPlayback](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/1851524-mediatypesrequiringuseractionfor)) - ///- MacOS 10.12+ ([Official API - WKWebViewConfiguration.mediaTypesRequiringUserActionForPlayback](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/1851524-mediatypesrequiringuseractionfor)) - bool? mediaPlaybackRequiresUserGesture; - - ///Sets the minimum font size. The default value is `8` for Android, `0` for iOS. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setMinimumFontSize](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setMinimumFontSize(int))) - ///- iOS ([Official API - WKPreferences.minimumFontSize](https://developer.apple.com/documentation/webkit/wkpreferences/1537155-minimumfontsize/)) - ///- MacOS ([Official API - WKPreferences.minimumFontSize](https://developer.apple.com/documentation/webkit/wkpreferences/1537155-minimumfontsize/)) - int? minimumFontSize; - - ///Define whether the vertical scrollbar should be drawn or not. The default value is `true`. - /// - ///**NOTE for Web**: It must have the same value of [horizontalScrollBarEnabled] to take effect. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - View.setVerticalScrollBarEnabled](https://developer.android.com/reference/android/view/View#setVerticalScrollBarEnabled(boolean))) - ///- iOS ([Official API - UIScrollView.showsVerticalScrollIndicator](https://developer.apple.com/documentation/uikit/uiscrollview/1619405-showsverticalscrollindicator/)) - ///- Web but iframe requires same origin - bool? verticalScrollBarEnabled; - - ///Define whether the horizontal scrollbar should be drawn or not. The default value is `true`. - /// - ///**NOTE for Web**: It must have the same value of [verticalScrollBarEnabled] to take effect. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - View.setHorizontalScrollBarEnabled](https://developer.android.com/reference/android/view/View#setHorizontalScrollBarEnabled(boolean))) - ///- iOS ([Official API - UIScrollView.showsHorizontalScrollIndicator](https://developer.apple.com/documentation/uikit/uiscrollview/1619380-showshorizontalscrollindicator)) - ///- Web but iframe requires same origin - bool? horizontalScrollBarEnabled; - - ///List of custom schemes that the WebView must handle. Use the [WebView.onLoadResourceWithCustomScheme] event to intercept resource requests with custom scheme. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS 11.0+ - ///- MacOS 10.13+ - List? resourceCustomSchemes; - - ///List of [ContentBlocker] that are a set of rules used to block content in the browser window. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS 11.0+ - ///- MacOS 10.13+ - List? contentBlockers; - - ///Sets the content mode that the WebView needs to use when loading and rendering a webpage. The default value is [UserPreferredContentMode.RECOMMENDED]. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS 13.0+ ([Official API - WKWebpagePreferences.preferredContentMode](https://developer.apple.com/documentation/webkit/wkwebpagepreferences/3194426-preferredcontentmode/)) - ///- MacOS 10.15+ ([Official API - WKWebpagePreferences.preferredContentMode](https://developer.apple.com/documentation/webkit/wkwebpagepreferences/3194426-preferredcontentmode/)) - UserPreferredContentMode? preferredContentMode; - - ///Set to `true` to be able to listen at the [WebView.shouldInterceptAjaxRequest] event. - /// - ///If the [WebView.shouldInterceptAjaxRequest] event is implemented and this value is `null`, - ///it will be automatically inferred as `true`, otherwise, the default value is `false`. - ///This logic will not be applied for [InAppBrowser], where you must set the value manually. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- MacOS - bool? useShouldInterceptAjaxRequest; - - ///Set to `true` to be able to listen at the [WebView.shouldInterceptFetchRequest] event. - /// - ///If the [WebView.shouldInterceptFetchRequest] event is implemented and this value is `null`, - ///it will be automatically inferred as `true`, otherwise, the default value is `false`. - ///This logic will not be applied for [InAppBrowser], where you must set the value manually. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- MacOS - bool? useShouldInterceptFetchRequest; - - ///Set to `true` to open a browser window with incognito mode. The default value is `false`. - /// - ///**NOTE for Android native WebView**: setting this to `true`, it will clear all the cookies of all WebView instances, - ///because there isn't any way to make the website data store non-persistent for the specific WebView instance such as on iOS. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- MacOS - bool? incognito; - - ///Sets whether WebView should use browser caching. The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- MacOS - bool? cacheEnabled; - - ///Set to `true` to make the background of the WebView transparent. If your app has a dark theme, this can prevent a white flash on initialization. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- MacOS 12.0+ - bool? transparentBackground; - - ///Set to `true` to disable vertical scroll. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- Web but iframe requires same origin - bool? disableVerticalScroll; - - ///Set to `true` to disable horizontal scroll. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- Web but iframe requires same origin - bool? disableHorizontalScroll; - - ///Set to `true` to disable context menu. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - ///- iOS - ///- Web but iframe requires same origin - bool? disableContextMenu; - - ///Set to `false` if the WebView should not support zooming using its on-screen zoom controls and gestures. The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setSupportZoom](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setSupportZoom(boolean))) - ///- iOS - ///- MacOS - bool? supportZoom; + ///- Android native WebView ([Official API - WebSettings.setAllowFileAccess](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setAllowFileAccess(boolean))) + bool? allowFileAccess; ///Sets whether cross-origin requests in the context of a file scheme URL should be allowed to access content from other file scheme URLs. ///Note that some accesses such as image HTML elements don't follow same-origin rules and aren't affected by this setting. @@ -261,489 +90,16 @@ class InAppWebViewSettings { ///- MacOS bool? allowUniversalAccessFromFileURLs; - ///Set to `true` to allow audio playing when the app goes in background or the screen is locked or another app is opened. - ///However, there will be no controls in the notification bar or on the lockscreen. - ///Also, make sure to not call [InAppWebViewController.pause], otherwise it will stop audio playing. - ///The default value is `false`. - /// - ///**IMPORTANT NOTE**: if you use this setting, your app could be rejected by the Google Play Store. - ///For example, if you allow background playing of YouTube videos, which is a violation of the YouTube API Terms of Service. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - bool? allowBackgroundAudioPlaying; - - ///Use a [WebViewAssetLoader] instance to load local files including application's static assets and resources using http(s):// URLs. - ///Loading local files using web-like URLs instead of `file://` is desirable as it is compatible with the Same-Origin policy. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - WebViewAssetLoader? webViewAssetLoader; - - ///Sets the text zoom of the page in percent. The default value is `100`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setTextZoom](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setTextZoom(int))) - int? textZoom; - - ///Set to `true` to have the session cookie cache cleared before the new window is opened. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - bool? clearSessionCache; - - ///Set to `true` if the WebView should use its built-in zoom mechanisms. The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setBuiltInZoomControls](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setBuiltInZoomControls(boolean))) - bool? builtInZoomControls; - - ///Set to `true` if the WebView should display on-screen zoom controls when using the built-in zoom mechanisms. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setDisplayZoomControls](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setDisplayZoomControls(boolean))) - bool? displayZoomControls; - - ///Set to `true` if you want the database storage API is enabled. The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setDatabaseEnabled](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setDatabaseEnabled(boolean))) - bool? databaseEnabled; - - ///Set to `true` if you want the DOM storage API is enabled. The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setDomStorageEnabled](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setDomStorageEnabled(boolean))) - bool? domStorageEnabled; - - ///Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport. - ///When the value of the setting is false, the layout width is always set to the width of the WebView control in device-independent (CSS) pixels. - ///When the value is true and the page contains the viewport meta tag, the value of the width specified in the tag is used. - ///If the page does not contain the tag or does not provide a width, then a wide viewport will be used. The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setUseWideViewPort](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setUseWideViewPort(boolean))) - bool? useWideViewPort; - - ///Sets whether Safe Browsing is enabled. Safe Browsing allows WebView to protect against malware and phishing attacks by verifying the links. - ///Safe Browsing is enabled by default for devices which support it. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView 26+ ([Official API - WebSettings.setSafeBrowsingEnabled](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setSafeBrowsingEnabled(boolean))) - bool? safeBrowsingEnabled; - - ///Configures the WebView's behavior when a secure origin attempts to load a resource from an insecure origin. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView 21+ ([Official API - WebSettings.setMixedContentMode](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setMixedContentMode(int))) - MixedContentMode? mixedContentMode; - - ///Enables or disables content URL access within WebView. Content URL access allows WebView to load content from a content provider installed in the system. The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setAllowContentAccess](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setAllowContentAccess(boolean))) - bool? allowContentAccess; - - ///Enables or disables file access within WebView. Note that this enables or disables file system access only. - ///Assets and resources are still accessible using `file:///android_asset` and `file:///android_res`. The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setAllowFileAccess](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setAllowFileAccess(boolean))) - bool? allowFileAccess; - - ///Sets the path to the Application Caches files. In order for the Application Caches API to be enabled, this option must be set a path to which the application can write. - ///This option is used one time: repeated calls are ignored. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView (Official API - WebSettings.setAppCachePath) - String? appCachePath; - - ///Sets whether the WebView should not load image resources from the network (resources accessed via http and https URI schemes). The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setBlockNetworkImage](https://developer.android.com/reference/android/webkit/WebSettings#setBlockNetworkImage(boolean))) - bool? blockNetworkImage; - - ///Sets whether the WebView should not load resources from the network. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setBlockNetworkLoads](https://developer.android.com/reference/android/webkit/WebSettings#setBlockNetworkLoads(boolean))) - bool? blockNetworkLoads; - - ///Overrides the way the cache is used. The way the cache is used is based on the navigation type. For a normal page load, the cache is checked and content is re-validated as needed. - ///When navigating back, content is not revalidated, instead the content is just retrieved from the cache. The default value is [CacheMode.LOAD_DEFAULT]. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setCacheMode](https://developer.android.com/reference/android/webkit/WebSettings#setCacheMode(int))) - CacheMode? cacheMode; - - ///Sets the cursive font family name. The default value is `"cursive"`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setCursiveFontFamily](https://developer.android.com/reference/android/webkit/WebSettings#setCursiveFontFamily(java.lang.String))) - String? cursiveFontFamily; - - ///Sets the default fixed font size. The default value is `16`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setDefaultFixedFontSize](https://developer.android.com/reference/android/webkit/WebSettings#setDefaultFixedFontSize(int))) - int? defaultFixedFontSize; - - ///Sets the default font size. The default value is `16`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setDefaultFontSize](https://developer.android.com/reference/android/webkit/WebSettings#setDefaultFontSize(int))) - int? defaultFontSize; - - ///Sets the default text encoding name to use when decoding html pages. The default value is `"UTF-8"`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setDefaultTextEncodingName](https://developer.android.com/reference/android/webkit/WebSettings#setDefaultTextEncodingName(java.lang.String))) - String? defaultTextEncodingName; - - ///Disables the action mode menu items according to menuItems flag. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView 24+ ([Official API - WebSettings.setDisabledActionModeMenuItems](https://developer.android.com/reference/android/webkit/WebSettings#setDisabledActionModeMenuItems(int))) - ActionModeMenuItem? disabledActionModeMenuItems; - - ///Sets the fantasy font family name. The default value is `"fantasy"`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setFantasyFontFamily](https://developer.android.com/reference/android/webkit/WebSettings#setFantasyFontFamily(java.lang.String))) - String? fantasyFontFamily; - - ///Sets the fixed font family name. The default value is `"monospace"`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setFixedFontFamily](https://developer.android.com/reference/android/webkit/WebSettings#setFixedFontFamily(java.lang.String))) - String? fixedFontFamily; - - ///Set the force dark mode for this WebView. The default value is [ForceDark.OFF]. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView 29+ ([Official API - WebSettings.setForceDark](https://developer.android.com/reference/android/webkit/WebSettings#setForceDark(int))) - ForceDark? forceDark; - - ///Sets whether Geolocation API is enabled. The default value is `true`. - ///Set how WebView content should be darkened. - ///The default value is [ForceDarkStrategy.PREFER_WEB_THEME_OVER_USER_AGENT_DARKENING]. - /// - ///**NOTE for Android native WebView**: it will take effect only if [WebViewFeature.isFeatureSupported] returns `true` for [WebViewFeature.FORCE_DARK_STRATEGY]. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettingsCompat.setForceDarkStrategy](https://developer.android.com/reference/androidx/webkit/WebSettingsCompat#setForceDarkStrategy(android.webkit.WebSettings,int))) - ForceDarkStrategy? forceDarkStrategy; - - ///Sets whether Geolocation is enabled. The default is `true`. - /// - ///**NOTE for Android native WebView**: Please note that in order for the Geolocation API to be usable by a page in the WebView, the following requirements must be met: - ///- an application must have permission to access the device location, see [Manifest.permission.ACCESS_COARSE_LOCATION](https://developer.android.com/reference/android/Manifest.permission#ACCESS_COARSE_LOCATION), [Manifest.permission.ACCESS_FINE_LOCATION](https://developer.android.com/reference/android/Manifest.permission#ACCESS_FINE_LOCATION); - ///- an application must provide an implementation of the [WebView.onGeolocationPermissionsShowPrompt] callback to receive notifications that a page is requesting access to location via the JavaScript Geolocation API. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setGeolocationEnabled](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setGeolocationEnabled(boolean))) - bool? geolocationEnabled; - - ///Sets the underlying layout algorithm. This will cause a re-layout of the WebView. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setLayoutAlgorithm](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setLayoutAlgorithm(android.webkit.WebSettings.LayoutAlgorithm))) - LayoutAlgorithm? layoutAlgorithm; - - ///Sets whether the WebView loads pages in overview mode, that is, zooms out the content to fit on screen by width. - ///This setting is taken into account when the content width is greater than the width of the WebView control, for example, when [useWideViewPort] is enabled. - ///The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setLoadWithOverviewMode](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setLoadWithOverviewMode(boolean))) - bool? loadWithOverviewMode; - - ///Sets whether the WebView should load image resources. Note that this method controls loading of all images, including those embedded using the data URI scheme. - ///Note that if the value of this setting is changed from false to true, all images resources referenced by content currently displayed by the WebView are loaded automatically. - ///The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setLoadsImagesAutomatically](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setLoadsImagesAutomatically(boolean))) - bool? loadsImagesAutomatically; - - ///Sets the minimum logical font size. The default is `8`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setMinimumLogicalFontSize](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setMinimumLogicalFontSize(int))) - int? minimumLogicalFontSize; - - ///Sets the initial scale for this WebView. 0 means default. The behavior for the default scale depends on the state of [useWideViewPort] and [loadWithOverviewMode]. - ///If the content fits into the WebView control by width, then the zoom is set to 100%. For wide content, the behavior depends on the state of [loadWithOverviewMode]. - ///If its value is true, the content will be zoomed out to be fit by width into the WebView control, otherwise not. - ///If initial scale is greater than 0, WebView starts with this value as initial scale. - ///Please note that unlike the scale properties in the viewport meta tag, this method doesn't take the screen density into account. - ///The default is `0`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebView.setInitialScale](https://developer.android.com/reference/android/webkit/WebView#setInitialScale(int))) - int? initialScale; - - ///Tells the WebView whether it needs to set a node. The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setNeedInitialFocus](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setNeedInitialFocus(boolean))) - bool? needInitialFocus; - - ///Sets whether this WebView should raster tiles when it is offscreen but attached to a window. - ///Turning this on can avoid rendering artifacts when animating an offscreen WebView on-screen. - ///Offscreen WebViews in this mode use more memory. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView 23+ ([Official API - WebSettings.setOffscreenPreRaster](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setOffscreenPreRaster(boolean))) - bool? offscreenPreRaster; - - ///Sets the sans-serif font family name. The default value is `"sans-serif"`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setSansSerifFontFamily](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setSansSerifFontFamily(java.lang.String))) - String? sansSerifFontFamily; - - ///Sets the serif font family name. The default value is `"sans-serif"`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setSerifFontFamily](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setSerifFontFamily(java.lang.String))) - String? serifFontFamily; - - ///Sets the standard font family name. The default value is `"sans-serif"`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setStandardFontFamily](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setStandardFontFamily(java.lang.String))) - String? standardFontFamily; - - ///Sets whether the WebView should save form data. In Android O, the platform has implemented a fully functional Autofill feature to store form data. - ///Therefore, the Webview form data save feature is disabled. Note that the feature will continue to be supported on older versions of Android as before. - ///The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setSaveFormData](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setSaveFormData(boolean))) - bool? saveFormData; - - ///Boolean value to enable third party cookies in the WebView. - ///Used on Android Lollipop and above only as third party cookies are enabled by default on Android Kitkat and below and on iOS. - ///The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView 21+ ([Official API - CookieManager.setAcceptThirdPartyCookies](https://developer.android.com/reference/android/webkit/CookieManager#setAcceptThirdPartyCookies(android.webkit.WebView,%20boolean))) - bool? thirdPartyCookiesEnabled; - - ///Boolean value to enable Hardware Acceleration in the WebView. - ///The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebView.setLayerType](https://developer.android.com/reference/android/webkit/WebView#setLayerType(int,%20android.graphics.Paint))) - bool? hardwareAcceleration; - - ///Sets whether the WebView supports multiple windows. - ///If set to `true`, [WebView.onCreateWindow] event must be implemented by the host application. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebSettings.setSupportMultipleWindows](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setSupportMultipleWindows(boolean))) - bool? supportMultipleWindows; - - ///Regular expression used by [WebView.shouldOverrideUrlLoading] event to cancel navigation requests for frames that are not the main frame. - ///If the url request of a subframe matches the regular expression, then the request of that subframe is canceled. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - String? regexToCancelSubFramesLoading; - - ///Set to `false` to disable Flutter Hybrid Composition. The default value is `true`. - ///Hybrid Composition is supported starting with Flutter v1.20+. - /// - ///**NOTE for Android native WebView**: It is recommended to use Hybrid Composition only on Android 10+ for a release app, - ///as it can cause framerate drops on animations in Android 9 and lower (see [Hybrid-Composition#performance](https://github.com/flutter/flutter/wiki/Hybrid-Composition#performance)). - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - bool? useHybridComposition; - - ///Set to `true` to be able to listen at the [WebView.shouldInterceptRequest] event. - /// - ///If the [WebView.shouldInterceptRequest] event is implemented and this value is `null`, - ///it will be automatically inferred as `true`, otherwise, the default value is `false`. - ///This logic will not be applied for [InAppBrowser], where you must set the value manually. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - bool? useShouldInterceptRequest; - - ///Set to `true` to be able to listen at the [WebView.onRenderProcessGone] event. - /// - ///If the [WebView.onRenderProcessGone] event is implemented and this value is `null`, - ///it will be automatically inferred as `true`, otherwise, the default value is `false`. - ///This logic will not be applied for [InAppBrowser], where you must set the value manually. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - bool? useOnRenderProcessGone; - - ///Sets the WebView's over-scroll mode. - ///Setting the over-scroll mode of a WebView will have an effect only if the WebView is capable of scrolling. - ///The default value is [OverScrollMode.IF_CONTENT_SCROLLS]. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - View.setOverScrollMode](https://developer.android.com/reference/android/view/View#setOverScrollMode(int))) - OverScrollMode? overScrollMode; - - ///Informs WebView of the network state. - ///This is used to set the JavaScript property `window.navigator.isOnline` and generates the online/offline event as specified in HTML5, sec. 5.7.7. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebView.setNetworkAvailable](https://developer.android.com/reference/android/webkit/WebView#setNetworkAvailable(boolean))) - bool? networkAvailable; - - ///Specifies the style of the scrollbars. The scrollbars can be overlaid or inset. - ///When inset, they add to the padding of the view. And the scrollbars can be drawn inside the padding area or on the edge of the view. - ///For example, if a view has a background drawable and you want to draw the scrollbars inside the padding specified by the drawable, - ///you can use SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to appear at the edge of the view, ignoring the padding, - ///then you can use SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET. - ///The default value is [ScrollBarStyle.SCROLLBARS_INSIDE_OVERLAY]. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebView.setScrollBarStyle](https://developer.android.com/reference/android/webkit/WebView#setScrollBarStyle(int))) - ScrollBarStyle? scrollBarStyle; - - ///Sets the position of the vertical scroll bar. - ///The default value is [VerticalScrollbarPosition.SCROLLBAR_POSITION_DEFAULT]. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - View.setVerticalScrollbarPosition](https://developer.android.com/reference/android/view/View#setVerticalScrollbarPosition(int))) - VerticalScrollbarPosition? verticalScrollbarPosition; - - ///Defines the delay in milliseconds that a scrollbar waits before fade out. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - View.setScrollBarDefaultDelayBeforeFade](https://developer.android.com/reference/android/view/View#setScrollBarDefaultDelayBeforeFade(int))) - int? scrollBarDefaultDelayBeforeFade; - - ///Defines whether scrollbars will fade when the view is not scrolling. - ///The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - View.setScrollbarFadingEnabled](https://developer.android.com/reference/android/view/View#setScrollbarFadingEnabled(boolean))) - bool? scrollbarFadingEnabled; - - ///Defines the scrollbar fade duration in milliseconds. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - View.setScrollBarFadeDuration](https://developer.android.com/reference/android/view/View#setScrollBarFadeDuration(int))) - int? scrollBarFadeDuration; - - ///Sets the renderer priority policy for this WebView. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView ([Official API - WebView.setRendererPriorityPolicy](https://developer.android.com/reference/android/webkit/WebView#setRendererPriorityPolicy(int,%20boolean))) - RendererPriorityPolicy? rendererPriorityPolicy; - - ///Sets whether the default Android WebView’s internal error page should be suppressed or displayed for bad navigations. - ///`true` means suppressed (not shown), `false` means it will be displayed. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - bool? disableDefaultErrorPage; - - ///Sets the vertical scrollbar thumb color. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView 29+ ([Official API - View.setVerticalScrollbarThumbDrawable](https://developer.android.com/reference/android/view/View#setVerticalScrollbarThumbDrawable(android.graphics.drawable.Drawable))) - Color? verticalScrollbarThumbColor; - - ///Sets the vertical scrollbar track color. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView 29+ ([Official API - View.setVerticalScrollbarTrackDrawable](https://developer.android.com/reference/android/view/View#setVerticalScrollbarTrackDrawable(android.graphics.drawable.Drawable))) - Color? verticalScrollbarTrackColor; - - ///Sets the horizontal scrollbar thumb color. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView 29+ ([Official API - View.setHorizontalScrollbarThumbDrawable](https://developer.android.com/reference/android/view/View#setHorizontalScrollbarThumbDrawable(android.graphics.drawable.Drawable))) - Color? horizontalScrollbarThumbColor; - - ///Sets the horizontal scrollbar track color. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView 29+ ([Official API - View.setHorizontalScrollbarTrackDrawable](https://developer.android.com/reference/android/view/View#setHorizontalScrollbarTrackDrawable(android.graphics.drawable.Drawable))) - Color? horizontalScrollbarTrackColor; - - ///Control whether algorithmic darkening is allowed. - /// - ///WebView always sets the media query `prefers-color-scheme` according to the app's theme attribute `isLightTheme`, - ///i.e. `prefers-color-scheme` is light if `isLightTheme` is `true` or not specified, otherwise it is `dark`. - ///This means that the web content's light or dark style will be applied automatically to match the app's theme if the content supports it. - /// - ///Algorithmic darkening is disallowed by default. - /// - ///If the app's theme is dark and it allows algorithmic darkening, - ///WebView will attempt to darken web content using an algorithm, - ///if the content doesn't define its own dark styles and doesn't explicitly disable darkening. - /// - ///**NOTE for Android native WebView**: available on Android only if [WebViewFeature.ALGORITHMIC_DARKENING] feature is supported. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView 29+ ([Official API - WebSettingsCompat.setAlgorithmicDarkeningAllowed](https://developer.android.com/reference/androidx/webkit/WebSettingsCompat#setAlgorithmicDarkeningAllowed(android.webkit.WebSettings,boolean))) - bool? algorithmicDarkeningAllowed; - - ///Sets how the WebView will set the `X-Requested-With` header on requests. - ///If you are calling this method, you may also want to call [ServiceWorkerWebSettingsCompat.setRequestedWithHeaderMode] - ///with the same parameter value to configure ServiceWorker requests. - ///The default behavior may vary depending on the WebView implementation. - /// - ///**NOTE for Android native WebView**: available on Android only if [WebViewFeature.REQUESTED_WITH_HEADER_CONTROL] feature is supported. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - RequestedWithHeaderMode? requestedWithHeaderMode; - - ///Sets whether EnterpriseAuthenticationAppLinkPolicy if set by admin is allowed to have any - ///effect on WebView. - /// - ///EnterpriseAuthenticationAppLinkPolicy in WebView allows admins to specify authentication - ///urls. When WebView is redirected to authentication url, and an app on the device has - ///registered as the default handler for the url, that app is launched. - /// - ///The default value is `true`. - /// - ///**NOTE for Android native WebView**: available on Android only if [WebViewFeature.ENTERPRISE_AUTHENTICATION_APP_LINK_POLICY] feature is supported. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - bool? enterpriseAuthenticationAppLinkPolicyEnabled; - - ///When not playing, video elements are represented by a 'poster' image. - ///The image to use can be specified by the poster attribute of the video tag in HTML. - ///If the attribute is absent, then a default poster will be used. - ///This property allows the WebView to provide that default image. - /// - ///**Supported Platforms/Implementations**: - ///- Android native WebView - Uint8List? defaultVideoPoster; - - ///Set to `true` to disable the bouncing of the WebView when the scrolling has reached an edge of the content. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- iOS - bool? disallowOverScroll; - - ///Set to `true` to allow a viewport meta tag to either disable or restrict the range of user scaling. The default value is `false`. + ///Used in combination with [WebView.initialUrlRequest] or [WebView.initialData] (using the `file://` scheme), it represents the URL from which to read the web content. + ///This URL must be a file-based URL (using the `file://` scheme). + ///Specify the same value as the [URLRequest.url] if you are using it with the [WebView.initialUrlRequest] parameter or + ///the [InAppWebViewInitialData.baseUrl] if you are using it with the [WebView.initialData] parameter to prevent WebView from reading any other content. + ///Specify a directory to give WebView permission to read additional files in the specified directory. /// ///**Supported Platforms/Implementations**: ///- iOS ///- MacOS - bool? enableViewportScale; - - ///Set to `true` if you want the WebView suppresses content rendering until it is fully loaded into memory. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- iOS ([Official API - WKWebViewConfiguration.suppressesIncrementalRendering](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/1395663-suppressesincrementalrendering)) - ///- MacOS ([Official API - WKWebViewConfiguration.suppressesIncrementalRendering](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/1395663-suppressesincrementalrendering)) - bool? suppressesIncrementalRendering; + WebUri? allowingReadAccessTo; ///Set to `true` to allow AirPlay. The default value is `true`. /// @@ -759,20 +115,6 @@ class InAppWebViewSettings { ///- MacOS ([Official API - WKWebView.allowsBackForwardNavigationGestures](https://developer.apple.com/documentation/webkit/wkwebview/1414995-allowsbackforwardnavigationgestu)) bool? allowsBackForwardNavigationGestures; - ///Set to `true` to allow that pressing on a link displays a preview of the destination for the link. The default value is `true`. - /// - ///**Supported Platforms/Implementations**: - ///- iOS ([Official API - WKWebView.allowsLinkPreview](https://developer.apple.com/documentation/webkit/wkwebview/1415000-allowslinkpreview)) - ///- MacOS ([Official API - WKWebView.allowsLinkPreview](https://developer.apple.com/documentation/webkit/wkwebview/1415000-allowslinkpreview)) - bool? allowsLinkPreview; - - ///Set to `true` if you want that the WebView should always allow scaling of the webpage, regardless of the author's intent. - ///The ignoresViewportScaleLimits property overrides the `user-scalable` HTML property in a webpage. The default value is `false`. - /// - ///**Supported Platforms/Implementations**: - ///- iOS ([Official API - WKWebViewConfiguration.ignoresViewportScaleLimits](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/2274633-ignoresviewportscalelimits)) - bool? ignoresViewportScaleLimits; - ///Set to `true` to allow HTML5 media playback to appear inline within the screen layout, using browser-supplied controls rather than native controls. ///For this to work, add the `webkit-playsinline` attribute to any `