| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/foundation.dart'; |
| import 'package:flutter/widgets.dart' show AndroidViewSurface; |
| |
| import 'android_webview_api_impls.dart'; |
| |
| // TODO(bparrishMines): This can be removed once pigeon supports null values: https://github.com/flutter/flutter/issues/59118 |
| // Workaround to represent null Strings since pigeon doesn't support null |
| // values. |
| const String _nullStringIdentifier = '<null-value>'; |
| |
| /// An Android View that displays web pages. |
| /// |
| /// **Basic usage** |
| /// In most cases, we recommend using a standard web browser, like Chrome, to |
| /// deliver content to the user. To learn more about web browsers, read the |
| /// guide on invoking a browser with |
| /// [url_launcher](https://pub.dev/packages/url_launcher). |
| /// |
| /// WebView objects allow you to display web content as part of your widget |
| /// layout, but lack some of the features of fully-developed browsers. A WebView |
| /// is useful when you need increased control over the UI and advanced |
| /// configuration options that will allow you to embed web pages in a |
| /// specially-designed environment for your app. |
| /// |
| /// To learn more about WebView and alternatives for serving web content, read |
| /// the documentation on |
| /// [Web-based content](https://developer.android.com/guide/webapps). |
| class WebView { |
| /// Constructs a new WebView. |
| WebView({this.useHybridComposition = false}) { |
| api.createFromInstance(this); |
| } |
| |
| /// Pigeon Host Api implementation for [WebView]. |
| @visibleForTesting |
| static WebViewHostApiImpl api = WebViewHostApiImpl(); |
| |
| WebViewClient? _currentWebViewClient; |
| DownloadListener? _currentDownloadListener; |
| WebChromeClient? _currentWebChromeClient; |
| Set<JavaScriptChannel> _javaScriptChannels = <JavaScriptChannel>{}; |
| |
| /// Whether the [WebView] will be rendered with an [AndroidViewSurface]. |
| /// |
| /// This implementation uses hybrid composition to render the WebView Widget. |
| /// This comes at the cost of some performance on Android versions below 10. |
| /// See |
| /// https://flutter.dev/docs/development/platform-integration/platform-views#performance |
| /// for more information. |
| /// |
| /// Defaults to false. |
| final bool useHybridComposition; |
| |
| /// The [WebSettings] object used to control the settings for this WebView. |
| late final WebSettings settings = WebSettings(this); |
| |
| /// Enables debugging of web contents (HTML / CSS / JavaScript) loaded into any WebViews of this application. |
| /// |
| /// This flag can be enabled in order to facilitate debugging of web layouts |
| /// and JavaScript code running inside WebViews. Please refer to [WebView] |
| /// documentation for the debugging guide. The default is false. |
| static Future<void> setWebContentsDebuggingEnabled(bool enabled) { |
| return api.setWebContentsDebuggingEnabled(enabled); |
| } |
| |
| /// Loads the given URL with additional HTTP headers, specified as a map from name to value. |
| /// |
| /// Note that if this map contains any of the headers that are set by default |
| /// by this WebView, such as those controlling caching, accept types or the |
| /// User-Agent, their values may be overridden by this WebView's defaults. |
| /// |
| /// Also see compatibility note on [evaluateJavascript]. |
| Future<void> loadUrl(String url, Map<String, String> headers) { |
| return api.loadUrlFromInstance(this, url, headers); |
| } |
| |
| /// Gets the URL for the current page. |
| /// |
| /// This is not always the same as the URL passed to |
| /// [WebViewClient.onPageStarted] because although the load for that URL has |
| /// begun, the current page may not have changed. |
| /// |
| /// Returns null if no page has been loaded. |
| Future<String?> getUrl() async { |
| final String result = await api.getUrlFromInstance(this); |
| if (result == _nullStringIdentifier) return null; |
| return result; |
| } |
| |
| /// Whether this WebView has a back history item. |
| Future<bool> canGoBack() { |
| return api.canGoBackFromInstance(this); |
| } |
| |
| /// Whether this WebView has a forward history item. |
| Future<bool> canGoForward() { |
| return api.canGoForwardFromInstance(this); |
| } |
| |
| /// Goes back in the history of this WebView. |
| Future<void> goBack() { |
| return api.goBackFromInstance(this); |
| } |
| |
| /// Goes forward in the history of this WebView. |
| Future<void> goForward() { |
| return api.goForwardFromInstance(this); |
| } |
| |
| /// Reloads the current URL. |
| Future<void> reload() { |
| return api.reloadFromInstance(this); |
| } |
| |
| /// Clears the resource cache. |
| /// |
| /// Note that the cache is per-application, so this will clear the cache for |
| /// all WebViews used. |
| Future<void> clearCache(bool includeDiskFiles) { |
| return api.clearCacheFromInstance(this, includeDiskFiles); |
| } |
| |
| // TODO(bparrishMines): Update documentation once addJavascriptInterface is added. |
| /// Asynchronously evaluates JavaScript in the context of the currently displayed page. |
| /// |
| /// If non-null, the returned value will be any result returned from that |
| /// execution. |
| /// |
| /// Compatibility note. Applications targeting Android versions N or later, |
| /// JavaScript state from an empty WebView is no longer persisted across |
| /// navigations like [loadUrl]. For example, global variables and functions |
| /// defined before calling [loadUrl]) will not exist in the loaded page. |
| Future<String?> evaluateJavascript(String javascriptString) async { |
| final String result = await api.evaluateJavascriptFromInstance( |
| this, |
| javascriptString, |
| ); |
| if (result == _nullStringIdentifier) return null; |
| return result; |
| } |
| |
| // TODO(bparrishMines): Update documentation when WebViewClient.onReceivedTitle is added. |
| /// Gets the title for the current page. |
| /// |
| /// Returns null if no page has been loaded. |
| Future<String?> getTitle() async { |
| final String result = await api.getTitleFromInstance(this); |
| if (result == _nullStringIdentifier) return null; |
| return result; |
| } |
| |
| // TODO(bparrishMines): Update documentation when onScrollChanged is added. |
| /// Set the scrolled position of your view. |
| Future<void> scrollTo(int x, int y) { |
| return api.scrollToFromInstance(this, x, y); |
| } |
| |
| // TODO(bparrishMines): Update documentation when onScrollChanged is added. |
| /// Move the scrolled position of your view. |
| Future<void> scrollBy(int x, int y) { |
| return api.scrollByFromInstance(this, x, y); |
| } |
| |
| /// Return the scrolled left position of this view. |
| /// |
| /// This is the left edge of the displayed part of your view. You do not |
| /// need to draw any pixels farther left, since those are outside of the frame |
| /// of your view on screen. |
| Future<int> getScrollX() { |
| return api.getScrollXFromInstance(this); |
| } |
| |
| /// Return the scrolled top position of this view. |
| /// |
| /// This is the top edge of the displayed part of your view. You do not need |
| /// to draw any pixels above it, since those are outside of the frame of your |
| /// view on screen. |
| Future<int> getScrollY() { |
| return api.getScrollYFromInstance(this); |
| } |
| |
| /// Sets the [WebViewClient] that will receive various notifications and requests. |
| /// |
| /// This will replace the current handler. |
| Future<void> setWebViewClient(WebViewClient webViewClient) { |
| final WebViewClient? currentWebViewClient = _currentWebViewClient; |
| |
| if (webViewClient == currentWebViewClient) { |
| return Future<void>.value(); |
| } |
| |
| if (currentWebViewClient != null) { |
| WebViewClient.api.disposeFromInstance(currentWebViewClient); |
| } |
| |
| WebViewClient.api.createFromInstance(webViewClient); |
| _currentWebViewClient = webViewClient; |
| return api.setWebViewClientFromInstance(this, webViewClient); |
| } |
| |
| /// Injects the supplied [JavascriptChannel] into this WebView. |
| /// |
| /// The object is injected into all frames of the web page, including all the |
| /// iframes, using the supplied name. This allows the object's methods to |
| /// be accessed from JavaScript. |
| /// |
| /// Note that injected objects will not appear in JavaScript until the page is |
| /// next (re)loaded. JavaScript should be enabled before injecting the object. |
| /// For example: |
| /// |
| /// ```dart |
| /// webview.settings.setJavaScriptEnabled(true); |
| /// webView.addJavascriptChannel(JavScriptChannel("injectedObject")); |
| /// webView.loadUrl("about:blank", <String, String>{}); |
| /// webView.loadUrl("javascript:injectedObject.postMessage("Hello, World!")", <String, String>{}); |
| /// ``` |
| /// |
| /// **Important** |
| /// * Because the object is exposed to all the frames, any frame could obtain |
| /// the object name and call methods on it. There is no way to tell the |
| /// calling frame's origin from the app side, so the app must not assume that |
| /// the caller is trustworthy unless the app can guarantee that no third party |
| /// content is ever loaded into the WebView even inside an iframe. |
| Future<void> addJavaScriptChannel(JavaScriptChannel javaScriptChannel) { |
| JavaScriptChannel.api.createFromInstance(javaScriptChannel); |
| _javaScriptChannels.add(javaScriptChannel); |
| return api.addJavaScriptChannelFromInstance(this, javaScriptChannel); |
| } |
| |
| /// Removes a previously injected [JavaScriptChannel] from this WebView. |
| /// |
| /// Note that the removal will not be reflected in JavaScript until the page |
| /// is next (re)loaded. See [addJavaScriptChannel]. |
| Future<void> removeJavaScriptChannel(JavaScriptChannel javaScriptChannel) { |
| _javaScriptChannels.remove(javaScriptChannel); |
| api.removeJavaScriptChannelFromInstance(this, javaScriptChannel); |
| return JavaScriptChannel.api.disposeFromInstance(javaScriptChannel); |
| } |
| |
| /// Registers the interface to be used when content can not be handled by the rendering engine, and should be downloaded instead. |
| /// |
| /// This will replace the current handler. |
| Future<void> setDownloadListener(DownloadListener listener) { |
| final DownloadListener? currentDownloadListener = _currentDownloadListener; |
| |
| if (listener == currentDownloadListener) { |
| return Future<void>.value(); |
| } |
| |
| if (currentDownloadListener != null) { |
| DownloadListener.api.disposeFromInstance(currentDownloadListener); |
| } |
| |
| DownloadListener.api.createFromInstance(listener); |
| _currentDownloadListener = listener; |
| return api.setDownloadListenerFromInstance(this, listener); |
| } |
| |
| /// Sets the chrome handler. |
| /// |
| /// This is an implementation of [WebChromeClient] for use in handling |
| /// JavaScript dialogs, favicons, titles, and the progress. This will replace |
| /// the current handler. |
| Future<void> setWebChromeClient(WebChromeClient client) { |
| final WebChromeClient? currentWebChromeClient = _currentWebChromeClient; |
| |
| if (client == currentWebChromeClient) { |
| return Future<void>.value(); |
| } |
| |
| if (currentWebChromeClient != null) { |
| WebChromeClient.api.disposeFromInstance(currentWebChromeClient); |
| } |
| |
| final WebViewClient? currentWebViewClient = _currentWebViewClient; |
| assert( |
| currentWebViewClient != null, |
| "Can't set a WebChromeClient without setting a WebViewClient first.", |
| ); |
| |
| WebChromeClient.api.createFromInstance(client, currentWebViewClient!); |
| _currentWebChromeClient = client; |
| return api.setWebChromeClientFromInstance(this, client); |
| } |
| } |
| |
| /// Manages settings state for a [WebView]. |
| /// |
| /// When a WebView is first created, it obtains a set of default settings. These |
| /// default settings will be returned from any getter call. A WebSettings object |
| /// obtained from [WebView.settings] is tied to the life of the WebView. If a |
| /// WebView has been destroyed, any method call on [WebSettings] will throw an |
| /// Exception. |
| class WebSettings { |
| /// Constructs a [WebSettings]. |
| /// |
| /// This constructor is only used for testing. An instance should be obtained |
| /// with [WebView.settings]. |
| @visibleForTesting |
| WebSettings(WebView webView) { |
| api.createFromInstance(this, webView); |
| } |
| |
| /// Pigeon Host Api implementation for [WebSettings]. |
| @visibleForTesting |
| static WebSettingsHostApiImpl api = WebSettingsHostApiImpl(); |
| |
| /// Sets whether the DOM storage API is enabled. |
| /// |
| /// The default value is false. |
| Future<void> setDomStorageEnabled(bool flag) { |
| return api.setDomStorageEnabledFromInstance(this, flag); |
| } |
| |
| /// Tells JavaScript to open windows automatically. |
| /// |
| /// This applies to the JavaScript function `window.open()`. The default is |
| /// false. |
| Future<void> setJavaScriptCanOpenWindowsAutomatically(bool flag) { |
| return api.setJavaScriptCanOpenWindowsAutomaticallyFromInstance( |
| this, |
| flag, |
| ); |
| } |
| |
| // TODO(bparrishMines): Update documentation when WebChromeClient.onCreateWindow is added. |
| /// Sets whether the WebView should supports multiple windows. |
| /// |
| /// The default is false. |
| Future<void> setSupportMultipleWindows(bool support) { |
| return api.setSupportZoomFromInstance(this, support); |
| } |
| |
| /// Tells the WebView to enable JavaScript execution. |
| /// |
| /// The default is false. |
| Future<void> setJavaScriptEnabled(bool flag) { |
| return api.setJavaScriptEnabledFromInstance(this, flag); |
| } |
| |
| /// Sets the WebView's user-agent string. |
| /// |
| /// If the string is empty, the system default value will be used. Note that |
| /// starting from KITKAT Android version, changing the user-agent while |
| /// loading a web page causes WebView to initiate loading once again. |
| Future<void> setUserAgentString(String userAgentString) { |
| return api.setUserAgentStringFromInstance(this, userAgentString); |
| } |
| |
| /// Sets whether the WebView requires a user gesture to play media. |
| /// |
| /// The default is true. |
| Future<void> setMediaPlaybackRequiresUserGesture(bool require) { |
| return api.setMediaPlaybackRequiresUserGestureFromInstance(this, require); |
| } |
| |
| // TODO(bparrishMines): Update documentation when WebView.zoomIn and WebView.zoomOut are added. |
| /// Sets whether the WebView should support zooming using its on-screen zoom controls and gestures. |
| /// |
| /// The particular zoom mechanisms that should be used can be set with |
| /// [setBuiltInZoomControls]. |
| /// |
| /// The default is true. |
| Future<void> setSupportZoom(bool support) { |
| return api.setSupportZoomFromInstance(this, support); |
| } |
| |
| /// 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 [setUseWideViewPort] |
| /// is enabled. |
| /// |
| /// The default is false. |
| Future<void> setLoadWithOverviewMode(bool overview) { |
| return api.setLoadWithOverviewModeFromInstance(this, overview); |
| } |
| |
| /// Sets whether 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. |
| Future<void> setUseWideViewPort(bool use) { |
| return api.setUseWideViewPortFromInstance(this, use); |
| } |
| |
| // TODO(bparrishMines): Update documentation when ZoomButtonsController is added. |
| /// Sets whether the WebView should display on-screen zoom controls when using the built-in zoom mechanisms. |
| /// |
| /// See [setBuiltInZoomControls]. The default is true. However, on-screen zoom |
| /// controls are deprecated in Android so it's recommended to set this to |
| /// false. |
| Future<void> setDisplayZoomControls(bool enabled) { |
| return api.setDisplayZoomControlsFromInstance(this, enabled); |
| } |
| |
| // TODO(bparrishMines): Update documentation when ZoomButtonsController is added. |
| /// Sets whether the WebView should use its built-in zoom mechanisms. |
| /// |
| /// The built-in zoom mechanisms comprise on-screen zoom controls, which are |
| /// displayed over the WebView's content, and the use of a pinch gesture to |
| /// control zooming. Whether or not these on-screen controls are displayed can |
| /// be set with [setDisplayZoomControls]. The default is false. |
| /// |
| /// The built-in mechanisms are the only currently supported zoom mechanisms, |
| /// so it is recommended that this setting is always enabled. However, |
| /// on-screen zoom controls are deprecated in Android so it's recommended to |
| /// disable [setDisplayZoomControls]. |
| Future<void> setBuiltInZoomControls(bool enabled) { |
| return api.setBuiltInZoomControlsFromInstance(this, enabled); |
| } |
| } |
| |
| /// Exposes a channel to receive calls from javaScript. |
| /// |
| /// See [WebView.addJavaScriptChannel]. |
| abstract class JavaScriptChannel { |
| /// Constructs a [JavaScriptChannel]. |
| JavaScriptChannel(this.channelName); |
| |
| /// Pigeon Host Api implementation for [JavaScriptChannel]. |
| @visibleForTesting |
| static JavaScriptChannelHostApiImpl api = JavaScriptChannelHostApiImpl(); |
| |
| /// Used to identify this object to receive messages from javaScript. |
| final String channelName; |
| |
| /// Callback method when javaScript calls `postMessage` on the object instance passed. |
| void postMessage(String message) {} |
| } |
| |
| /// Receive various notifications and requests for [WebView]. |
| abstract class WebViewClient { |
| /// Constructs a [WebViewClient]. |
| WebViewClient({this.shouldOverrideUrlLoading = true}); |
| |
| /// User authentication failed on server. |
| static const int errorAuthentication = 0xfffffffc; |
| |
| /// Malformed URL. |
| static const int errorBadUrl = 0xfffffff4; |
| |
| /// Failed to connect to the server. |
| static const int errorConnect = 0xfffffffa; |
| |
| /// Failed to perform SSL handshake. |
| static const int errorFailedSslHandshake = 0xfffffff5; |
| |
| /// Generic file error. |
| static const int errorFile = 0xfffffff3; |
| |
| /// File not found. |
| static const int errorFileNotFound = 0xfffffff2; |
| |
| /// Server or proxy hostname lookup failed. |
| static const int errorHostLookup = 0xfffffffe; |
| |
| /// Failed to read or write to the server. |
| static const int errorIO = 0xfffffff9; |
| |
| /// User authentication failed on proxy. |
| static const int errorProxyAuthentication = 0xfffffffb; |
| |
| /// Too many redirects. |
| static const int errorRedirectLoop = 0xfffffff7; |
| |
| /// Connection timed out. |
| static const int errorTimeout = 0xfffffff8; |
| |
| /// Too many requests during this load. |
| static const int errorTooManyRequests = 0xfffffff1; |
| |
| /// Generic error. |
| static const int errorUnknown = 0xffffffff; |
| |
| /// Resource load was canceled by Safe Browsing. |
| static const int errorUnsafeResource = 0xfffffff0; |
| |
| /// Unsupported authentication scheme (not basic or digest). |
| static const int errorUnsupportedAuthScheme = 0xfffffffd; |
| |
| /// Unsupported URI scheme. |
| static const int errorUnsupportedScheme = 0xfffffff6; |
| |
| /// Pigeon Host Api implementation for [WebViewClient]. |
| @visibleForTesting |
| static WebViewClientHostApiImpl api = WebViewClientHostApiImpl(); |
| |
| /// Whether loading a url should be overridden. |
| /// |
| /// In Java, `shouldOverrideUrlLoading()` and `shouldOverrideRequestLoading()` |
| /// callbacks must synchronously return a boolean. This sets the default |
| /// return value. |
| /// |
| /// Setting [shouldOverrideUrlLoading] to true causes the current [WebView] to |
| /// abort loading the URL, while returning false causes the [WebView] to |
| /// continue loading the URL as usual. [requestLoading] or [urlLoading] will |
| /// still be called either way. |
| /// |
| /// Defaults to true. |
| final bool shouldOverrideUrlLoading; |
| |
| /// Notify the host application that a page has started loading. |
| /// |
| /// This method is called once for each main frame load so a page with iframes |
| /// or framesets will call onPageStarted one time for the main frame. This |
| /// also means that [onPageStarted] will not be called when the contents of an |
| /// embedded frame changes, i.e. clicking a link whose target is an iframe, it |
| /// will also not be called for fragment navigations (navigations to |
| /// #fragment_id). |
| void onPageStarted(WebView webView, String url) {} |
| |
| // TODO(bparrishMines): Update documentation when WebView.postVisualStateCallback is added. |
| /// Notify the host application that a page has finished loading. |
| /// |
| /// This method is called only for main frame. Receiving an [onPageFinished] |
| /// callback does not guarantee that the next frame drawn by WebView will |
| /// reflect the state of the DOM at this point. |
| void onPageFinished(WebView webView, String url) {} |
| |
| /// Report web resource loading error to the host application. |
| /// |
| /// These errors usually indicate inability to connect to the server. Note |
| /// that unlike the deprecated version of the callback, the new version will |
| /// be called for any resource (iframe, image, etc.), not just for the main |
| /// page. Thus, it is recommended to perform minimum required work in this |
| /// callback. |
| void onReceivedRequestError( |
| WebView webView, |
| WebResourceRequest request, |
| WebResourceError error, |
| ) {} |
| |
| /// Report an error to the host application. |
| /// |
| /// These errors are unrecoverable (i.e. the main resource is unavailable). |
| /// The errorCode parameter corresponds to one of the error* constants. |
| @Deprecated('Only called on Android version < 23.') |
| void onReceivedError( |
| WebView webView, |
| int errorCode, |
| String description, |
| String failingUrl, |
| ) {} |
| |
| // TODO(bparrishMines): Update documentation once synchronous url handling is supported. |
| /// When a URL is about to be loaded in the current [WebView]. |
| /// |
| /// If a [WebViewClient] is not provided, by default [WebView] will ask |
| /// Activity Manager to choose the proper handler for the URL. If a |
| /// [WebViewClient] is provided, setting [shouldOverrideUrlLoading] to true |
| /// causes the current [WebView] to abort loading the URL, while returning |
| /// false causes the [WebView] to continue loading the URL as usual. |
| void requestLoading(WebView webView, WebResourceRequest request) {} |
| |
| // TODO(bparrishMines): Update documentation once synchronous url handling is supported. |
| /// When a URL is about to be loaded in the current [WebView]. |
| /// |
| /// If a [WebViewClient] is not provided, by default [WebView] will ask |
| /// Activity Manager to choose the proper handler for the URL. If a |
| /// [WebViewClient] is provided, setting [shouldOverrideUrlLoading] to true |
| /// causes the current [WebView] to abort loading the URL, while returning |
| /// false causes the [WebView] to continue loading the URL as usual. |
| void urlLoading(WebView webView, String url) {} |
| } |
| |
| /// The interface to be used when content can not be handled by the rendering engine for [WebView], and should be downloaded instead. |
| abstract class DownloadListener { |
| /// Pigeon Host Api implementation for [DownloadListener]. |
| @visibleForTesting |
| static DownloadListenerHostApiImpl api = DownloadListenerHostApiImpl(); |
| |
| /// Notify the host application that a file should be downloaded. |
| void onDownloadStart( |
| String url, |
| String userAgent, |
| String contentDisposition, |
| String mimetype, |
| int contentLength, |
| ); |
| } |
| |
| /// Handles JavaScript dialogs, favicons, titles, and the progress for [WebView]. |
| abstract class WebChromeClient { |
| /// Pigeon Host Api implementation for [WebChromeClient]. |
| @visibleForTesting |
| static WebChromeClientHostApiImpl api = WebChromeClientHostApiImpl(); |
| |
| /// Notify the host application that a file should be downloaded. |
| void onProgressChanged(WebView webView, int progress); |
| } |
| |
| /// Encompasses parameters to the [WebViewClient.requestLoading] method. |
| class WebResourceRequest { |
| /// Constructs a [WebResourceRequest]. |
| WebResourceRequest({ |
| required this.url, |
| required this.isForMainFrame, |
| required this.isRedirect, |
| required this.hasGesture, |
| required this.method, |
| required this.requestHeaders, |
| }); |
| |
| /// Gets the URL for which the resource request was made. |
| final String url; |
| |
| /// Gets whether the request was made in order to fetch the main frame's document. |
| final isForMainFrame; |
| |
| /// Gets whether the request was a result of a server-side redirect. |
| /// |
| /// Only supported on Android version >= 24. |
| final bool? isRedirect; |
| |
| /// Gets whether a gesture (such as a click) was associated with the request. |
| final bool hasGesture; |
| |
| /// Gets the method associated with the request, for example "GET". |
| final String method; |
| |
| /// Gets the headers associated with the request. |
| final Map<String, String> requestHeaders; |
| } |
| |
| /// Encapsulates information about errors occurred during loading of web resources. |
| /// |
| /// See [WebViewClient.onReceivedRequestError]. |
| class WebResourceError { |
| /// Constructs a [WebResourceError]. |
| WebResourceError({ |
| required this.errorCode, |
| required this.description, |
| }); |
| |
| /// The integer code of the error (e.g. [WebViewClient.errorAuthentication]. |
| final int errorCode; |
| |
| /// Describes the error. |
| final String description; |
| } |