Merge branch 'master' into feature/android-11
This commit is contained in:
commit
57557407a5
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -1,16 +1,32 @@
|
|||
## 5.0.0
|
||||
## 5.0.0-nullsafety.0
|
||||
|
||||
- Added support for Dart null-safety feature
|
||||
- Added Android Hybrid Composition support "Use PlatformViewLink widget for Android WebView" [#462](https://github.com/pichillilorenzo/flutter_inappwebview/pull/462) (thanks to [plateaukao](https://github.com/plateaukao) and [tneotia](https://github.com/tneotia))
|
||||
- Added `allowUniversalAccessFromFileURLs` and `allowFileAccessFromFileURLs` WebView options also for iOS (also thanks to [liranhao](https://github.com/liranhao))
|
||||
- Updated integration tests
|
||||
- Merge "Upgraded appcompat to 1.2.0-rc-02" [#465](https://github.com/pichillilorenzo/flutter_inappwebview/pull/465) (thanks to [andreidiaconu](https://github.com/andreidiaconu))
|
||||
- Merge "Added missing field 'headers' which returned by WebResourceResponse.toMap()" [#490](https://github.com/pichillilorenzo/flutter_inappwebview/pull/490) (thanks to [Doflatango](https://github.com/Doflatango))
|
||||
- Merge "Fix: added iOS fallback module import" [#466](https://github.com/pichillilorenzo/flutter_inappwebview/pull/466) (thanks to [Eddayy](https://github.com/Eddayy))
|
||||
- Merge "Fix NullPointerException after taking a photo by a camera app on Android" [#492](https://github.com/pichillilorenzo/flutter_inappwebview/pull/492) (thanks to [AAkira](https://github.com/AAkira))
|
||||
- Merge "iOS CookieManager.getCookies - Check that URL has suffix of cookie do…" [#658](https://github.com/pichillilorenzo/flutter_inappwebview/pull/658) (thanks to [arneke](https://github.com/arneke))
|
||||
- Merge "Add NTLM Auth" [#634](https://github.com/pichillilorenzo/flutter_inappwebview/pull/634) (thanks to [albatrosify](https://github.com/albatrosify))
|
||||
- Merge "iOS ChromeSafariBrowserManager - Fixing unnecessary casting of rootViewController to FlutterViewController" [#567](https://github.com/pichillilorenzo/flutter_inappwebview/pull/567) (thanks to [gunantosteven](https://github.com/gunantosteven))
|
||||
- Merge "Fix _channel.invokeMethod name for injectCSSFileFromUrl method" [#645](https://github.com/pichillilorenzo/flutter_inappwebview/pull/645) (thanks to [omralcrt](https://github.com/omralcrt))
|
||||
- Merge "Add android media intents on wildcard input accept" [#620](https://github.com/pichillilorenzo/flutter_inappwebview/pull/620) (thanks to [cbodin](https://github.com/cbodin))
|
||||
- Fixed missing properties initialization when using InAppWebViewController.fromInAppBrowser
|
||||
- Fixed "Issue in Flutter web: 'Unsupported operation: Platform._operatingSystem'" [#507](https://github.com/pichillilorenzo/flutter_inappwebview/issues/507)
|
||||
- Fixed "window.flutter_inappwebview.callHandler is not a function" [#218](https://github.com/pichillilorenzo/flutter_inappwebview/issues/218)
|
||||
- Fixed "Android ContentBlocker - java.lang.NullPointerException ContentBlockerTrigger resource type" [#506](https://github.com/pichillilorenzo/flutter_inappwebview/issues/506)
|
||||
- Fixed "Android CookieManager throws error caused by websites that are sending back illegal/invalid cookies." [#476](https://github.com/pichillilorenzo/flutter_inappwebview/issues/476)
|
||||
- Fixed missing `clearHistory` webview method implementation on Android
|
||||
- Fixed iOS crash when using CookieManager getCookies for an URL and the host URL is `null`
|
||||
- Fixed "IOS does not support allowUniversalAccessFromFileURLs" [#654](https://github.com/pichillilorenzo/flutter_inappwebview/issues/654)
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
- Minimum Flutter version required is `1.22.0` and Dart SDK `>=2.12.0-0 <3.0.0`
|
||||
- Removed `debuggingEnabled` WebView option; on Android you should use now the `AndroidInAppWebViewController.setWebContentsDebuggingEnabled(bool debuggingEnabled)` static method; on iOS, debugging is always enabled
|
||||
- `allowUniversalAccessFromFileURLs` and `allowFileAccessFromFileURLs` WebView options moved from Android-specific options to cross-platform options.
|
||||
|
||||
## 4.0.0+4
|
||||
|
||||
|
|
439
README.md
439
README.md
|
@ -22,8 +22,8 @@ A Flutter plugin that allows you to add an inline webview, to use an headless we
|
|||
|
||||
## Requirements
|
||||
|
||||
- Dart sdk: ">=2.7.0 <3.0.0"
|
||||
- Flutter: ">=1.12.13+hotfix.5"
|
||||
- Dart sdk: ">=2.12.0-0 <3.0.0"
|
||||
- Flutter: ">=1.22.0"
|
||||
- Android: `minSdkVersion 17` and add support for `androidx` (see [AndroidX Migration](https://flutter.dev/docs/development/androidx-migration) to migrate an existing app)
|
||||
- iOS: `--ios-language swift`, Xcode version `>= 11`
|
||||
|
||||
|
@ -75,7 +75,21 @@ or **Android API 19+** if you enable the `useHybridComposition` Android-specific
|
|||
- Check the official [Network security configuration - "Opt out of cleartext traffic"](https://developer.android.com/training/articles/security-config#CleartextTrafficPermitted) section.
|
||||
- Also, check this StackOverflow issue answer: [Cleartext HTTP traffic not permitted](https://stackoverflow.com/a/50834600/4637638).
|
||||
|
||||
If you want to use the `ChromeSafariBrowser` on Android 11+ you need to specify your app querying for `android.support.customtabs.action.CustomTabsService` in your `AndroidManifest.xml` you can read more about it here: https://developers.google.com/web/android/custom-tabs/best-practices#applications_targeting_android_11_api_level_30_or_above
|
||||
#### Debugging Android WebViews
|
||||
On Android, in order to enable/disable debugging WebViews using `chrome://inspect` on Chrome, you should use the `AndroidInAppWebViewController.setWebContentsDebuggingEnabled(bool debuggingEnabled)` static method.
|
||||
|
||||
For example, you could call it inside the main function:
|
||||
```dart
|
||||
Future main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
|
||||
runApp(new MyApp());
|
||||
}
|
||||
```
|
||||
|
||||
### IMPORTANT Note for iOS
|
||||
|
||||
|
@ -139,6 +153,9 @@ Other useful `Info.plist` properties are:
|
|||
* `NSAllowsLocalNetworking`: A Boolean value indicating whether to allow loading of local resources ([Official wiki](https://developer.apple.com/documentation/bundleresources/information_property_list/nsapptransportsecurity/nsallowslocalnetworking));
|
||||
* `NSAllowsArbitraryLoadsInWebContent`: A Boolean value indicating whether all App Transport Security restrictions are disabled for requests made from web views ([Official wiki](https://developer.apple.com/documentation/bundleresources/information_property_list/nsapptransportsecurity/nsallowsarbitraryloadsinwebcontent)).
|
||||
|
||||
#### Debugging iOS WebViews
|
||||
On iOS, debugging WebViews on Safari through developer tools is always enabled. There isn't a way to enable or disable it.
|
||||
|
||||
### How to enable the usage of camera for HTML inputs such as `<input type="file" accept="image/*" capture>`
|
||||
|
||||
In order to be able to use camera, for example, for taking images through `<input type="file" accept="image/*" capture>` HTML tag, you need to ask camera permission.
|
||||
|
@ -184,11 +201,11 @@ First, add `flutter_inappwebview` as a [dependency in your pubspec.yaml file](ht
|
|||
## Usage
|
||||
|
||||
Classes:
|
||||
- [InAppWebView](#inappwebview-class): Flutter Widget for adding an **inline native WebView** integrated into the flutter widget tree. To use `InAppWebView` class on iOS you need to opt-in for the embedded views preview by adding a boolean property to the app's `Info.plist` file, with the key `io.flutter.embedded_views_preview` and the value `YES`. Also, note that on Android it requires **Android API 20+** (see [AndroidView](https://api.flutter.dev/flutter/widgets/AndroidView-class.html)) or **Android API 19+** if you enable the `useHybridComposition` Android-specific option.
|
||||
- [InAppWebView](#inappwebview-class): Flutter Widget for adding an **inline native WebView** integrated into the flutter widget tree. Note that on Android it requires **Android API 20+** (see [AndroidView](https://api.flutter.dev/flutter/widgets/AndroidView-class.html)) or **Android API 19+** if you enable the `useHybridComposition` Android-specific option.
|
||||
- [ContextMenu](#contextmenu-class): This class represents the WebView context menu.
|
||||
- [HeadlessInAppWebView](#headlessinappwebview-class): 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.
|
||||
- [InAppBrowser](#inappbrowser-class): In-App Browser using native WebView.
|
||||
- [ChromeSafariBrowser](#chromesafaribrowser-class): In-App Browser using [Chrome Custom Tabs](https://developer.android.com/reference/android/support/customtabs/package-summary) on Android / [SFSafariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) on iOS.
|
||||
- [ChromeSafariBrowser](#chromesafaribrowser-class): In-App Browser using [Chrome Custom Tabs](https://developer.android.com/reference/android/support/customtabs/package-summary) on Android / [SFSafariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) on iOS. If you want to use the `ChromeSafariBrowser` on Android 11+ you need to specify your app querying for `android.support.customtabs.action.CustomTabsService` in your `AndroidManifest.xml` (you can read more about it here: https://developers.google.com/web/android/custom-tabs/best-practices#applications_targeting_android_11_api_level_30_or_above).
|
||||
- [InAppLocalhostServer](#inapplocalhostserver-class): This class allows you to create a simple server on `http://localhost:[port]/`. The default `port` value is `8080`.
|
||||
- [CookieManager](#cookiemanager-class): This class implements a singleton object (shared instance) which manages the cookies used by WebView instances. **NOTE for iOS**: available from iOS 11.0+.
|
||||
- [HttpAuthCredentialDatabase](#httpauthcredentialdatabase-class): This class implements a singleton object (shared instance) which manages the shared HTTP auth credentials cache.
|
||||
|
@ -234,20 +251,22 @@ The plugin relies on Flutter's mechanism (in developers preview) for embedding A
|
|||
Known issues are tagged with the [platform-views](https://github.com/flutter/flutter/labels/a%3A%20platform-views) label in the [Flutter official repo](https://github.com/flutter/flutter).
|
||||
Keyboard support within webviews is also experimental.
|
||||
|
||||
To use `InAppWebView` class on iOS you need to opt-in for the embedded views preview by adding a boolean property to the app's `Info.plist` file, with the key `io.flutter.embedded_views_preview` and the value `YES`.
|
||||
|
||||
Also, note that on Android it requires **Android API 20+** (see [AndroidView](https://api.flutter.dev/flutter/widgets/AndroidView-class.html))
|
||||
Note that on Android it requires **Android API 20+** (see [AndroidView](https://api.flutter.dev/flutter/widgets/AndroidView-class.html))
|
||||
or **Android API 19+** if you enable the `useHybridComposition` Android-specific option.
|
||||
|
||||
Use `InAppWebViewController` to control the WebView instance.
|
||||
Example:
|
||||
```dart
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
Future main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
if (Platform.isAndroid) {
|
||||
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
runApp(new MyApp());
|
||||
}
|
||||
|
||||
|
@ -258,7 +277,7 @@ class MyApp extends StatefulWidget {
|
|||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
|
||||
InAppWebViewController webView;
|
||||
InAppWebViewController? webView;
|
||||
String url = "";
|
||||
double progress = 0;
|
||||
|
||||
|
@ -280,81 +299,75 @@ class _MyAppState extends State<MyApp> {
|
|||
title: const Text('InAppWebView Example'),
|
||||
),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.all(20.0),
|
||||
child: Text(
|
||||
"CURRENT URL\n${(url.length > 50) ? url.substring(0, 50) + "..." : url}"),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.all(10.0),
|
||||
child: progress < 1.0
|
||||
? LinearProgressIndicator(value: progress)
|
||||
: Container()),
|
||||
Expanded(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(10.0),
|
||||
decoration:
|
||||
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
|
||||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
)
|
||||
child: Column(children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.all(20.0),
|
||||
child: Text(
|
||||
"CURRENT URL\n${(url.length > 50) ? url.substring(0, 50) + "..." : url}"),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.all(10.0),
|
||||
child: progress < 1.0
|
||||
? LinearProgressIndicator(value: progress)
|
||||
: Container()),
|
||||
Expanded(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(10.0),
|
||||
decoration:
|
||||
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
|
||||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (controller, url) {
|
||||
setState(() {
|
||||
this.url = url ?? '';
|
||||
});
|
||||
},
|
||||
onLoadStop: (controller, url) async {
|
||||
setState(() {
|
||||
this.url = url ?? '';
|
||||
});
|
||||
},
|
||||
onProgressChanged: (controller, progress) {
|
||||
setState(() {
|
||||
this.progress = progress / 100;
|
||||
});
|
||||
},
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
setState(() {
|
||||
this.url = url;
|
||||
});
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) async {
|
||||
setState(() {
|
||||
this.url = url;
|
||||
});
|
||||
},
|
||||
onProgressChanged: (InAppWebViewController controller, int progress) {
|
||||
setState(() {
|
||||
this.progress = progress / 100;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
ButtonBar(
|
||||
alignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
RaisedButton(
|
||||
child: Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
if (webView != null) {
|
||||
webView.goBack();
|
||||
}
|
||||
},
|
||||
),
|
||||
RaisedButton(
|
||||
child: Icon(Icons.arrow_forward),
|
||||
onPressed: () {
|
||||
if (webView != null) {
|
||||
webView.goForward();
|
||||
}
|
||||
},
|
||||
),
|
||||
RaisedButton(
|
||||
child: Icon(Icons.refresh),
|
||||
onPressed: () {
|
||||
if (webView != null) {
|
||||
webView.reload();
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
])),
|
||||
ButtonBar(
|
||||
alignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
RaisedButton(
|
||||
child: Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
webView?.goBack();
|
||||
},
|
||||
),
|
||||
RaisedButton(
|
||||
child: Icon(Icons.arrow_forward),
|
||||
onPressed: () {
|
||||
webView?.goForward();
|
||||
},
|
||||
),
|
||||
RaisedButton(
|
||||
child: Icon(Icons.refresh),
|
||||
onPressed: () {
|
||||
webView?.reload();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
])),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -447,7 +460,7 @@ Methods available:
|
|||
|
||||
##### `InAppWebViewController` Android-specific methods
|
||||
|
||||
Android-specific methods can be called using the `InAppWebViewController.android` attribute.
|
||||
Android-specific methods can be called using the `InAppWebViewController.android` attribute. Static methods can be called using the `AndroidInAppWebViewController` class directly.
|
||||
|
||||
* `startSafeBrowsing`: Starts Safe Browsing initialization.
|
||||
* `clearSslPreferences`: Clears the SSL preferences table stored in response to proceeding with SSL certificate errors.
|
||||
|
@ -464,10 +477,11 @@ Android-specific methods can be called using the `InAppWebViewController.android
|
|||
* `static getSafeBrowsingPrivacyPolicyUrl`: Returns a URL pointing to the privacy policy for Safe Browsing reporting. This value will never be `null`.
|
||||
* `static setSafeBrowsingWhitelist({@required List<String> hosts})`: Sets the list of hosts (domain names/IP addresses) that are exempt from SafeBrowsing checks. The list is global for all the WebViews.
|
||||
* `static getCurrentWebViewPackage`: Gets the current Android WebView package info.
|
||||
* `static setWebContentsDebuggingEnabled(bool debuggingEnabled)`: Enables debugging of web contents (HTML / CSS / JavaScript) loaded into any WebViews of this application. Debugging is disabled by default.
|
||||
|
||||
##### `InAppWebViewController` iOS-specific methods
|
||||
|
||||
iOS-specific methods can be called using the `InAppWebViewController.ios` attribute.
|
||||
iOS-specific methods can be called using the `InAppWebViewController.ios` attribute. Static methods can be called using the `IOSInAppWebViewController` class directly.
|
||||
|
||||
* `hasOnlySecureContent`: A Boolean value indicating whether all resources on the page have been loaded over securely encrypted connections.
|
||||
* `reloadFromOrigin`: Reloads the current page, performing end-to-end revalidation using cache-validating conditionals if possible.
|
||||
|
@ -521,112 +535,111 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
|
|||
|
||||
##### `InAppWebView` Cross-platform options
|
||||
|
||||
* `useShouldOverrideUrlLoading`: Set to `true` to be able to listen at the `shouldOverrideUrlLoading` event. The default value is `false`.
|
||||
* `useOnLoadResource`: Set to `true` to be able to listen at the `onLoadResource` event. The default value is `false`.
|
||||
* `useOnDownloadStart`: Set to `true` to be able to listen at the `onDownloadStart` event. The default value is `false`.
|
||||
* `useShouldInterceptAjaxRequest`: Set to `true` to be able to listen at the `shouldInterceptAjaxRequest` event. The default value is `false`.
|
||||
* `useShouldInterceptFetchRequest`: Set to `true` to be able to listen at the `shouldInterceptFetchRequest` event. The default value is `false`.
|
||||
* `clearCache`: Set to `true` to have all the browser's cache cleared before the new WebView is opened. The default value is `false`.
|
||||
* `userAgent`: Sets the user-agent for the WebView.
|
||||
* `allowFileAccessFromFileURLs`: Sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from other file scheme URLs. The default value is `false`.
|
||||
* `allowUniversalAccessFromFileURLs`: Sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from any origin. The default value is `false`.
|
||||
* `applicationNameForUserAgent`: Append to the existing user-agent. Setting userAgent will override this.
|
||||
* `javaScriptEnabled`: Set to `true` to enable JavaScript. The default value is `true`.
|
||||
* `debuggingEnabled`: Enables debugging of web contents (HTML / CSS / JavaScript) loaded into any WebViews of this application.
|
||||
* `cacheEnabled`: Sets whether WebView should use browser caching. The default value is `true`.
|
||||
* `clearCache`: Set to `true` to have all the browser's cache cleared before the new WebView is opened. The default value is `false`.
|
||||
* `contentBlockers`: List of `ContentBlocker` that are a set of rules used to block content in the browser window.
|
||||
* `disableContextMenu`: Set to `true` to disable context menu. The default value is `false`.
|
||||
* `disableHorizontalScroll`: Set to `true` to disable horizontal scroll. The default value is `false`.
|
||||
* `disableVerticalScroll`: Set to `true` to disable vertical scroll. The default value is `false`.
|
||||
* `horizontalScrollBarEnabled`: Define whether the horizontal scrollbar should be drawn or not. The default value is `true`.
|
||||
* `incognito`: Set to `true` to open a browser window with incognito mode. The default value is `false`.
|
||||
* `javaScriptCanOpenWindowsAutomatically`: Set to `true` to allow JavaScript open windows without user interaction. The default value is `false`.
|
||||
* `javaScriptEnabled`: Set to `true` to enable JavaScript. The default value is `true`.
|
||||
* `mediaPlaybackRequiresUserGesture`: Set to `true` to prevent HTML5 audio or video from autoplaying. The default value is `true`.
|
||||
* `minimumFontSize`: Sets the minimum font size. The default value is `8` for Android, `0` for iOS.
|
||||
* `verticalScrollBarEnabled`: Define whether the vertical scrollbar should be drawn or not. The default value is `true`.
|
||||
* `horizontalScrollBarEnabled`: Define whether the horizontal scrollbar should be drawn or not. The default value is `true`.
|
||||
* `resourceCustomSchemes`: List of custom schemes that the WebView must handle. Use the `onLoadResourceCustomScheme` event to intercept resource requests with custom scheme.
|
||||
* `contentBlockers`: List of `ContentBlocker` that are a set of rules used to block content in the browser window.
|
||||
* `preferredContentMode`: Sets the content mode that the WebView needs to use when loading and rendering a webpage. The default value is `InAppWebViewUserPreferredContentMode.RECOMMENDED`.
|
||||
* `incognito`: Set to `true` to open a browser window with incognito mode. The default value is `false`.
|
||||
* `cacheEnabled`: Sets whether WebView should use browser caching. The default value is `true`.
|
||||
* `transparentBackground`: 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`.
|
||||
* `disableVerticalScroll`: Set to `true` to disable vertical scroll. The default value is `false`.
|
||||
* `disableHorizontalScroll`: Set to `true` to disable horizontal scroll. The default value is `false`.
|
||||
* `disableContextMenu`: Set to `true` to disable context menu. The default value is `false`.
|
||||
* `resourceCustomSchemes`: List of custom schemes that the WebView must handle. Use the `onLoadResourceCustomScheme` event to intercept resource requests with custom scheme.
|
||||
* `supportZoom`: Set to `false` if the WebView should not support zooming using its on-screen zoom controls and gestures. The default value is `true`.
|
||||
* `transparentBackground`: 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`.
|
||||
* `useOnDownloadStart`: Set to `true` to be able to listen at the `onDownloadStart` event. The default value is `false`.
|
||||
* `useOnLoadResource`: Set to `true` to be able to listen at the `onLoadResource` event. The default value is `false`.
|
||||
* `useShouldInterceptAjaxRequest`: Set to `true` to be able to listen at the `shouldInterceptAjaxRequest` event. The default value is `false`.
|
||||
* `useShouldInterceptFetchRequest`: Set to `true` to be able to listen at the `shouldInterceptFetchRequest` event. The default value is `false`.
|
||||
* `useShouldOverrideUrlLoading`: Set to `true` to be able to listen at the `shouldOverrideUrlLoading` event. The default value is `false`.
|
||||
* `userAgent`: Sets the user-agent for the WebView.
|
||||
* `verticalScrollBarEnabled`: Define whether the vertical scrollbar should be drawn or not. The default value is `true`.
|
||||
|
||||
##### `InAppWebView` Android-specific options
|
||||
|
||||
* `useHybridComposition`: Set to `true` to use Flutter's new Hybrid Composition rendering method, which fixes all issues [here](https://github.com/flutter/flutter/issues/61133). The default value is `false`. Note that this option requires Flutter v1.20+ and should only be used on Android 10+ for release apps, as animations will drop frames on < Android 10 (see [Hybrid-Composition#performance](https://github.com/flutter/flutter/wiki/Hybrid-Composition#performance)).
|
||||
* `useShouldInterceptRequest`: Set to `true` to be able to listen at the `androidShouldInterceptRequest` event. The default value is `false`.
|
||||
* `useOnRenderProcessGone`: Set to `true` to be able to listen at the `androidOnRenderProcessGone` event. The default value is `false`.
|
||||
* `textZoom`: Sets the text zoom of the page in percent. The default value is `100`.
|
||||
* `clearSessionCache`: Set to `true` to have the session cookie cache cleared before the new window is opened.
|
||||
* `builtInZoomControls`: Set to `true` if the WebView should use its built-in zoom mechanisms. The default value is `true`.
|
||||
* `displayZoomControls`: Set to `true` if the WebView should display on-screen zoom controls when using the built-in zoom mechanisms. The default value is `false`.
|
||||
* `databaseEnabled`: Set to `true` if you want the database storage API is enabled. The default value is `true`.
|
||||
* `domStorageEnabled`: Set to `true` if you want the DOM storage API is enabled. The default value is `true`.
|
||||
* `useWideViewPort`: Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport.
|
||||
* `safeBrowsingEnabled`: Sets whether Safe Browsing is enabled. Safe Browsing allows WebView to protect against malware and phishing attacks by verifying the links.
|
||||
* `mixedContentMode`: Configures the WebView's behavior when a secure origin attempts to load a resource from an insecure origin.
|
||||
* `allowContentAccess`: 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`.
|
||||
* `allowFileAccess`: Enables or disables file access within WebView. Note that this enables or disables file system access only.
|
||||
* `allowFileAccessFromFileURLs`: Sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from other file scheme URLs.
|
||||
* `allowUniversalAccessFromFileURLs`: Sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from any origin.
|
||||
* `appCachePath`: 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.
|
||||
* `blockNetworkImage`: 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`.
|
||||
* `blockNetworkLoads`: Sets whether the WebView should not load resources from the network. The default value is `false`.
|
||||
* `builtInZoomControls`: Set to `true` if the WebView should use its built-in zoom mechanisms. The default value is `true`.
|
||||
* `cacheMode`: 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.
|
||||
* `clearSessionCache`: Set to `true` to have the session cookie cache cleared before the new window is opened.
|
||||
* `cursiveFontFamily`: Sets the cursive font family name. The default value is `"cursive"`.
|
||||
* `databaseEnabled`: Set to `true` if you want the database storage API is enabled. The default value is `true`.
|
||||
* `defaultFixedFontSize`: Sets the default fixed font size. The default value is `16`.
|
||||
* `defaultFontSize`: Sets the default font size. The default value is `16`.
|
||||
* `defaultTextEncodingName`: Sets the default text encoding name to use when decoding html pages. The default value is `"UTF-8"`.
|
||||
* `disableDefaultErrorPage`: Sets whether the default Android error page should be disabled. The default value is `false`.
|
||||
* `disabledActionModeMenuItems`: Disables the action mode menu items according to menuItems flag.
|
||||
* `displayZoomControls`: Set to `true` if the WebView should display on-screen zoom controls when using the built-in zoom mechanisms. The default value is `false`.
|
||||
* `domStorageEnabled`: Set to `true` if you want the DOM storage API is enabled. The default value is `true`.
|
||||
* `fantasyFontFamily`: Sets the fantasy font family name. The default value is `"fantasy"`.
|
||||
* `fixedFontFamily`: Sets the fixed font family name. The default value is `"monospace"`.
|
||||
* `forceDark`: Set the force dark mode for this WebView. The default value is `AndroidInAppWebViewForceDark.FORCE_DARK_OFF`.
|
||||
* `geolocationEnabled`: Sets whether Geolocation API is enabled. The default value is `true`.
|
||||
* `hardwareAcceleration`: Boolean value to enable Hardware Acceleration in the WebView.
|
||||
* `initialScale`: Sets the initial scale for this WebView. 0 means default. The behavior for the default scale depends on the state of `useWideViewPort` and `loadWithOverviewMode`.
|
||||
* `layoutAlgorithm`: Sets the underlying layout algorithm. This will cause a re-layout of the WebView.
|
||||
* `loadWithOverviewMode`: Sets whether the WebView loads pages in overview mode, that is, zooms out the content to fit on screen by width.
|
||||
* `loadsImagesAutomatically`: 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.
|
||||
* `minimumLogicalFontSize`: Sets the minimum logical font size. The default is `8`.
|
||||
* `initialScale`: Sets the initial scale for this WebView. 0 means default. The behavior for the default scale depends on the state of `useWideViewPort` and `loadWithOverviewMode`.
|
||||
* `mixedContentMode`: Configures the WebView's behavior when a secure origin attempts to load a resource from an insecure origin.
|
||||
* `needInitialFocus`: Tells the WebView whether it needs to set a node. The default value is `true`.
|
||||
* `offscreenPreRaster`: Sets whether this WebView should raster tiles when it is offscreen but attached to a window.
|
||||
* `overScrollMode`: Sets the WebView's over-scroll mode. The default value is `AndroidOverScrollMode.OVER_SCROLL_IF_CONTENT_SCROLLS`.
|
||||
* `regexToCancelSubFramesLoading`: Regular expression used by `shouldOverrideUrlLoading` event to cancel navigation 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.
|
||||
* `rendererPriorityPolicy`: Set the renderer priority policy for this WebView.
|
||||
* `safeBrowsingEnabled`: Sets whether Safe Browsing is enabled. Safe Browsing allows WebView to protect against malware and phishing attacks by verifying the links.
|
||||
* `sansSerifFontFamily`: Sets the sans-serif font family name. The default value is `"sans-serif"`.
|
||||
* `saveFormData`: Sets whether the WebView should save form data. In Android O, the platform has implemented a fully functional Autofill feature to store form data.
|
||||
* `scrollBarDefaultDelayBeforeFade`: Defines the delay in milliseconds that a scrollbar waits before fade out.
|
||||
* `scrollBarFadeDuration`: Define the scrollbar fade duration in milliseconds.
|
||||
* `scrollBarStyle`: Specify the style of the scrollbars. The scrollbars can be overlaid or inset. The default value is `AndroidScrollBarStyle.SCROLLBARS_INSIDE_OVERLAY`.
|
||||
* `scrollbarFadingEnabled`: Define whether scrollbars will fade when the view is not scrolling. The default value is `true`.
|
||||
* `serifFontFamily`: Sets the serif font family name. The default value is `"sans-serif"`.
|
||||
* `standardFontFamily`: Sets the standard font family name. The default value is `"sans-serif"`.
|
||||
* `saveFormData`: Sets whether the WebView should save form data. In Android O, the platform has implemented a fully functional Autofill feature to store form data.
|
||||
* `thirdPartyCookiesEnabled`: Boolean value to enable third party cookies in the WebView.
|
||||
* `hardwareAcceleration`: Boolean value to enable Hardware Acceleration in the WebView.
|
||||
* `supportMultipleWindows`: Sets whether the WebView whether supports multiple windows.
|
||||
* `regexToCancelSubFramesLoading`: Regular expression used by `shouldOverrideUrlLoading` event to cancel navigation 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.
|
||||
* `overScrollMode`: Sets the WebView's over-scroll mode. The default value is `AndroidOverScrollMode.OVER_SCROLL_IF_CONTENT_SCROLLS`.
|
||||
* `scrollBarStyle`: Specify the style of the scrollbars. The scrollbars can be overlaid or inset. The default value is `AndroidScrollBarStyle.SCROLLBARS_INSIDE_OVERLAY`.
|
||||
* `textZoom`: Sets the text zoom of the page in percent. The default value is `100`.
|
||||
* `thirdPartyCookiesEnabled`: Boolean value to enable third party cookies in the WebView.
|
||||
* `useHybridComposition`: Set to `true` to use Flutter's new Hybrid Composition rendering method, which fixes all issues [here](https://github.com/flutter/flutter/issues/61133). The default value is `false`. Note that this option requires Flutter v1.20+ and should only be used on Android 10+ for release apps, as animations will drop frames on < Android 10 (see [Hybrid-Composition#performance](https://github.com/flutter/flutter/wiki/Hybrid-Composition#performance)).
|
||||
* `useOnRenderProcessGone`: Set to `true` to be able to listen at the `androidOnRenderProcessGone` event. The default value is `false`.
|
||||
* `useShouldInterceptRequest`: Set to `true` to be able to listen at the `androidShouldInterceptRequest` event. The default value is `false`.
|
||||
* `useWideViewPort`: Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport.
|
||||
* `verticalScrollbarPosition`: Set the position of the vertical scroll bar. The default value is `AndroidVerticalScrollbarPosition.SCROLLBAR_POSITION_DEFAULT`.
|
||||
* `scrollBarDefaultDelayBeforeFade`: Defines the delay in milliseconds that a scrollbar waits before fade out.
|
||||
* `scrollbarFadingEnabled`: Define whether scrollbars will fade when the view is not scrolling. The default value is `true`.
|
||||
* `scrollBarFadeDuration`: Define the scrollbar fade duration in milliseconds.
|
||||
* `rendererPriorityPolicy`: Set the renderer priority policy for this WebView.
|
||||
* `disableDefaultErrorPage`: Sets whether the default Android error page should be disabled. The default value is `false`.
|
||||
|
||||
##### `InAppWebView` iOS-specific options
|
||||
|
||||
* `disallowOverScroll`: 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`.
|
||||
* `enableViewportScale`: Set to `true` to allow a viewport meta tag to either disable or restrict the range of user scaling. The default value is `false`.
|
||||
* `suppressesIncrementalRendering`: Set to `true` if you want the WebView suppresses content rendering until it is fully loaded into memory. The default value is `false`.
|
||||
* `accessibilityIgnoresInvertColors`: A Boolean value indicating whether the view ignores an accessibility request to invert its colors. The default value is `false`.
|
||||
* `allowsAirPlayForMediaPlayback`: Set to `true` to allow AirPlay. The default value is `true`.
|
||||
* `allowsBackForwardNavigationGestures`: Set to `true` to allow the horizontal swipe gestures trigger back-forward list navigations. The default value is `true`.
|
||||
* `allowsLinkPreview`: Set to `true` to allow that pressing on a link displays a preview of the destination for the link. The default value is `true`.
|
||||
* `ignoresViewportScaleLimits`: Set to `true` if you want that the WebView should always allow scaling of the webpage, regardless of the author's intent.
|
||||
* `allowsInlineMediaPlayback`: Set to `true` to allow HTML5 media playback to appear inline within the screen layout, using browser-supplied controls rather than native controls.
|
||||
* `allowsLinkPreview`: Set to `true` to allow that pressing on a link displays a preview of the destination for the link. The default value is `true`.
|
||||
* `allowsPictureInPictureMediaPlayback`: Set to `true` to allow HTML5 videos play picture-in-picture. The default value is `true`.
|
||||
* `isFraudulentWebsiteWarningEnabled`: A Boolean value indicating whether warnings should be shown for suspected fraudulent content such as phishing or malware.
|
||||
* `selectionGranularity`: The level of granularity with which the user can interactively select content in the web view.
|
||||
* `dataDetectorTypes`: Specifying a dataDetectoryTypes value adds interactivity to web content that matches the value.
|
||||
* `sharedCookiesEnabled`: Set `true` if shared cookies from `HTTPCookieStorage.shared` should used for every load request in the WebView.
|
||||
* `automaticallyAdjustsScrollIndicatorInsets`: Configures whether the scroll indicator insets are automatically adjusted by the system. The default value is `false`.
|
||||
* `accessibilityIgnoresInvertColors`: A Boolean value indicating whether the view ignores an accessibility request to invert its colors. The default value is `false`.
|
||||
* `decelerationRate`: A `IOSUIScrollViewDecelerationRate` value that determines the rate of deceleration after the user lifts their finger. The default value is `IOSUIScrollViewDecelerationRate.NORMAL`.
|
||||
* `alwaysBounceVertical`: A Boolean value that determines whether bouncing always occurs when vertical scrolling reaches the end of the content. The default value is `false`.
|
||||
* `alwaysBounceHorizontal`: A Boolean value that determines whether bouncing always occurs when horizontal scrolling reaches the end of the content view. The default value is `false`.
|
||||
* `scrollsToTop`: A Boolean value that controls whether the scroll-to-top gesture is enabled. The default value is `true`.
|
||||
* `alwaysBounceVertical`: A Boolean value that determines whether bouncing always occurs when vertical scrolling reaches the end of the content. The default value is `false`.
|
||||
* `automaticallyAdjustsScrollIndicatorInsets`: Configures whether the scroll indicator insets are automatically adjusted by the system. The default value is `false`.
|
||||
* `contentInsetAdjustmentBehavior`: Configures how safe area insets are added to the adjusted content inset. The default value is `IOSUIScrollViewContentInsetAdjustmentBehavior.NEVER`.
|
||||
* `dataDetectorTypes`: Specifying a dataDetectoryTypes value adds interactivity to web content that matches the value.
|
||||
* `decelerationRate`: A `IOSUIScrollViewDecelerationRate` value that determines the rate of deceleration after the user lifts their finger. The default value is `IOSUIScrollViewDecelerationRate.NORMAL`.
|
||||
* `disallowOverScroll`: 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`.
|
||||
* `enableViewportScale`: Set to `true` to allow a viewport meta tag to either disable or restrict the range of user scaling. The default value is `false`.
|
||||
* `ignoresViewportScaleLimits`: Set to `true` if you want that the WebView should always allow scaling of the webpage, regardless of the author's intent.
|
||||
* `isFraudulentWebsiteWarningEnabled`: A Boolean value indicating whether warnings should be shown for suspected fraudulent content such as phishing or malware.
|
||||
* `isPagingEnabled`: A Boolean value that determines whether paging is enabled for the scroll view. The default value is `false`.
|
||||
* `maximumZoomScale`: A floating-point value that specifies the maximum scale factor that can be applied to the scroll view's content. The default value is `1.0`.
|
||||
* `minimumZoomScale`: A floating-point value that specifies the minimum scale factor that can be applied to the scroll view's content. The default value is `1.0`.
|
||||
* `contentInsetAdjustmentBehavior`: Configures how safe area insets are added to the adjusted content inset. The default value is `IOSUIScrollViewContentInsetAdjustmentBehavior.NEVER`.
|
||||
* `scrollsToTop`: A Boolean value that controls whether the scroll-to-top gesture is enabled. The default value is `true`.
|
||||
* `selectionGranularity`: The level of granularity with which the user can interactively select content in the web view.
|
||||
* `sharedCookiesEnabled`: Set `true` if shared cookies from `HTTPCookieStorage.shared` should used for every load request in the WebView.
|
||||
* `suppressesIncrementalRendering`: Set to `true` if you want the WebView suppresses content rendering until it is fully loaded into memory. The default value is `false`.
|
||||
|
||||
#### `InAppWebView` Events
|
||||
|
||||
|
@ -701,6 +714,9 @@ import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
|||
|
||||
Future main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
if (Platform.isAndroid) {
|
||||
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
runApp(new MyApp());
|
||||
}
|
||||
|
||||
|
@ -711,8 +727,8 @@ class MyApp extends StatefulWidget {
|
|||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
|
||||
InAppWebViewController webView;
|
||||
ContextMenu contextMenu;
|
||||
InAppWebViewController? webView;
|
||||
ContextMenu? contextMenu;
|
||||
String url = "";
|
||||
double progress = 0;
|
||||
|
||||
|
@ -729,7 +745,7 @@ class _MyAppState extends State<MyApp> {
|
|||
onCreateContextMenu: (hitTestResult) async {
|
||||
print("onCreateContextMenu");
|
||||
print(hitTestResult.extra);
|
||||
print(await webView.getSelectedText());
|
||||
print(await webView?.getSelectedText());
|
||||
},
|
||||
onHideContextMenu: () {
|
||||
print("onHideContextMenu");
|
||||
|
@ -777,23 +793,23 @@ class _MyAppState extends State<MyApp> {
|
|||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
onLoadStart: (controller, url) {
|
||||
setState(() {
|
||||
this.url = url;
|
||||
this.url = url ?? '';
|
||||
});
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) async {
|
||||
onLoadStop: (controller, url) async {
|
||||
setState(() {
|
||||
this.url = url;
|
||||
this.url = url ?? '';
|
||||
});
|
||||
},
|
||||
onProgressChanged: (InAppWebViewController controller, int progress) {
|
||||
onProgressChanged: (controller, progress) {
|
||||
setState(() {
|
||||
this.progress = progress / 100;
|
||||
});
|
||||
|
@ -807,25 +823,19 @@ class _MyAppState extends State<MyApp> {
|
|||
RaisedButton(
|
||||
child: Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
if (webView != null) {
|
||||
webView.goBack();
|
||||
}
|
||||
webView?.goBack();
|
||||
},
|
||||
),
|
||||
RaisedButton(
|
||||
child: Icon(Icons.arrow_forward),
|
||||
onPressed: () {
|
||||
if (webView != null) {
|
||||
webView.goForward();
|
||||
}
|
||||
webView?.goForward();
|
||||
},
|
||||
),
|
||||
RaisedButton(
|
||||
child: Icon(Icons.refresh),
|
||||
onPressed: () {
|
||||
if (webView != null) {
|
||||
webView.reload();
|
||||
}
|
||||
webView?.reload();
|
||||
},
|
||||
),
|
||||
],
|
||||
|
@ -858,12 +868,16 @@ As `InAppWebView`, it has the same options and events. Use `InAppWebViewControll
|
|||
Example:
|
||||
```dart
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
Future main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
if (Platform.isAndroid) {
|
||||
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
runApp(new MyApp());
|
||||
}
|
||||
|
||||
|
@ -874,7 +888,7 @@ class MyApp extends StatefulWidget {
|
|||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
|
||||
HeadlessInAppWebView headlessWebView;
|
||||
HeadlessInAppWebView? headlessWebView;
|
||||
String url = "";
|
||||
|
||||
@override
|
||||
|
@ -885,7 +899,7 @@ class _MyAppState extends State<MyApp> {
|
|||
initialUrl: "https://flutter.dev/",
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
|
||||
),
|
||||
),
|
||||
onWebViewCreated: (controller) {
|
||||
|
@ -897,19 +911,19 @@ class _MyAppState extends State<MyApp> {
|
|||
onLoadStart: (controller, url) async {
|
||||
print("onLoadStart $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
this.url = url ?? '';
|
||||
});
|
||||
},
|
||||
onLoadStop: (controller, url) async {
|
||||
print("onLoadStop $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
this.url = url ?? '';
|
||||
});
|
||||
},
|
||||
onUpdateVisitedHistory: (InAppWebViewController controller, String url, bool androidIsReload) {
|
||||
onUpdateVisitedHistory: (controller, url, androidIsReload) {
|
||||
print("onUpdateVisitedHistory $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
this.url = url ?? '';
|
||||
});
|
||||
},
|
||||
);
|
||||
|
@ -918,7 +932,7 @@ class _MyAppState extends State<MyApp> {
|
|||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
headlessWebView.dispose();
|
||||
headlessWebView?.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -938,8 +952,8 @@ class _MyAppState extends State<MyApp> {
|
|||
Center(
|
||||
child: RaisedButton(
|
||||
onPressed: () async {
|
||||
await headlessWebView.dispose();
|
||||
await headlessWebView.run();
|
||||
await headlessWebView?.dispose();
|
||||
await headlessWebView?.run();
|
||||
},
|
||||
child: Text("Run HeadlessInAppWebView")),
|
||||
),
|
||||
|
@ -947,7 +961,7 @@ class _MyAppState extends State<MyApp> {
|
|||
child: RaisedButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
await headlessWebView.webViewController.evaluateJavascript(source: """console.log('Here is the message!');""");
|
||||
await headlessWebView?.webViewController.evaluateJavascript(source: """console.log('Here is the message!');""");
|
||||
} on MissingPluginException catch(e) {
|
||||
print("HeadlessInAppWebView is not running. Click on \"Run HeadlessInAppWebView\"!");
|
||||
}
|
||||
|
@ -957,7 +971,7 @@ class _MyAppState extends State<MyApp> {
|
|||
Center(
|
||||
child: RaisedButton(
|
||||
onPressed: () {
|
||||
headlessWebView.dispose();
|
||||
headlessWebView?.dispose();
|
||||
},
|
||||
child: Text("Dispose HeadlessInAppWebView")),
|
||||
)
|
||||
|
@ -977,6 +991,8 @@ In-App Browser using native WebView.
|
|||
Create a Class that extends the `InAppBrowser` Class in order to override the callbacks to manage the browser events.
|
||||
Example:
|
||||
```dart
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
|
@ -987,22 +1003,22 @@ class MyInAppBrowser extends InAppBrowser {
|
|||
}
|
||||
|
||||
@override
|
||||
Future onLoadStart(String url) async {
|
||||
Future onLoadStart(url) async {
|
||||
print("\n\nStarted $url\n\n");
|
||||
}
|
||||
|
||||
@override
|
||||
Future onLoadStop(String url) async {
|
||||
Future onLoadStop(url) async {
|
||||
print("\n\nStopped $url\n\n");
|
||||
}
|
||||
|
||||
@override
|
||||
void onLoadError(String url, int code, String message) {
|
||||
void onLoadError(url, code, message) {
|
||||
print("Can't load $url.. Error: $message");
|
||||
}
|
||||
|
||||
@override
|
||||
void onProgressChanged(int progress) {
|
||||
void onProgressChanged(progress) {
|
||||
print("Progress: $progress");
|
||||
}
|
||||
|
||||
|
@ -1024,7 +1040,7 @@ class MyInAppBrowser extends InAppBrowser {
|
|||
"ms ---> duration: " +
|
||||
response.duration.toString() +
|
||||
"ms " +
|
||||
response.url);
|
||||
(response.url ?? ''));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1032,13 +1048,16 @@ class MyInAppBrowser extends InAppBrowser {
|
|||
print("""
|
||||
console output:
|
||||
message: ${consoleMessage.message}
|
||||
messageLevel: ${consoleMessage.messageLevel.toValue()}
|
||||
messageLevel: ${consoleMessage.messageLevel?.toValue()}
|
||||
""");
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
Future main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
if (Platform.isAndroid) {
|
||||
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
runApp(
|
||||
new MyApp(),
|
||||
);
|
||||
|
@ -1111,27 +1130,27 @@ Specific options of the `InAppBrowser` class are:
|
|||
##### `InAppBrowser` Cross-platform options
|
||||
|
||||
* `hidden`: 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`.
|
||||
* `toolbarTop`: Set to `false` to hide the toolbar at the top of the WebView. The default value is `true`.
|
||||
* `toolbarTopBackgroundColor`: Set the custom background color of the toolbar at the top.
|
||||
* `hideUrlBar`: Set to `true` to hide the url bar on the toolbar at the top. The default value is `false`.
|
||||
* `toolbarTopBackgroundColor`: Set the custom background color of the toolbar at the top.
|
||||
* `toolbarTop`: Set to `false` to hide the toolbar at the top of the WebView. The default value is `true`.
|
||||
|
||||
##### `InAppBrowser` Android-specific options
|
||||
|
||||
* `hideTitleBar`: Set to `true` if you want the title should be displayed. The default value is `false`.
|
||||
* `toolbarTopFixedTitle`: Set the action bar's title.
|
||||
* `closeOnCannotGoBack`: Set to `false` to not close the InAppBrowser when the user click on the back button and the WebView cannot go back to the history. The default value is `true`.
|
||||
* `hideTitleBar`: Set to `true` if you want the title should be displayed. The default value is `false`.
|
||||
* `progressBar`: Set to `false` to hide the progress bar at the bottom of the toolbar at the top. The default value is `true`.
|
||||
* `toolbarTopFixedTitle`: Set the action bar's title.
|
||||
|
||||
##### `InAppBrowser` iOS-specific options
|
||||
|
||||
* `toolbarBottom`: Set to `false` to hide the toolbar at the bottom of the WebView. The default value is `true`.
|
||||
* `toolbarBottomBackgroundColor`: Set the custom background color of the toolbar at the bottom.
|
||||
* `toolbarBottomTranslucent`: Set to `true` to set the toolbar at the bottom translucent. The default value is `true`.
|
||||
* `closeButtonCaption`: Set the custom text for the close button.
|
||||
* `closeButtonColor`: Set the custom color for the close button.
|
||||
* `presentationStyle`: Set the custom modal presentation style when presenting the WebView. The default value is `IOSUIModalPresentationStyle.FULL_SCREEN`.
|
||||
* `transitionStyle`: Set to the custom transition style when presenting the WebView. The default value is `IOSUIModalTransitionStyle.COVER_VERTICAL`.
|
||||
* `spinner`: Set to `false` to hide the spinner when the WebView is loading a page. The default value is `true`.
|
||||
* `toolbarBottomBackgroundColor`: Set the custom background color of the toolbar at the bottom.
|
||||
* `toolbarBottomTranslucent`: Set to `true` to set the toolbar at the bottom translucent. The default value is `true`.
|
||||
* `toolbarBottom`: Set to `false` to hide the toolbar at the bottom of the WebView. The default value is `true`.
|
||||
* `transitionStyle`: Set to the custom transition style when presenting the WebView. The default value is `IOSUIModalTransitionStyle.COVER_VERTICAL`.
|
||||
|
||||
#### `InAppBrowser` Events
|
||||
|
||||
|
@ -1145,27 +1164,31 @@ Specific events of the `InAppBrowser` class are:
|
|||
|
||||
[Chrome Custom Tabs](https://developer.android.com/reference/android/support/customtabs/package-summary) on Android / [SFSafariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) on iOS.
|
||||
|
||||
If you want to use the `ChromeSafariBrowser` on Android 11+ you need to specify your app querying for `android.support.customtabs.action.CustomTabsService` in your `AndroidManifest.xml` (you can read more about it here: https://developers.google.com/web/android/custom-tabs/best-practices#applications_targeting_android_11_api_level_30_or_above).
|
||||
|
||||
You can initialize the `ChromeSafariBrowser` instance with an `InAppBrowser` fallback instance.
|
||||
|
||||
Create a Class that extends the `ChromeSafariBrowser` Class in order to override the callbacks to manage the browser events. Example:
|
||||
```dart
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
class MyInAppBrowser extends InAppBrowser {
|
||||
|
||||
@override
|
||||
Future onLoadStart(String url) async {
|
||||
Future onLoadStart(url) async {
|
||||
print("\n\nStarted $url\n\n");
|
||||
}
|
||||
|
||||
@override
|
||||
Future onLoadStop(String url) async {
|
||||
Future onLoadStop(url) async {
|
||||
print("\n\nStopped $url\n\n");
|
||||
}
|
||||
|
||||
@override
|
||||
void onLoadError(String url, int code, String message) {
|
||||
void onLoadError(url, code, message) {
|
||||
print("\n\nCan't load $url.. Error: $message\n\n");
|
||||
}
|
||||
|
||||
|
@ -1196,11 +1219,12 @@ class MyChromeSafariBrowser extends ChromeSafariBrowser {
|
|||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
Future main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
runApp(
|
||||
new MyApp(),
|
||||
);
|
||||
if (Platform.isAndroid) {
|
||||
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
runApp(new MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatefulWidget {
|
||||
|
@ -1262,11 +1286,11 @@ Screenshots:
|
|||
|
||||
#### `ChromeSafariBrowser` Methods
|
||||
|
||||
* `open({@required String url, ChromeSafariBrowserClassOptions options, Map<String, String> headersFallback = const {}, InAppBrowserClassOptions optionsFallback})`: Opens an `url` in a new `ChromeSafariBrowser` instance.
|
||||
* `isOpened`: Returns `true` if the `ChromeSafariBrowser` instance is opened, otherwise `false`.
|
||||
* `close`: Closes the `ChromeSafariBrowser` instance.
|
||||
* `addMenuItem`: Adds a `ChromeSafariBrowserMenuItem` to the menu.
|
||||
* `addMenuItems`: Adds a list of `ChromeSafariBrowserMenuItem` to the menu.
|
||||
* `close`: Closes the `ChromeSafariBrowser` instance.
|
||||
* `isOpened`: Returns `true` if the `ChromeSafariBrowser` instance is opened, otherwise `false`.
|
||||
* `open({@required String url, ChromeSafariBrowserClassOptions options, Map<String, String> headersFallback = const {}, InAppBrowserClassOptions optionsFallback})`: Opens an `url` in a new `ChromeSafariBrowser` instance.
|
||||
* `static isAvailable`: On Android, returns `true` if Chrome Custom Tabs is available. On iOS, returns `true` if SFSafariViewController is available. Otherwise returns `false`.
|
||||
|
||||
#### `ChromeSafariBrowser` options
|
||||
|
@ -1274,18 +1298,18 @@ Screenshots:
|
|||
##### `ChromeSafariBrowser` Android-specific options
|
||||
|
||||
* `addDefaultShareMenuItem`: Set to `false` if you don't want the default share item to the menu. The default value is `true`.
|
||||
* `showTitle`: Set to `false` if the title shouldn't be shown in the custom tab. The default value is `true`.
|
||||
* `toolbarBackgroundColor`: Set the custom background color of the toolbar.
|
||||
* `enableUrlBarHiding`: Set to `true` to enable the url bar to hide as the user scrolls down on the page. The default value is `false`.
|
||||
* `instantAppsEnabled`: Set to `true` to enable Instant Apps. The default value is `false`.
|
||||
* `packageName`: Set the name of the application package to handle the intent (for example `com.android.chrome`), or null to allow any application package.
|
||||
* `keepAliveEnabled`: Set to `true` to enable Keep Alive. The default value is `false`.
|
||||
* `packageName`: Set the name of the application package to handle the intent (for example `com.android.chrome`), or null to allow any application package.
|
||||
* `showTitle`: Set to `false` if the title shouldn't be shown in the custom tab. The default value is `true`.
|
||||
* `toolbarBackgroundColor`: Set the custom background color of the toolbar.
|
||||
|
||||
##### `ChromeSafariBrowser` iOS-specific options
|
||||
|
||||
* `entersReaderIfAvailable`: Set to `true` if Reader mode should be entered automatically when it is available for the webpage. The default value is `false`.
|
||||
* `barCollapsingEnabled`: Set to `true` to enable bar collapsing. The default value is `false`.
|
||||
* `dismissButtonStyle`: Set the custom style for the dismiss button. The default value is `IOSSafariDismissButtonStyle.DONE`.
|
||||
* `entersReaderIfAvailable`: Set to `true` if Reader mode should be entered automatically when it is available for the webpage. The default value is `false`.
|
||||
* `preferredBarTintColor`: Set the custom background color of the navigation bar and the toolbar.
|
||||
* `preferredControlTintColor`: Set the custom color of the control buttons on the navigation bar and the toolbar.
|
||||
* `presentationStyle`: Set the custom modal presentation style when presenting the WebView. The default value is `IOSUIModalPresentationStyle.FULL_SCREEN`.
|
||||
|
@ -1310,6 +1334,9 @@ InAppLocalhostServer localhostServer = new InAppLocalhostServer();
|
|||
Future main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await localhostServer.start();
|
||||
if (Platform.isAndroid) {
|
||||
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
runApp(new MyApp());
|
||||
}
|
||||
|
||||
|
@ -1330,17 +1357,17 @@ Future main() async {
|
|||
initialUrl: "http://localhost:8080/assets/index.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
inAppWebViewOptions: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
onWebViewCreated: (controller) {
|
||||
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
onLoadStart: (controller, url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
onLoadStop: (controller, url) {
|
||||
|
||||
},
|
||||
),
|
||||
|
|
|
@ -109,31 +109,33 @@ public class ContentBlockerHandler {
|
|||
latch.await();
|
||||
}
|
||||
|
||||
if (!trigger.loadType.isEmpty()) {
|
||||
URI cUrl = new URI(webViewUrl[0]);
|
||||
String cHost = cUrl.getHost();
|
||||
int cPort = cUrl.getPort();
|
||||
String cScheme = cUrl.getScheme();
|
||||
if (webViewUrl[0] != null) {
|
||||
if (!trigger.loadType.isEmpty()) {
|
||||
URI cUrl = new URI(webViewUrl[0]);
|
||||
String cHost = cUrl.getHost();
|
||||
int cPort = cUrl.getPort();
|
||||
String cScheme = cUrl.getScheme();
|
||||
|
||||
if ( (trigger.loadType.contains("first-party") && cHost != null && !(cScheme.equals(scheme) && cHost.equals(host) && cPort == port)) ||
|
||||
(trigger.loadType.contains("third-party") && cHost != null && cHost.equals(host)) )
|
||||
return null;
|
||||
}
|
||||
if (!trigger.ifTopUrl.isEmpty()) {
|
||||
boolean matchFound = false;
|
||||
for (String topUrl : trigger.ifTopUrl) {
|
||||
if (webViewUrl[0].startsWith(topUrl)) {
|
||||
matchFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!matchFound)
|
||||
return null;
|
||||
}
|
||||
if (!trigger.unlessTopUrl.isEmpty()) {
|
||||
for (String topUrl : trigger.unlessTopUrl)
|
||||
if (webViewUrl[0].startsWith(topUrl))
|
||||
if ( (trigger.loadType.contains("first-party") && cHost != null && !(cScheme.equals(scheme) && cHost.equals(host) && cPort == port)) ||
|
||||
(trigger.loadType.contains("third-party") && cHost != null && cHost.equals(host)) )
|
||||
return null;
|
||||
}
|
||||
if (!trigger.ifTopUrl.isEmpty()) {
|
||||
boolean matchFound = false;
|
||||
for (String topUrl : trigger.ifTopUrl) {
|
||||
if (webViewUrl[0].startsWith(topUrl)) {
|
||||
matchFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!matchFound)
|
||||
return null;
|
||||
}
|
||||
if (!trigger.unlessTopUrl.isEmpty()) {
|
||||
for (String topUrl : trigger.unlessTopUrl)
|
||||
if (webViewUrl[0].startsWith(topUrl))
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
switch (action.type) {
|
||||
|
|
|
@ -67,28 +67,9 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
"- See the official wiki here: https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects\n\n\n");
|
||||
}
|
||||
|
||||
// MutableContextWrapper mMutableContext = new MutableContextWrapper(Shared.activity);
|
||||
// webView = new InAppWebView(mMutableContext, this, id, options, contextMenu, containerView);
|
||||
// displayListenerProxy.onPostWebViewInitialization(displayManager);
|
||||
// mMutableContext.setBaseContext(context);
|
||||
|
||||
webView = new InAppWebView(Shared.activity, this, id, windowId, options, contextMenu, containerView);
|
||||
webView = new InAppWebView(context, this, id, windowId, options, contextMenu, containerView);
|
||||
displayListenerProxy.onPostWebViewInitialization(displayManager);
|
||||
|
||||
// fix https://github.com/pichillilorenzo/flutter_inappwebview/issues/182
|
||||
try {
|
||||
Class superClass = webView.getClass().getSuperclass();
|
||||
while(!superClass.getName().equals("android.view.View")) {
|
||||
superClass = superClass.getSuperclass();
|
||||
}
|
||||
Field mContext = superClass.getDeclaredField("mContext");
|
||||
mContext.setAccessible(true);
|
||||
mContext.set(webView, context);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(LOG_TAG, "Cannot find mContext for this WebView");
|
||||
}
|
||||
|
||||
webView.prepare();
|
||||
|
||||
if (windowId != null) {
|
||||
|
|
|
@ -677,9 +677,6 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
WebSettings settings = getSettings();
|
||||
|
||||
settings.setJavaScriptEnabled(options.javaScriptEnabled);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
setWebContentsDebuggingEnabled(options.debuggingEnabled);
|
||||
}
|
||||
settings.setJavaScriptCanOpenWindowsAutomatically(options.javaScriptCanOpenWindowsAutomatically);
|
||||
settings.setBuiltInZoomControls(options.builtInZoomControls);
|
||||
settings.setDisplayZoomControls(options.displayZoomControls);
|
||||
|
@ -853,7 +850,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
}
|
||||
};
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && !options.useHybridComposition) {
|
||||
checkContextMenuShouldBeClosedTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -1133,9 +1130,6 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
if (newOptionsMap.get("javaScriptEnabled") != null && options.javaScriptEnabled != newOptions.javaScriptEnabled)
|
||||
settings.setJavaScriptEnabled(newOptions.javaScriptEnabled);
|
||||
|
||||
if (newOptionsMap.get("debuggingEnabled") != null && options.debuggingEnabled != newOptions.debuggingEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
|
||||
setWebContentsDebuggingEnabled(newOptions.debuggingEnabled);
|
||||
|
||||
if (newOptionsMap.get("useShouldInterceptAjaxRequest") != null && options.useShouldInterceptAjaxRequest != newOptions.useShouldInterceptAjaxRequest) {
|
||||
String placeholderValue = newOptions.useShouldInterceptAjaxRequest ? "true" : "false";
|
||||
String sourceJs = InAppWebView.enableVariableForShouldInterceptAjaxRequestJS.replace("$PLACEHOLDER_VALUE", placeholderValue);
|
||||
|
@ -1505,14 +1499,11 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onScrollChanged (int l,
|
||||
int t,
|
||||
int oldl,
|
||||
int oldt) {
|
||||
super.onScrollChanged(l, t, oldl, oldt);
|
||||
|
||||
int x = (int) (l/scale);
|
||||
int y = (int) (t/scale);
|
||||
protected void onScrollChanged (int x,
|
||||
int y,
|
||||
int oldX,
|
||||
int oldY) {
|
||||
super.onScrollChanged(x, y, oldX, oldY);
|
||||
|
||||
if (floatingContextMenu != null) {
|
||||
floatingContextMenu.setAlpha(0f);
|
||||
|
@ -1662,12 +1653,18 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
|
||||
@Override
|
||||
public ActionMode startActionMode(ActionMode.Callback callback) {
|
||||
if (options.useHybridComposition && !options.disableContextMenu && (contextMenu == null || contextMenu.keySet().size() == 0)) {
|
||||
return super.startActionMode(callback);
|
||||
}
|
||||
return rebuildActionMode(super.startActionMode(callback), callback);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
@Override
|
||||
public ActionMode startActionMode(ActionMode.Callback callback, int type) {
|
||||
if (options.useHybridComposition && !options.disableContextMenu && (contextMenu == null || contextMenu.keySet().size() == 0)) {
|
||||
return super.startActionMode(callback, type);
|
||||
}
|
||||
return rebuildActionMode(super.startActionMode(callback, type), callback);
|
||||
}
|
||||
|
||||
|
@ -1711,6 +1708,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
final MenuItem menuItem = actionMenu.getItem(i);
|
||||
final int itemId = menuItem.getItemId();
|
||||
final String itemTitle = menuItem.getTitle().toString();
|
||||
|
||||
TextView text = (TextView) LayoutInflater.from(this.getContext())
|
||||
.inflate(R.layout.floating_action_mode_item, this, false);
|
||||
text.setText(itemTitle);
|
||||
|
@ -1855,7 +1853,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
" var clientRect = range.getClientRects();" +
|
||||
" if (clientRect.length > 0) {" +
|
||||
" rangeY = clientRect[0].y;" +
|
||||
" } else if (document.activeElement) {" +
|
||||
" } else if (document.activeElement != null && document.activeElement.tagName.toLowerCase() !== 'iframe') {" +
|
||||
" var boundingClientRect = document.activeElement.getBoundingClientRect();" +
|
||||
" rangeY = boundingClientRect.y;" +
|
||||
" }" +
|
||||
|
@ -1865,7 +1863,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
@Override
|
||||
public void onReceiveValue(String value) {
|
||||
if (floatingContextMenu != null) {
|
||||
if (value != null) {
|
||||
if (value != null && !value.equals("null")) {
|
||||
int x = contextMenuPoint.x;
|
||||
int y = (int) ((Float.parseFloat(value) * scale) + (floatingContextMenu.getHeight() / 3.5));
|
||||
contextMenuPoint.y = y;
|
||||
|
@ -1873,6 +1871,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
} else {
|
||||
floatingContextMenu.setVisibility(View.VISIBLE);
|
||||
floatingContextMenu.animate().alpha(1f).setDuration(100).setListener(null);
|
||||
onFloatingActionGlobalLayout(contextMenuPoint.x, contextMenuPoint.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@ package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
|
|||
import android.Manifest;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
|
@ -46,6 +48,7 @@ import com.pichillilorenzo.flutter_inappwebview.Shared;
|
|||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -72,7 +75,8 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
private static final int PICKER = 1;
|
||||
private static final int PICKER_LEGACY = 3;
|
||||
final String DEFAULT_MIME_TYPES = "*/*";
|
||||
private static Uri outputFileUri;
|
||||
private static Uri videoOutputFileUri;
|
||||
private static Uri imageOutputFileUri;
|
||||
|
||||
protected static final FrameLayout.LayoutParams FULLSCREEN_LAYOUT_PARAMS = new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER);
|
||||
|
@ -810,39 +814,37 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
// this filename instead
|
||||
switch (requestCode) {
|
||||
case PICKER:
|
||||
if (resultCode != RESULT_OK) {
|
||||
if (InAppWebViewFlutterPlugin.filePathCallback != null) {
|
||||
InAppWebViewFlutterPlugin.filePathCallback.onReceiveValue(null);
|
||||
}
|
||||
} else {
|
||||
Uri result[] = this.getSelectedFiles(data, resultCode);
|
||||
if (result != null) {
|
||||
InAppWebViewFlutterPlugin.filePathCallback.onReceiveValue(result);
|
||||
} else {
|
||||
InAppWebViewFlutterPlugin.filePathCallback.onReceiveValue(new Uri[]{outputFileUri});
|
||||
}
|
||||
Uri[] results = null;
|
||||
if (resultCode == RESULT_OK) {
|
||||
results = getSelectedFiles(data, resultCode);
|
||||
}
|
||||
|
||||
if (InAppWebViewFlutterPlugin.filePathCallback != null) {
|
||||
InAppWebViewFlutterPlugin.filePathCallback.onReceiveValue(results);
|
||||
}
|
||||
break;
|
||||
|
||||
case PICKER_LEGACY:
|
||||
Uri result = resultCode != Activity.RESULT_OK ? null : data == null ? outputFileUri : data.getData();
|
||||
Uri result = null;
|
||||
if (resultCode == RESULT_OK) {
|
||||
result = data != null ? data.getData() : getCapturedMediaFile();
|
||||
}
|
||||
|
||||
InAppWebViewFlutterPlugin.filePathCallbackLegacy.onReceiveValue(result);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
InAppWebViewFlutterPlugin.filePathCallback = null;
|
||||
InAppWebViewFlutterPlugin.filePathCallbackLegacy = null;
|
||||
outputFileUri = null;
|
||||
imageOutputFileUri = null;
|
||||
videoOutputFileUri = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Uri[] getSelectedFiles(Intent data, int resultCode) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// we have one file selected
|
||||
if (data.getData() != null) {
|
||||
if (data != null && data.getData() != null) {
|
||||
if (resultCode == RESULT_OK && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
return WebChromeClient.FileChooserParams.parseResult(resultCode, data);
|
||||
} else {
|
||||
|
@ -851,7 +853,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
}
|
||||
|
||||
// we have multiple files selected
|
||||
if (data.getClipData() != null) {
|
||||
if (data != null && data.getClipData() != null) {
|
||||
final int numSelectedFiles = data.getClipData().getItemCount();
|
||||
Uri[] result = new Uri[numSelectedFiles];
|
||||
for (int i = 0; i < numSelectedFiles; i++) {
|
||||
|
@ -859,6 +861,40 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// we have a captured image or video file
|
||||
Uri mediaUri = getCapturedMediaFile();
|
||||
if (mediaUri != null) {
|
||||
return new Uri[]{mediaUri};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isFileNotEmpty(Uri uri) {
|
||||
Activity activity = inAppBrowserActivity != null ? inAppBrowserActivity : Shared.activity;
|
||||
|
||||
long length;
|
||||
try {
|
||||
AssetFileDescriptor descriptor = activity.getContentResolver().openAssetFileDescriptor(uri, "r");
|
||||
length = descriptor.getLength();
|
||||
descriptor.close();
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return length > 0;
|
||||
}
|
||||
|
||||
private Uri getCapturedMediaFile() {
|
||||
if (imageOutputFileUri != null && isFileNotEmpty(imageOutputFileUri)) {
|
||||
return imageOutputFileUri;
|
||||
}
|
||||
|
||||
if (videoOutputFileUri != null && isFileNotEmpty(videoOutputFileUri)) {
|
||||
return videoOutputFileUri;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -935,15 +971,15 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
|
||||
private Intent getPhotoIntent() {
|
||||
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
outputFileUri = getOutputUri(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
|
||||
imageOutputFileUri = getOutputUri(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageOutputFileUri);
|
||||
return intent;
|
||||
}
|
||||
|
||||
private Intent getVideoIntent() {
|
||||
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
|
||||
outputFileUri = getOutputUri(MediaStore.ACTION_VIDEO_CAPTURE);
|
||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
|
||||
videoOutputFileUri = getOutputUri(MediaStore.ACTION_VIDEO_CAPTURE);
|
||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, videoOutputFileUri);
|
||||
return intent;
|
||||
}
|
||||
|
||||
|
@ -971,6 +1007,20 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
return intent;
|
||||
}
|
||||
|
||||
private Boolean acceptsAny(String[] types) {
|
||||
if (isArrayEmpty(types)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (String type : types) {
|
||||
if (type.equals("*/*")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Boolean acceptsImages(String types) {
|
||||
String mimeType = types;
|
||||
if (types.matches("\\.\\w+")) {
|
||||
|
@ -981,7 +1031,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
|
||||
private Boolean acceptsImages(String[] types) {
|
||||
String[] mimeTypes = getAcceptedMimeType(types);
|
||||
return isArrayEmpty(mimeTypes) || arrayContainsString(mimeTypes, "image");
|
||||
return acceptsAny(types) || arrayContainsString(mimeTypes, "image");
|
||||
}
|
||||
|
||||
private Boolean acceptsVideo(String types) {
|
||||
|
@ -994,7 +1044,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
|
||||
private Boolean acceptsVideo(String[] types) {
|
||||
String[] mimeTypes = getAcceptedMimeType(types);
|
||||
return isArrayEmpty(mimeTypes) || arrayContainsString(mimeTypes, "video");
|
||||
return acceptsAny(types) || arrayContainsString(mimeTypes, "video");
|
||||
}
|
||||
|
||||
private Boolean arrayContainsString(String[] array, String pattern) {
|
||||
|
@ -1056,31 +1106,29 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
String prefix = "";
|
||||
String suffix = "";
|
||||
String dir = "";
|
||||
String filename = "";
|
||||
|
||||
if (intentType.equals(MediaStore.ACTION_IMAGE_CAPTURE)) {
|
||||
prefix = "image-";
|
||||
prefix = "image";
|
||||
suffix = ".jpg";
|
||||
dir = Environment.DIRECTORY_PICTURES;
|
||||
} else if (intentType.equals(MediaStore.ACTION_VIDEO_CAPTURE)) {
|
||||
prefix = "video-";
|
||||
prefix = "video";
|
||||
suffix = ".mp4";
|
||||
dir = Environment.DIRECTORY_MOVIES;
|
||||
}
|
||||
|
||||
filename = prefix + String.valueOf(System.currentTimeMillis()) + suffix;
|
||||
|
||||
// for versions below 6.0 (23) we use the old File creation & permissions model
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
// only this Directory works on all tested Android versions
|
||||
// ctx.getExternalFilesDir(dir) was failing on Android 5.0 (sdk 21)
|
||||
File storageDir = Environment.getExternalStoragePublicDirectory(dir);
|
||||
String filename = String.format("%s-%d%s", prefix, System.currentTimeMillis(), suffix);
|
||||
return new File(storageDir, filename);
|
||||
}
|
||||
|
||||
Activity activity = inAppBrowserActivity != null ? inAppBrowserActivity : Shared.activity;
|
||||
File storageDir = activity.getApplicationContext().getExternalFilesDir(null);
|
||||
return File.createTempFile(filename, suffix, storageDir);
|
||||
return File.createTempFile(prefix, suffix, storageDir);
|
||||
}
|
||||
|
||||
private Boolean isArrayEmpty(String[] arr) {
|
||||
|
|
|
@ -176,7 +176,9 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
if (webView.options.useOnLoadResource) {
|
||||
js += InAppWebView.resourceObserverJS.replaceAll("[\r\n]+", "");
|
||||
}
|
||||
js += InAppWebView.checkGlobalKeyDownEventToHideContextMenuJS.replaceAll("[\r\n]+", "");
|
||||
if (!webView.options.useHybridComposition) {
|
||||
js += InAppWebView.checkGlobalKeyDownEventToHideContextMenuJS.replaceAll("[\r\n]+", "");
|
||||
}
|
||||
js += InAppWebView.onWindowFocusEventJS.replaceAll("[\r\n]+", "");
|
||||
js += InAppWebView.onWindowBlurEventJS.replaceAll("[\r\n]+", "");
|
||||
js += InAppWebView.printJS.replaceAll("[\r\n]+", "");
|
||||
|
|
|
@ -26,7 +26,6 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
|
|||
public String userAgent = "";
|
||||
public String applicationNameForUserAgent = "";
|
||||
public Boolean javaScriptEnabled = true;
|
||||
public Boolean debuggingEnabled = false;
|
||||
public Boolean javaScriptCanOpenWindowsAutomatically = false;
|
||||
public Boolean mediaPlaybackRequiresUserGesture = true;
|
||||
public Integer minimumFontSize = 8;
|
||||
|
@ -44,6 +43,8 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
|
|||
public Boolean disableHorizontalScroll = false;
|
||||
public Boolean disableContextMenu = false;
|
||||
public Boolean supportZoom = true;
|
||||
public Boolean allowFileAccessFromFileURLs = false;
|
||||
public Boolean allowUniversalAccessFromFileURLs = false;
|
||||
|
||||
public Integer textZoom = 100;
|
||||
public Boolean clearSessionCache = false;
|
||||
|
@ -56,8 +57,6 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
|
|||
public Integer mixedContentMode;
|
||||
public Boolean allowContentAccess = true;
|
||||
public Boolean allowFileAccess = true;
|
||||
public Boolean allowFileAccessFromFileURLs = true;
|
||||
public Boolean allowUniversalAccessFromFileURLs = true;
|
||||
public String appCachePath;
|
||||
public Boolean blockNetworkImage = false;
|
||||
public Boolean blockNetworkLoads = false;
|
||||
|
@ -97,6 +96,7 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
|
|||
public Boolean useShouldInterceptRequest = false;
|
||||
public Boolean useOnRenderProcessGone = false;
|
||||
public Boolean disableDefaultErrorPage = false;
|
||||
public Boolean useHybridComposition = false;
|
||||
|
||||
@Override
|
||||
public InAppWebViewOptions parse(Map<String, Object> options) {
|
||||
|
@ -129,9 +129,6 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
|
|||
case "javaScriptEnabled":
|
||||
javaScriptEnabled = (Boolean) value;
|
||||
break;
|
||||
case "debuggingEnabled":
|
||||
debuggingEnabled = (Boolean) value;
|
||||
break;
|
||||
case "javaScriptCanOpenWindowsAutomatically":
|
||||
javaScriptCanOpenWindowsAutomatically = (Boolean) value;
|
||||
break;
|
||||
|
@ -339,6 +336,9 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
|
|||
case "disableDefaultErrorPage":
|
||||
disableDefaultErrorPage = (Boolean) value;
|
||||
break;
|
||||
case "useHybridComposition":
|
||||
useHybridComposition = (Boolean) value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,7 +355,6 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
|
|||
options.put("userAgent", userAgent);
|
||||
options.put("applicationNameForUserAgent", applicationNameForUserAgent);
|
||||
options.put("javaScriptEnabled", javaScriptEnabled);
|
||||
options.put("debuggingEnabled", debuggingEnabled);
|
||||
options.put("javaScriptCanOpenWindowsAutomatically", javaScriptCanOpenWindowsAutomatically);
|
||||
options.put("mediaPlaybackRequiresUserGesture", mediaPlaybackRequiresUserGesture);
|
||||
options.put("minimumFontSize", minimumFontSize);
|
||||
|
@ -425,6 +424,7 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
|
|||
options.put("useShouldInterceptRequest", useShouldInterceptRequest);
|
||||
options.put("useOnRenderProcessGone", useOnRenderProcessGone);
|
||||
options.put("disableDefaultErrorPage", disableDefaultErrorPage);
|
||||
options.put("useHybridComposition", useHybridComposition);
|
||||
return options;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ import android.widget.ListPopupWindow;
|
|||
* A WebView subclass that mirrors the same implementation hacks that the system WebView does in
|
||||
* order to correctly create an InputConnection.
|
||||
*
|
||||
* These hacks are only needed in Android versions below N and exist to create an InputConnection
|
||||
* on the WebView's dedicated input, or IME, thread. The majority of this proxying logic is in
|
||||
* https://github.com/flutter/plugins/blob/master/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java
|
||||
*/
|
||||
public class InputAwareWebView extends WebView {
|
||||
|
@ -234,9 +236,9 @@ public class InputAwareWebView extends WebView {
|
|||
|
||||
private boolean isCalledFromListPopupWindowShow() {
|
||||
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
|
||||
for (int i = 0; i < stackTraceElements.length; i++) {
|
||||
if (stackTraceElements[i].getClassName().equals(ListPopupWindow.class.getCanonicalName())
|
||||
&& stackTraceElements[i].getMethodName().equals("show")) {
|
||||
for (StackTraceElement stackTraceElement : stackTraceElements) {
|
||||
if (stackTraceElement.getClassName().equals(ListPopupWindow.class.getCanonicalName())
|
||||
&& stackTraceElement.getMethodName().equals("show")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,13 @@ public class InAppWebViewStatic implements MethodChannel.MethodCallHandler {
|
|||
result.success(null);
|
||||
}
|
||||
break;
|
||||
case "setWebContentsDebuggingEnabled":
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
boolean debuggingEnabled = (boolean) call.argument("debuggingEnabled");
|
||||
WebView.setWebContentsDebuggingEnabled(debuggingEnabled);
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
default:
|
||||
result.notImplemented();
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.11/","dependencies":[]}],"android":[{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.11/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+3/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.0.1+7/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+1/","dependencies":[]}],"windows":[],"web":[{"name":"url_launcher_web","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_web-0.1.2/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_inappwebview","dependencies":[]},{"name":"e2e","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_web","url_launcher_macos"]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]}],"date_created":"2020-09-07 18:06:16.830498","version":"1.20.3"}
|
||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"android":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+8/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.0.4+3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-01-29 00:53:56.206541","version":"1.26.0-13.0.pre.194"}
|
|
@ -1,15 +1,16 @@
|
|||
package com.pichillilorenzo.flutterwebviewexample;
|
||||
|
||||
import android.os.Bundle;
|
||||
import dev.flutter.plugins.e2e.E2EPlugin;
|
||||
import io.flutter.app.FlutterActivity;
|
||||
import dev.flutter.plugins.integration_test.IntegrationTestPlugin;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||
|
||||
public class EmbedderV1Activity extends FlutterActivity {
|
||||
@SuppressWarnings("deprecation")
|
||||
public class EmbedderV1Activity extends io.flutter.app.FlutterActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
E2EPlugin.registerWith(registrarFor("dev.flutter.plugins.e2e.E2EPlugin"));
|
||||
IntegrationTestPlugin.registerWith(
|
||||
registrarFor("dev.flutter.plugins.integration_test.IntegrationTestPlugin"));
|
||||
InAppWebViewFlutterPlugin.registerWith(
|
||||
registrarFor("com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin"));
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
final environment = {"NODE_SERVER_IP":"192.168.1.129"};
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,4 @@
|
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
FLUTTER_BUILD_MODE=debug
|
|
@ -1,18 +0,0 @@
|
|||
#
|
||||
# NOTE: This podspec is NOT to be published. It is only used as a local source!
|
||||
#
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'Flutter'
|
||||
s.version = '1.0.0'
|
||||
s.summary = 'High-performance, high-fidelity mobile apps.'
|
||||
s.description = <<-DESC
|
||||
Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
|
||||
DESC
|
||||
s.homepage = 'https://flutter.io'
|
||||
s.license = { :type => 'MIT' }
|
||||
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
|
||||
s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
|
||||
s.ios.deployment_target = '8.0'
|
||||
s.vendored_frameworks = 'Flutter.framework'
|
||||
end
|
|
@ -1,2 +1,3 @@
|
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
|
|
@ -2,14 +2,12 @@
|
|||
# This is a generated file; do not edit or check into version control.
|
||||
export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter"
|
||||
export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example"
|
||||
export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart"
|
||||
export "FLUTTER_TARGET=lib/main.dart"
|
||||
export "FLUTTER_BUILD_DIR=build"
|
||||
export "SYMROOT=${SOURCE_ROOT}/../build/ios"
|
||||
export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
|
||||
export "FLUTTER_FRAMEWORK_DIR=/Users/lorenzopichilli/flutter/bin/cache/artifacts/engine/ios"
|
||||
export "FLUTTER_BUILD_NAME=1.0.0"
|
||||
export "FLUTTER_BUILD_NUMBER=1"
|
||||
export "DART_OBFUSCATION=false"
|
||||
export "TRACK_WIDGET_CREATION=true"
|
||||
export "TRACK_WIDGET_CREATION=false"
|
||||
export "TREE_SHAKE_ICONS=false"
|
||||
export "PACKAGE_CONFIG=.packages"
|
||||
|
|
|
@ -254,19 +254,17 @@
|
|||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
|
||||
"${PODS_ROOT}/../Flutter/Flutter.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/e2e/e2e.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/flutter_downloader/flutter_downloader.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/flutter_inappwebview/flutter_inappwebview.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/integration_test/integration_test.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/e2e.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_downloader.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappwebview.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/integration_test.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework",
|
||||
);
|
||||
|
@ -451,7 +449,7 @@
|
|||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.pichillilorenzo.flutter_inappwebviewExample;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "flutter-inappwebviewExample";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
|
|
@ -2,54 +2,52 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSLocationAlwaysUsageDescription</key>
|
||||
<string>Need location</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>Need location</string>
|
||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||
<string>Need location</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>flutter_inappwebview_example</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>fetch</string>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>flutter_inappwebview_example</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsLocalNetworking</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||
<string>Need location</string>
|
||||
<key>NSLocationAlwaysUsageDescription</key>
|
||||
<string>Need location</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>Need location</string>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>fetch</string>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>io.flutter.embedded_views_preview</key>
|
||||
<true/>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
|
@ -57,7 +55,13 @@
|
|||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>NSBonjourServices</key>
|
||||
<array>
|
||||
<string></string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>NSLocalNetworkUsageDescription</key>
|
||||
<string>Allow Flutter tools on your computer to connect and debug your application.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -11,7 +11,7 @@ class HeadlessInAppWebViewExampleScreen extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebViewExampleScreen> {
|
||||
HeadlessInAppWebView headlessWebView;
|
||||
HeadlessInAppWebView? headlessWebView;
|
||||
String url = "";
|
||||
|
||||
@override
|
||||
|
@ -22,7 +22,7 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView
|
|||
initialUrl: "https://flutter.dev/",
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
|
||||
),
|
||||
),
|
||||
onWebViewCreated: (controller) {
|
||||
|
@ -34,19 +34,19 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView
|
|||
onLoadStart: (controller, url) async {
|
||||
print("onLoadStart $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
this.url = url ?? '';
|
||||
});
|
||||
},
|
||||
onLoadStop: (controller, url) async {
|
||||
print("onLoadStop $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
this.url = url ?? '';
|
||||
});
|
||||
},
|
||||
onUpdateVisitedHistory: (InAppWebViewController controller, String url, bool androidIsReload) {
|
||||
onUpdateVisitedHistory: (controller, url, androidIsReload) {
|
||||
print("onUpdateVisitedHistory $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
this.url = url ?? '';
|
||||
});
|
||||
},
|
||||
);
|
||||
|
@ -55,7 +55,7 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView
|
|||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
headlessWebView.dispose();
|
||||
headlessWebView?.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -76,8 +76,8 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView
|
|||
Center(
|
||||
child: RaisedButton(
|
||||
onPressed: () async {
|
||||
await headlessWebView.dispose();
|
||||
await headlessWebView.run();
|
||||
await headlessWebView?.dispose();
|
||||
await headlessWebView?.run();
|
||||
},
|
||||
child: Text("Run HeadlessInAppWebView")),
|
||||
),
|
||||
|
@ -85,7 +85,7 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView
|
|||
child: RaisedButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
await headlessWebView.webViewController.evaluateJavascript(source: """console.log('Here is the message!');""");
|
||||
await headlessWebView?.webViewController.evaluateJavascript(source: """console.log('Here is the message!');""");
|
||||
} on MissingPluginException catch(e) {
|
||||
print("HeadlessInAppWebView is not running. Click on \"Run HeadlessInAppWebView\"!");
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebView
|
|||
Center(
|
||||
child: RaisedButton(
|
||||
onPressed: () {
|
||||
headlessWebView.dispose();
|
||||
headlessWebView?.dispose();
|
||||
},
|
||||
child: Text("Dispose HeadlessInAppWebView")),
|
||||
)
|
||||
|
|
|
@ -12,22 +12,22 @@ class MyInAppBrowser extends InAppBrowser {
|
|||
}
|
||||
|
||||
@override
|
||||
Future onLoadStart(String url) async {
|
||||
Future onLoadStart(url) async {
|
||||
print("\n\nStarted $url\n\n");
|
||||
}
|
||||
|
||||
@override
|
||||
Future onLoadStop(String url) async {
|
||||
Future onLoadStop(url) async {
|
||||
print("\n\nStopped $url\n\n");
|
||||
}
|
||||
|
||||
@override
|
||||
void onLoadError(String url, int code, String message) {
|
||||
void onLoadError(url, code, message) {
|
||||
print("Can't load $url.. Error: $message");
|
||||
}
|
||||
|
||||
@override
|
||||
void onProgressChanged(int progress) {
|
||||
void onProgressChanged(progress) {
|
||||
print("Progress: $progress");
|
||||
}
|
||||
|
||||
|
@ -38,27 +38,27 @@ class MyInAppBrowser extends InAppBrowser {
|
|||
|
||||
@override
|
||||
Future<ShouldOverrideUrlLoadingAction> shouldOverrideUrlLoading(
|
||||
ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest) async {
|
||||
shouldOverrideUrlLoadingRequest) async {
|
||||
print("\n\nOverride ${shouldOverrideUrlLoadingRequest.url}\n\n");
|
||||
return ShouldOverrideUrlLoadingAction.ALLOW;
|
||||
}
|
||||
|
||||
@override
|
||||
void onLoadResource(LoadedResource response) {
|
||||
void onLoadResource(response) {
|
||||
print("Started at: " +
|
||||
response.startTime.toString() +
|
||||
"ms ---> duration: " +
|
||||
response.duration.toString() +
|
||||
"ms " +
|
||||
response.url);
|
||||
response.url!);
|
||||
}
|
||||
|
||||
@override
|
||||
void onConsoleMessage(ConsoleMessage consoleMessage) {
|
||||
void onConsoleMessage(consoleMessage) {
|
||||
print("""
|
||||
console output:
|
||||
message: ${consoleMessage.message}
|
||||
messageLevel: ${consoleMessage.messageLevel.toValue()}
|
||||
messageLevel: ${consoleMessage.messageLevel!.toValue()}
|
||||
""");
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,6 @@ class _InAppBrowserExampleScreenState extends State<InAppBrowserExampleScreen> {
|
|||
options: InAppBrowserClassOptions(
|
||||
inAppWebViewGroupOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
useShouldOverrideUrlLoading: true,
|
||||
useOnLoadResource: true,
|
||||
))));
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -14,8 +13,8 @@ class InAppWebViewExampleScreen extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
||||
InAppWebViewController webView;
|
||||
ContextMenu contextMenu;
|
||||
InAppWebViewController? webView;
|
||||
late ContextMenu contextMenu;
|
||||
String url = "";
|
||||
double progress = 0;
|
||||
CookieManager _cookieManager = CookieManager.instance();
|
||||
|
@ -28,8 +27,8 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
|||
menuItems: [
|
||||
ContextMenuItem(androidId: 1, iosId: "1", title: "Special", action: () async {
|
||||
print("Menu item Special clicked!");
|
||||
print(await webView.getSelectedText());
|
||||
await webView.clearFocus();
|
||||
print(await webView?.getSelectedText());
|
||||
await webView?.clearFocus();
|
||||
})
|
||||
],
|
||||
options: ContextMenuOptions(
|
||||
|
@ -38,7 +37,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
|||
onCreateContextMenu: (hitTestResult) async {
|
||||
print("onCreateContextMenu");
|
||||
print(hitTestResult.extra);
|
||||
print(await webView.getSelectedText());
|
||||
print(await webView?.getSelectedText());
|
||||
},
|
||||
onHideContextMenu: () {
|
||||
print("onHideContextMenu");
|
||||
|
@ -81,26 +80,25 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
|||
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
|
||||
child: InAppWebView(
|
||||
// contextMenu: contextMenu,
|
||||
initialUrl: "https://github.com/flutter",
|
||||
initialUrl: "https://flutter.dev/",
|
||||
// initialFile: "assets/index.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
useShouldOverrideUrlLoading: true,
|
||||
useShouldOverrideUrlLoading: false,
|
||||
),
|
||||
android: AndroidInAppWebViewOptions(
|
||||
useHybridComposition: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
onWebViewCreated: (controller) {
|
||||
webView = controller;
|
||||
print("onWebViewCreated");
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
onLoadStart: (controller, url) {
|
||||
print("onLoadStart $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
this.url = url ?? '';
|
||||
});
|
||||
},
|
||||
shouldOverrideUrlLoading: (controller, shouldOverrideUrlLoadingRequest) async {
|
||||
|
@ -122,21 +120,21 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
|||
|
||||
return ShouldOverrideUrlLoadingAction.ALLOW;
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) async {
|
||||
onLoadStop: (controller, url) async {
|
||||
print("onLoadStop $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
this.url = url ?? '';
|
||||
});
|
||||
},
|
||||
onProgressChanged: (InAppWebViewController controller, int progress) {
|
||||
onProgressChanged: (controller, progress) {
|
||||
setState(() {
|
||||
this.progress = progress / 100;
|
||||
});
|
||||
},
|
||||
onUpdateVisitedHistory: (InAppWebViewController controller, String url, bool androidIsReload) {
|
||||
onUpdateVisitedHistory: (controller, url, androidIsReload) {
|
||||
print("onUpdateVisitedHistory $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
this.url = url ?? '';
|
||||
});
|
||||
},
|
||||
onConsoleMessage: (controller, consoleMessage) {
|
||||
|
@ -151,25 +149,19 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
|||
RaisedButton(
|
||||
child: Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
if (webView != null) {
|
||||
webView.goBack();
|
||||
}
|
||||
webView?.goBack();
|
||||
},
|
||||
),
|
||||
RaisedButton(
|
||||
child: Icon(Icons.arrow_forward),
|
||||
onPressed: () {
|
||||
if (webView != null) {
|
||||
webView.goForward();
|
||||
}
|
||||
webView?.goForward();
|
||||
},
|
||||
),
|
||||
RaisedButton(
|
||||
child: Icon(Icons.refresh),
|
||||
onPressed: () {
|
||||
if (webView != null) {
|
||||
webView.reload();
|
||||
}
|
||||
webView?.reload();
|
||||
},
|
||||
),
|
||||
],
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'package:flutter_inappwebview_example/chrome_safari_browser_example.screen.dart';
|
||||
import 'package:flutter_inappwebview_example/headless_in_app_webview.screen.dart';
|
||||
|
@ -15,10 +17,13 @@ Future main() async {
|
|||
// await Permission.camera.request();
|
||||
// await Permission.storage.request();
|
||||
// await localhostServer.start();
|
||||
if (Platform.isAndroid) {
|
||||
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
Drawer myDrawer({@required BuildContext context}) {
|
||||
Drawer myDrawer({required BuildContext context}) {
|
||||
return Drawer(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
|
|
|
@ -10,8 +10,8 @@ description: Demonstrates how to use the flutter_inappwebview plugin.
|
|||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
||||
flutter: ">=1.10.0 <2.0.0"
|
||||
sdk: ">=2.12.0-0 <3.0.0"
|
||||
flutter: ">=1.22.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
|
@ -19,20 +19,26 @@ dependencies:
|
|||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^0.1.2
|
||||
flutter_downloader: ^1.4.4
|
||||
path_provider: ^1.6.9
|
||||
permission_handler: ^5.0.0+hotfix.6
|
||||
url_launcher: ^5.4.11
|
||||
cupertino_icons: ^1.0.2
|
||||
flutter_downloader: ^1.5.2
|
||||
path_provider: ^1.6.27
|
||||
permission_handler: ^5.0.1+1
|
||||
url_launcher: ^6.0.0-nullsafety.4
|
||||
# connectivity: ^0.4.5+6
|
||||
flutter_inappwebview:
|
||||
path: ../
|
||||
|
||||
dev_dependencies:
|
||||
e2e: "^0.2.0"
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_driver:
|
||||
sdk: flutter
|
||||
test: any
|
||||
# integration_test: ^1.0.2+1
|
||||
integration_test:
|
||||
git:
|
||||
url: https://github.com/flutter/plugins.git
|
||||
path: packages/integration_test
|
||||
pedantic: ^1.8.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://www.dartlang.org/tools/pub/pubspec
|
||||
|
@ -53,6 +59,8 @@ flutter:
|
|||
- assets/css/
|
||||
- assets/images/
|
||||
- assets/favicon.ico
|
||||
- assets/sample_audio.ogg
|
||||
- assets/sample_video.mp4
|
||||
- test_assets/certificate.pfx
|
||||
- test_assets/in_app_webview_initial_file_test.html
|
||||
- test_assets/in_app_webview_on_load_resource_test.html
|
||||
|
@ -64,6 +72,8 @@ flutter:
|
|||
- test_assets/css/
|
||||
- test_assets/images/
|
||||
- test_assets/favicon.ico
|
||||
- test_assets/sample_audio.ogg
|
||||
- test_assets/sample_video.mp4
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
# assets:
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1 +0,0 @@
|
|||
final environment = {"NODE_SERVER_IP":"192.168.1.122"};
|
|
@ -1,11 +0,0 @@
|
|||
import 'package:flutter_driver/driver_extension.dart';
|
||||
import 'main_test.dart' as app;
|
||||
|
||||
void main() {
|
||||
// This line enables the extension.
|
||||
enableFlutterDriverExtension();
|
||||
|
||||
// Call the `main()` function of the app, or call `runApp` with
|
||||
// any widget you are interested in testing.
|
||||
app.main();
|
||||
}
|
|
@ -1,532 +0,0 @@
|
|||
// Imports the Flutter Driver API.
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter_driver/flutter_driver.dart';
|
||||
import 'package:test/test.dart';
|
||||
import '.env.dart';
|
||||
|
||||
void main() {
|
||||
|
||||
group('Flutter InAppWebView', () {
|
||||
FlutterDriver driver;
|
||||
|
||||
// Connect to the Flutter driver before running any tests.
|
||||
setUpAll(() async {
|
||||
driver = await FlutterDriver.connect();
|
||||
await driver.setTextEntryEmulation(enabled: true);
|
||||
});
|
||||
|
||||
// Close the connection to the driver after the tests have completed.
|
||||
tearDownAll(() async {
|
||||
if (driver != null) {
|
||||
driver.close();
|
||||
}
|
||||
});
|
||||
|
||||
test('InAppWebViewInitialUrlTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewInitialFileTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewInitialUrlTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String url = await driver.getText(appBarTitle);
|
||||
expect(url, "https://flutter.dev/");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewInitialFileTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewInitialDataTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewInitialFileTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "true");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewInitialDataTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnProgressChangedTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewInitialDataTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "true");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnProgressChangedTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnScrollChangedTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnProgressChangedTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "true");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnScrollChangedTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnLoadResourceTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnScrollChangedTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "true");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnLoadResourceTest', () async {
|
||||
List<String> resourceList = [
|
||||
"https://getbootstrap.com/docs/4.3/dist/css/bootstrap.min.css",
|
||||
"https://code.jquery.com/jquery-3.3.1.min.js",
|
||||
"https://via.placeholder.com/100x50"
|
||||
];
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewJavaScriptHandlerTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnLoadResourceTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
for (String resource in resourceList) {
|
||||
expect(true, title.contains(resource));
|
||||
}
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewJavaScriptHandlerTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewAjaxTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewJavaScriptHandlerTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(true, !title.contains("false"));
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewAjaxTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewFetchTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewAjaxTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "Lorenzo Pichilli Lorenzo Pichilli");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewFetchTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnLoadResourceCustomSchemeTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewFetchTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(true, title.contains("Lorenzo Pichilli") && title.contains("200"));
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnLoadResourceCustomSchemeTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewShouldOverrideUrlLoadingTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnLoadResourceCustomSchemeTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "true");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewShouldOverrideUrlLoadingTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnConsoleMessageTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewShouldOverrideUrlLoadingTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String url = await driver.getText(appBarTitle);
|
||||
expect(url, "https://flutter.dev/");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnConsoleMessageTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnDownloadStartTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnConsoleMessageTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "message LOG");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnDownloadStartTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnCreateWindowTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnDownloadStartTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String url = await driver.getText(appBarTitle);
|
||||
expect(url, "http://${environment["NODE_SERVER_IP"]}:8082/test-download-file");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnCreateWindowTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnJsDialogTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnCreateWindowTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String url = await driver.getText(appBarTitle);
|
||||
expect(url, "https://flutter.dev/");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnJsDialogTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
final alertButtonOk = find.byValueKey('AlertButtonOk');
|
||||
final confirmButtonCancel = find.byValueKey('ConfirmButtonCancel');
|
||||
final confirmButtonOk = find.byValueKey('ConfirmButtonOk');
|
||||
final promptTextField = find.byValueKey('PromptTextField');
|
||||
final promptButtonCancel = find.byValueKey('PromptButtonCancel');
|
||||
final promptButtonOk = find.byValueKey('PromptButtonOk');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnSafeBrowsingHitTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnJsDialogTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
await driver.tap(alertButtonOk);
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "alert");
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
await driver.tap(confirmButtonOk);
|
||||
|
||||
title = await driver.getText(appBarTitle);
|
||||
expect(title, "confirm true");
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
await driver.tap(promptTextField);
|
||||
await driver.enterText("new value");
|
||||
await driver.waitFor(find.text("new value"));
|
||||
|
||||
await driver.tap(promptButtonOk);
|
||||
|
||||
title = await driver.getText(appBarTitle);
|
||||
expect(title, "prompt new value");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnSafeBrowsingHitTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnReceivedHttpAuthRequestTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnSafeBrowsingHitTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String url = await driver.getText(appBarTitle);
|
||||
if (Platform.isAndroid)
|
||||
expect(url, "chrome://safe-browsing/match?type=malware");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnReceivedHttpAuthRequestTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewSslRequestTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnReceivedHttpAuthRequestTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "Authorized");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewSslRequestTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnFindResultReceivedTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewSslRequestTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "Authorized");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnFindResultReceivedTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnNavigationStateChangeTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnFindResultReceivedTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "2");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnNavigationStateChangeTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnLoadErrorTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnNavigationStateChangeTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(true, title.contains("first-push") && title.contains("second-push"));
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnLoadErrorTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewOnLoadHttpErrorTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnLoadErrorTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
if (Platform.isAndroid) {
|
||||
expect(title, "-2");
|
||||
} else if (Platform.isIOS) {
|
||||
expect(title, "-1022");
|
||||
}
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewOnLoadHttpErrorTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewCookieManagerTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewOnLoadHttpErrorTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "404");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewCookieManagerTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewHttpAuthCredentialDatabaseTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewCookieManagerTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "myValue true true");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewHttpAuthCredentialDatabaseTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
final sideMenuButton = find.byValueKey('SideMenu');
|
||||
final listTiles = find.byValueKey('ListTiles');
|
||||
final nextTest = find.byValueKey('InAppWebViewContentBlockerTest');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewHttpAuthCredentialDatabaseTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "Authorized true true");
|
||||
|
||||
await driver.tap(sideMenuButton);
|
||||
await driver.scrollUntilVisible(listTiles, nextTest, dyScroll: -300.0);
|
||||
await driver.tap(nextTest);
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
test('InAppWebViewContentBlockerTest', () async {
|
||||
final appBarTitle = find.byValueKey('AppBarTitle');
|
||||
|
||||
while((await driver.getText(appBarTitle)) == "InAppWebViewContentBlockerTest") {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
String title = await driver.getText(appBarTitle);
|
||||
expect(title, "true");
|
||||
}, timeout: new Timeout(new Duration(minutes: 5)));
|
||||
|
||||
});
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
class WidgetTest extends StatefulWidget {
|
||||
final WidgetTestState state = WidgetTestState();
|
||||
|
||||
WidgetTest({Key key}): super(key: key);
|
||||
|
||||
@override
|
||||
WidgetTestState createState() {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
class WidgetTestState extends State<WidgetTest> {
|
||||
final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||
InAppWebViewController webView;
|
||||
String appBarTitle;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main_test.dart';
|
||||
import 'custom_widget_test.dart';
|
||||
import '.env.dart';
|
||||
|
||||
class InAppWebViewAjaxTest extends WidgetTest {
|
||||
final InAppWebViewAjaxTestState state = InAppWebViewAjaxTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewAjaxTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewAjaxTestState extends WidgetTestState {
|
||||
String appBarTitle = "InAppWebViewAjaxTest";
|
||||
int totTests = 2;
|
||||
int testsDone = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>InAppWebViewAjaxTest</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>InAppWebViewAjaxTest</h1>
|
||||
<script>
|
||||
window.addEventListener('flutterInAppWebViewPlatformReady', function(event) {
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.open("POST", "http://${environment["NODE_SERVER_IP"]}:8082/test-ajax-post");
|
||||
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
xhttp.send("firstname=Foo&lastname=Bar");
|
||||
|
||||
var xhttp2 = new XMLHttpRequest();
|
||||
xhttp2.open("GET", "http://${environment["NODE_SERVER_IP"]}:8082/test-download-file");
|
||||
xhttp2.send();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""),
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
useShouldInterceptAjaxRequest: true,
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
shouldInterceptAjaxRequest: (InAppWebViewController controller, AjaxRequest ajaxRequest) async {
|
||||
if (ajaxRequest.url.endsWith("/test-ajax-post")) {
|
||||
ajaxRequest.responseType = 'json';
|
||||
ajaxRequest.data = "firstname=Lorenzo&lastname=Pichilli";
|
||||
}
|
||||
return ajaxRequest;
|
||||
},
|
||||
onAjaxReadyStateChange: (InAppWebViewController controller, AjaxRequest ajaxRequest) async {
|
||||
if (ajaxRequest.readyState == AjaxRequestReadyState.DONE && ajaxRequest.status == 200 && ajaxRequest.url.endsWith("/test-ajax-post")) {
|
||||
Map<String, Object> res = ajaxRequest.response;
|
||||
appBarTitle = (appBarTitle == "InAppWebViewAjaxTest") ? res['fullname'] : appBarTitle + " " + res['fullname'];
|
||||
updateCountTest(context: context);
|
||||
}
|
||||
return AjaxRequestAction.PROCEED;
|
||||
},
|
||||
onAjaxProgress: (InAppWebViewController controller, AjaxRequest ajaxRequest) async {
|
||||
if (ajaxRequest.event.type == AjaxRequestEventType.LOAD && ajaxRequest.url.endsWith("/test-ajax-post")) {
|
||||
Map<String, Object> res = ajaxRequest.response;
|
||||
appBarTitle = (appBarTitle == "InAppWebViewAjaxTest") ? res['fullname'] : appBarTitle + " " + res['fullname'];
|
||||
updateCountTest(context: context);
|
||||
}
|
||||
return AjaxRequestAction.PROCEED;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void updateCountTest({@required BuildContext context}) {
|
||||
testsDone++;
|
||||
if (testsDone == totTests) {
|
||||
setState(() { });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'custom_widget_test.dart';
|
||||
import 'main_test.dart';
|
||||
|
||||
class InAppWebViewContentBlockerTest extends WidgetTest {
|
||||
final InAppWebViewContentBlockerTestState state = InAppWebViewContentBlockerTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewContentBlockerTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewContentBlockerTestState extends WidgetTestState {
|
||||
|
||||
String appBarTitle = "InAppWebViewContentBlockerTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
contentBlockers: [
|
||||
ContentBlocker(
|
||||
trigger: ContentBlockerTrigger(
|
||||
urlFilter: ".*",
|
||||
resourceType: [
|
||||
ContentBlockerTriggerResourceType.IMAGE,
|
||||
ContentBlockerTriggerResourceType.STYLE_SHEET
|
||||
],
|
||||
ifTopUrl: [
|
||||
"https://flutter.dev/"
|
||||
]),
|
||||
action: ContentBlockerAction(
|
||||
type: ContentBlockerActionType.BLOCK))
|
||||
]
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
setState(() {
|
||||
appBarTitle = "true";
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'custom_widget_test.dart';
|
||||
import 'main_test.dart';
|
||||
|
||||
class InAppWebViewCookieManagerTest extends WidgetTest {
|
||||
final InAppWebViewCookieManagerTestState state = InAppWebViewCookieManagerTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewCookieManagerTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewCookieManagerTestState extends WidgetTestState {
|
||||
|
||||
String appBarTitle = "InAppWebViewCookieManagerTest";
|
||||
CookieManager cookieManager = CookieManager.instance();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) async {
|
||||
var title = "";
|
||||
await cookieManager.getCookies(url: url);
|
||||
await cookieManager.setCookie(url: url, name: "myCookie", value: "myValue");
|
||||
Cookie cookie = await cookieManager.getCookie(url: url, name: "myCookie");
|
||||
title = cookie.value.toString();
|
||||
await cookieManager.deleteCookie(url: url, name: "myCookie");
|
||||
cookie = await cookieManager.getCookie(url: url, name: "myCookie");
|
||||
title += " " + ((cookie == null) ? "true" : "false");
|
||||
await cookieManager.deleteCookies(url: url);
|
||||
List<Cookie> cookies = await cookieManager.getCookies(url: url);
|
||||
title += " " + ((cookies.length == 0) ? "true" : "false");
|
||||
|
||||
setState(() {
|
||||
appBarTitle = title;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main_test.dart';
|
||||
import 'custom_widget_test.dart';
|
||||
import '.env.dart';
|
||||
|
||||
class InAppWebViewFetchTest extends WidgetTest {
|
||||
final InAppWebViewFetchTestState state = InAppWebViewFetchTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewFetchTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewFetchTestState extends WidgetTestState {
|
||||
String appBarTitle = "InAppWebViewFetchTest";
|
||||
int totTests = 2;
|
||||
int testsDone = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>InAppWebViewFetchTest</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>InAppWebViewFetchTest</h1>
|
||||
<script>
|
||||
window.addEventListener('flutterInAppWebViewPlatformReady', function(event) {
|
||||
fetch(new Request("http://${environment["NODE_SERVER_IP"]}:8082/test-download-file")).then(function(response) {
|
||||
window.flutter_inappwebview.callHandler('fetchGet', response.status);
|
||||
}).catch(function(error) {
|
||||
window.flutter_inappwebview.callHandler('fetchGet', "ERROR: " + error);
|
||||
});
|
||||
|
||||
fetch("http://${environment["NODE_SERVER_IP"]}:8082/test-ajax-post", {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
firstname: 'Foo',
|
||||
lastname: 'Bar'
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then(function(response) {
|
||||
response.json().then(function(value) {
|
||||
window.flutter_inappwebview.callHandler('fetchPost', value);
|
||||
}).catch(function(error) {
|
||||
window.flutter_inappwebview.callHandler('fetchPost', "ERROR: " + error);
|
||||
});
|
||||
}).catch(function(error) {
|
||||
window.flutter_inappwebview.callHandler('fetchPost', "ERROR: " + error);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""),
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
useShouldInterceptFetchRequest: true,
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
|
||||
webView.addJavaScriptHandler(handlerName: "fetchGet", callback: (args) {
|
||||
appBarTitle = (appBarTitle == "InAppWebViewFetchTest") ? args[0].toString() : appBarTitle + " " + args[0].toString();
|
||||
updateCountTest(context: context);
|
||||
});
|
||||
|
||||
webView.addJavaScriptHandler(handlerName: "fetchPost", callback: (args) {
|
||||
appBarTitle = (appBarTitle == "InAppWebViewFetchTest") ? args[0]["fullname"] : appBarTitle + " " + args[0]["fullname"];
|
||||
updateCountTest(context: context);
|
||||
});
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
shouldInterceptFetchRequest: (InAppWebViewController controller, FetchRequest fetchRequest) async {
|
||||
if (fetchRequest.url.endsWith("/test-ajax-post")) {
|
||||
fetchRequest.body = utf8.encode("""{
|
||||
"firstname": "Lorenzo",
|
||||
"lastname": "Pichilli"
|
||||
}
|
||||
""");
|
||||
}
|
||||
return fetchRequest;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void updateCountTest({@required BuildContext context}) {
|
||||
testsDone++;
|
||||
if (testsDone == totTests) {
|
||||
setState(() { });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'custom_widget_test.dart';
|
||||
import 'main_test.dart';
|
||||
import '.env.dart';
|
||||
|
||||
class InAppWebViewHttpAuthCredentialDatabaseTest extends WidgetTest {
|
||||
final InAppWebViewHttpAuthCredentialDatabaseTestState state = InAppWebViewHttpAuthCredentialDatabaseTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewHttpAuthCredentialDatabaseTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewHttpAuthCredentialDatabaseTestState extends WidgetTestState {
|
||||
|
||||
String appBarTitle = "InAppWebViewHttpAuthCredentialDatabaseTest";
|
||||
HttpAuthCredentialDatabase httpAuthCredentialDatabase = HttpAuthCredentialDatabase.instance();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
httpAuthCredentialDatabase.setHttpAuthCredential(
|
||||
protectionSpace: ProtectionSpace(host: environment["NODE_SERVER_IP"], protocol: "http", realm: "Node", port: 8081),
|
||||
credential: HttpAuthCredential(username: "USERNAME", password: "PASSWORD")
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialUrl: "http://${environment["NODE_SERVER_IP"]}:8081/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) async {
|
||||
var title = "";
|
||||
String h1Content = await controller.evaluateJavascript(source: "document.body.querySelector('h1').textContent");
|
||||
title = h1Content;
|
||||
var credentials = await httpAuthCredentialDatabase.getHttpAuthCredentials(protectionSpace:
|
||||
ProtectionSpace(host: environment["NODE_SERVER_IP"], protocol: "http", realm: "Node", port: 8081)
|
||||
);
|
||||
title += " " + ((credentials.length == 1) ? "true" : "false");
|
||||
await httpAuthCredentialDatabase.clearAllAuthCredentials();
|
||||
credentials = await httpAuthCredentialDatabase.getHttpAuthCredentials(protectionSpace:
|
||||
ProtectionSpace(host: environment["NODE_SERVER_IP"], protocol: "http", realm: "Node", port: 8081)
|
||||
);
|
||||
title += " " + ((credentials.length == 0) ? "true" : "false");
|
||||
setState(() {
|
||||
appBarTitle = title;
|
||||
});
|
||||
},
|
||||
onReceivedHttpAuthRequest: (InAppWebViewController controller, HttpAuthChallenge challenge) async {
|
||||
return new HttpAuthResponse(action: HttpAuthResponseAction.USE_SAVED_HTTP_AUTH_CREDENTIALS);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main_test.dart';
|
||||
import 'custom_widget_test.dart';
|
||||
|
||||
class InAppWebViewInitialDataTest extends WidgetTest {
|
||||
final InAppWebViewInitialDataTestState state = InAppWebViewInitialDataTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewInitialDataTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewInitialDataTestState extends WidgetTestState {
|
||||
String appBarTitle = "InAppWebViewInitialDataTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>InAppWebViewInitialDataTest</title>
|
||||
<link rel="stylesheet" href="https://getbootstrap.com/docs/4.3/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
</head>
|
||||
<body class="text-center">
|
||||
<div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column">
|
||||
<header class="masthead mb-auto">
|
||||
<div class="inner">
|
||||
<h3 class="masthead-brand">InAppWebViewInitialDataTest</h3>
|
||||
<nav class="nav nav-masthead justify-content-center">
|
||||
<a class="nav-link active" href="index.html">Home</a>
|
||||
<a class="nav-link" href="page-1.html">Page 1</a>
|
||||
<a class="nav-link" href="page-2.html">Page 2</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main role="main" class="inner cover">
|
||||
<h1 class="cover-heading">InAppWebViewInitialFileTest</h1>
|
||||
<img src="images/flutter-logo.svg" alt="flutter logo">
|
||||
<p>
|
||||
<img src="https://via.placeholder.com/100x50" alt="placeholder 100x50">
|
||||
</p>
|
||||
<a id="link" href="https://github.com/pichillilorenzo/flutter_inappwebview">flutter_inappwebview</a>
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""),
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
setState(() {
|
||||
appBarTitle = "true";
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main_test.dart';
|
||||
import 'custom_widget_test.dart';
|
||||
|
||||
class InAppWebViewInitialFileTest extends WidgetTest {
|
||||
final InAppWebViewInitialFileTestState state = InAppWebViewInitialFileTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewInitialFileTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewInitialFileTestState extends WidgetTestState {
|
||||
String appBarTitle = "InAppWebViewInitialFileTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_initial_file_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
setState(() {
|
||||
appBarTitle = "true";
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'custom_widget_test.dart';
|
||||
import 'main_test.dart';
|
||||
|
||||
class InAppWebViewInitialUrlTest extends WidgetTest {
|
||||
final InAppWebViewInitialUrlTestState state = InAppWebViewInitialUrlTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewInitialUrlTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewInitialUrlTestState extends WidgetTestState {
|
||||
|
||||
String appBarTitle = "InAppWebViewInitialUrlTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
setState(() {
|
||||
appBarTitle = url;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main_test.dart';
|
||||
import 'custom_widget_test.dart';
|
||||
|
||||
class Foo {
|
||||
String bar;
|
||||
String baz;
|
||||
|
||||
Foo({this.bar, this.baz});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'bar': this.bar,
|
||||
'baz': this.baz
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class InAppWebViewJavaScriptHandlerTest extends WidgetTest {
|
||||
final InAppWebViewJavaScriptHandlerTestState state = InAppWebViewJavaScriptHandlerTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewJavaScriptHandlerTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewJavaScriptHandlerTestState extends WidgetTestState {
|
||||
|
||||
String appBarTitle = "InAppWebViewJavaScriptHandlerTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_javascript_handler_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
|
||||
controller.addJavaScriptHandler(handlerName:'handlerFoo', callback: (args) {
|
||||
appBarTitle = (args.length == 0).toString();
|
||||
return Foo(bar: 'bar_value', baz: 'baz_value');
|
||||
});
|
||||
|
||||
controller.addJavaScriptHandler(handlerName: 'handlerFooWithArgs', callback: (args) {
|
||||
appBarTitle += " " + (args[0] is int).toString();
|
||||
appBarTitle += " " + (args[1] is bool).toString();
|
||||
appBarTitle += " " + (args[2] is List).toString();
|
||||
appBarTitle += " " + (args[2] is List).toString();
|
||||
appBarTitle += " " + (args[3] is Map).toString();
|
||||
appBarTitle += " " + (args[4] is Map).toString();
|
||||
setState(() { });
|
||||
});
|
||||
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main_test.dart';
|
||||
import 'custom_widget_test.dart';
|
||||
|
||||
class InAppWebViewOnConsoleMessageTest extends WidgetTest {
|
||||
final InAppWebViewOnConsoleMessageTestState state = InAppWebViewOnConsoleMessageTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnConsoleMessageTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnConsoleMessageTestState extends WidgetTestState {
|
||||
String appBarTitle = "InAppWebViewOnConsoleMessageTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_on_console_message_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onConsoleMessage: (InAppWebViewController controller, ConsoleMessage consoleMessage) {
|
||||
setState(() {
|
||||
appBarTitle = consoleMessage.message + " " + consoleMessage.messageLevel.toString();
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main_test.dart';
|
||||
import 'custom_widget_test.dart';
|
||||
|
||||
class InAppWebViewOnCreateWindowTest extends WidgetTest {
|
||||
final InAppWebViewOnCreateWindowTestState state = InAppWebViewOnCreateWindowTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnCreateWindowTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnCreateWindowTestState extends WidgetTestState {
|
||||
String appBarTitle = "InAppWebViewOnCreateWindowTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_on_create_window_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
javaScriptCanOpenWindowsAutomatically: true,
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
if (url == "https://flutter.dev/") {
|
||||
setState(() {
|
||||
appBarTitle = url;
|
||||
});
|
||||
}
|
||||
},
|
||||
onCreateWindow: (InAppWebViewController controller, CreateWindowRequest createWindowRequest) async {
|
||||
controller.loadUrl(url: createWindowRequest.url);
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main_test.dart';
|
||||
import 'custom_widget_test.dart';
|
||||
import '.env.dart';
|
||||
|
||||
class InAppWebViewOnDownloadStartTest extends WidgetTest {
|
||||
final InAppWebViewOnDownloadStartTestState state = InAppWebViewOnDownloadStartTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnDownloadStartTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnDownloadStartTestState extends WidgetTestState {
|
||||
String appBarTitle = "InAppWebViewOnDownloadStartTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>InAppWebViewOnDownloadStartTest</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>InAppWebViewOnDownloadStartTest</h1>
|
||||
<a id="download-file" href="http://${environment["NODE_SERVER_IP"]}:8082/test-download-file">download file</a>
|
||||
<script>
|
||||
window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
|
||||
document.querySelector("#download-file").click();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""),
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
useOnDownloadStart: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onDownloadStart: (InAppWebViewController controller, String url) {
|
||||
setState(() {
|
||||
appBarTitle = url;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main_test.dart';
|
||||
import 'custom_widget_test.dart';
|
||||
|
||||
class InAppWebViewOnFindResultReceivedTest extends WidgetTest {
|
||||
final InAppWebViewOnFindResultReceivedTestState state = InAppWebViewOnFindResultReceivedTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnFindResultReceivedTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnFindResultReceivedTestState extends WidgetTestState {
|
||||
String appBarTitle = "InAppWebViewOnFindResultReceivedTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_initial_file_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
controller.findAllAsync(find: "InAppWebViewInitialFileTest");
|
||||
},
|
||||
onFindResultReceived: (InAppWebViewController controller, int activeMatchOrdinal, int numberOfMatches, bool isDoneCounting) async {
|
||||
if (isDoneCounting) {
|
||||
setState(() {
|
||||
appBarTitle = numberOfMatches.toString();
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,199 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main_test.dart';
|
||||
import 'custom_widget_test.dart';
|
||||
|
||||
class InAppWebViewOnJsDialogTest extends WidgetTest {
|
||||
final InAppWebViewOnJsDialogTestState state = InAppWebViewOnJsDialogTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnJsDialogTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnJsDialogTestState extends WidgetTestState {
|
||||
String appBarTitle = "InAppWebViewOnJsDialogTest";
|
||||
|
||||
TextEditingController _textFieldController = TextEditingController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
_textFieldController.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_on_js_dialog_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
|
||||
controller.addJavaScriptHandler(handlerName: 'confirm', callback: (args) {
|
||||
setState(() {
|
||||
appBarTitle = "confirm " + ((args[0] is bool && args[0]) ? "true" : "false");
|
||||
});
|
||||
});
|
||||
|
||||
controller.addJavaScriptHandler(handlerName: 'prompt', callback: (args) {
|
||||
setState(() {
|
||||
appBarTitle = "prompt " + args[0];
|
||||
});
|
||||
});
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
setState(() {
|
||||
appBarTitle = "loaded";
|
||||
});
|
||||
},
|
||||
onJsAlert:
|
||||
(InAppWebViewController controller, JsAlertRequest jsAlertRequest) async {
|
||||
JsAlertResponseAction action =
|
||||
await createAlertDialog(context, jsAlertRequest.message);
|
||||
return JsAlertResponse(
|
||||
handledByClient: true, action: action);
|
||||
},
|
||||
onJsConfirm:
|
||||
(InAppWebViewController controller, JsConfirmRequest jsConfirmRequest) async {
|
||||
JsConfirmResponseAction action =
|
||||
await createConfirmDialog(context, jsConfirmRequest.message);
|
||||
return JsConfirmResponse(
|
||||
handledByClient: true, action: action);
|
||||
},
|
||||
onJsPrompt: (InAppWebViewController controller, JsPromptRequest jsPromptRequest) async {
|
||||
_textFieldController.text = jsPromptRequest.defaultValue;
|
||||
JsPromptResponseAction action =
|
||||
await createPromptDialog(context, jsPromptRequest.message);
|
||||
return JsPromptResponse(
|
||||
handledByClient: true,
|
||||
action: action,
|
||||
value: _textFieldController.text);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Future<JsAlertResponseAction> createAlertDialog(
|
||||
BuildContext context, String message) async {
|
||||
JsAlertResponseAction action;
|
||||
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
content: Text(message),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
child: Text("Ok"),
|
||||
key: Key("AlertButtonOk"),
|
||||
onPressed: () {
|
||||
action = JsAlertResponseAction.CONFIRM;
|
||||
Navigator.of(context).pop();
|
||||
setState(() {
|
||||
appBarTitle = "alert";
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
Future<JsConfirmResponseAction> createConfirmDialog(
|
||||
BuildContext context, String message) async {
|
||||
JsConfirmResponseAction action;
|
||||
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
content: Text(message),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
child: Text("Cancel"),
|
||||
key: Key("ConfirmButtonCancel"),
|
||||
onPressed: () {
|
||||
action = JsConfirmResponseAction.CANCEL;
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
FlatButton(
|
||||
child: Text("Ok"),
|
||||
key: Key("ConfirmButtonOk"),
|
||||
onPressed: () {
|
||||
action = JsConfirmResponseAction.CONFIRM;
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
Future<JsPromptResponseAction> createPromptDialog(
|
||||
BuildContext context, String message) async {
|
||||
JsPromptResponseAction action;
|
||||
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(message),
|
||||
content: TextField(
|
||||
key: Key("PromptTextField"),
|
||||
controller: _textFieldController,
|
||||
),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
child: Text("Cancel"),
|
||||
key: Key("PromptButtonCancel"),
|
||||
onPressed: () {
|
||||
action = JsPromptResponseAction.CANCEL;
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
FlatButton(
|
||||
child: Text("Ok"),
|
||||
key: Key("PromptButtonOk"),
|
||||
onPressed: () {
|
||||
action = JsPromptResponseAction.CONFIRM;
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return action;
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'custom_widget_test.dart';
|
||||
import 'main_test.dart';
|
||||
|
||||
class InAppWebViewOnLoadErrorTest extends WidgetTest {
|
||||
final InAppWebViewOnLoadErrorTestState state = InAppWebViewOnLoadErrorTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnLoadErrorTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnLoadErrorTestState extends WidgetTestState {
|
||||
|
||||
String appBarTitle = "InAppWebViewOnLoadErrorTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialUrl: "https://not-existing-domain.org/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadError: (InAppWebViewController controller, String url, int code, String message) async {
|
||||
setState(() {
|
||||
appBarTitle = code.toString();
|
||||
});
|
||||
}
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'custom_widget_test.dart';
|
||||
import 'main_test.dart';
|
||||
|
||||
class InAppWebViewOnLoadHttpErrorTest extends WidgetTest {
|
||||
final InAppWebViewOnLoadHttpErrorTestState state = InAppWebViewOnLoadHttpErrorTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnLoadHttpErrorTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnLoadHttpErrorTestState extends WidgetTestState {
|
||||
|
||||
String appBarTitle = "InAppWebViewOnLoadHttpErrorTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialUrl: "https://google.com/404",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadHttpError: (InAppWebViewController controller, String url, int statusCode, String description) async {
|
||||
setState(() {
|
||||
appBarTitle = statusCode.toString();
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main_test.dart';
|
||||
import 'custom_widget_test.dart';
|
||||
|
||||
class InAppWebViewOnLoadResourceCustomSchemeTest extends WidgetTest {
|
||||
final InAppWebViewOnLoadResourceCustomSchemeTestState state = InAppWebViewOnLoadResourceCustomSchemeTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnLoadResourceCustomSchemeTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnLoadResourceCustomSchemeTestState extends WidgetTestState {
|
||||
String appBarTitle = "InAppWebViewOnLoadResourceCustomSchemeTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_on_load_resource_custom_scheme_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
resourceCustomSchemes: ["my-special-custom-scheme"]
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
|
||||
webView.addJavaScriptHandler(handlerName: "imageLoaded", callback: (args) {
|
||||
setState(() {
|
||||
appBarTitle = "true";
|
||||
});
|
||||
});
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadResourceCustomScheme: (InAppWebViewController controller, String scheme, String url) async {
|
||||
if (scheme == "my-special-custom-scheme") {
|
||||
var bytes = await rootBundle.load("test_assets/" + url.replaceFirst("my-special-custom-scheme://", "", 0));
|
||||
var response = CustomSchemeResponse(data: bytes.buffer.asUint8List(), contentType: "image/svg+xml", contentEnconding: "utf-8");
|
||||
return response;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main_test.dart';
|
||||
import 'custom_widget_test.dart';
|
||||
|
||||
class InAppWebViewOnLoadResourceTest extends WidgetTest {
|
||||
final InAppWebViewOnLoadResourceTestState state = InAppWebViewOnLoadResourceTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnLoadResourceTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnLoadResourceTestState extends WidgetTestState {
|
||||
List<String> resourceList = [
|
||||
"https://getbootstrap.com/docs/4.3/dist/css/bootstrap.min.css",
|
||||
"https://code.jquery.com/jquery-3.3.1.min.js",
|
||||
"https://via.placeholder.com/100x50"
|
||||
];
|
||||
int countResources = 0;
|
||||
String appBarTitle = "InAppWebViewOnLoadResourceTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_on_load_resource_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
useOnLoadResource: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadResource: (InAppWebViewController controller, LoadedResource response) {
|
||||
appBarTitle = (appBarTitle == "InAppWebViewOnLoadResourceTest") ? response.url : appBarTitle + " " + response.url;
|
||||
countResources++;
|
||||
if (countResources == resourceList.length) {
|
||||
setState(() { });
|
||||
}
|
||||
}
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main_test.dart';
|
||||
import 'custom_widget_test.dart';
|
||||
|
||||
class InAppWebViewOnNavigationStateChangeTest extends WidgetTest {
|
||||
final InAppWebViewOnNavigationStateChangeTestState state = InAppWebViewOnNavigationStateChangeTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnNavigationStateChangeTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnNavigationStateChangeTestState extends WidgetTestState {
|
||||
String appBarTitle = "InAppWebViewOnNavigationStateChangeTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
controller.evaluateJavascript(source: """
|
||||
var state = {}
|
||||
var title = ''
|
||||
var url = 'first-push';
|
||||
history.pushState(state, title, url);
|
||||
|
||||
setTimeout(function() {
|
||||
var url = 'second-push';
|
||||
history.pushState(state, title, url);
|
||||
}, 100);
|
||||
""");
|
||||
},
|
||||
onUpdateVisitedHistory: (InAppWebViewController controller, String url, bool androidIsReload) async {
|
||||
if (url.endsWith("second-push")) {
|
||||
setState(() {
|
||||
appBarTitle += " " + url;
|
||||
});
|
||||
} else {
|
||||
appBarTitle = url;
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'custom_widget_test.dart';
|
||||
import 'main_test.dart';
|
||||
|
||||
class InAppWebViewOnProgressChangedTest extends WidgetTest {
|
||||
final InAppWebViewOnProgressChangedTestState state = InAppWebViewOnProgressChangedTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnProgressChangedTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnProgressChangedTestState extends WidgetTestState {
|
||||
|
||||
String appBarTitle = "InAppWebViewOnProgressChangedTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onProgressChanged: (InAppWebViewController controller, int progress) {
|
||||
if (progress == 100) {
|
||||
setState(() {
|
||||
appBarTitle = "true";
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'custom_widget_test.dart';
|
||||
import 'main_test.dart';
|
||||
import '.env.dart';
|
||||
|
||||
class InAppWebViewOnReceivedHttpAuthRequestTest extends WidgetTest {
|
||||
final InAppWebViewOnReceivedHttpAuthRequestTestState state = InAppWebViewOnReceivedHttpAuthRequestTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnReceivedHttpAuthRequestTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnReceivedHttpAuthRequestTestState extends WidgetTestState {
|
||||
|
||||
String appBarTitle = "InAppWebViewOnReceivedHttpAuthRequestTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialUrl: "http://${environment["NODE_SERVER_IP"]}:8081/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) async {
|
||||
String h1Content = await controller.evaluateJavascript(source: "document.body.querySelector('h1').textContent");
|
||||
setState(() {
|
||||
appBarTitle = h1Content;
|
||||
});
|
||||
},
|
||||
onReceivedHttpAuthRequest: (InAppWebViewController controller, HttpAuthChallenge challenge) async {
|
||||
return new HttpAuthResponse(
|
||||
username: "USERNAME",
|
||||
password: "PASSWORD",
|
||||
action: HttpAuthResponseAction.PROCEED,
|
||||
permanentPersistence: true);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'custom_widget_test.dart';
|
||||
import 'main_test.dart';
|
||||
|
||||
class InAppWebViewOnSafeBrowsingHitTest extends WidgetTest {
|
||||
final InAppWebViewOnSafeBrowsingHitTestState state = InAppWebViewOnSafeBrowsingHitTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnSafeBrowsingHitTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnSafeBrowsingHitTestState extends WidgetTestState {
|
||||
|
||||
String appBarTitle = "InAppWebViewOnSafeBrowsingHitTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialUrl: (Platform.isAndroid) ? "chrome://safe-browsing/match?type=malware" : "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
// if I set javaScriptEnabled to true, it will crash!
|
||||
javaScriptEnabled: false,
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
),
|
||||
android: AndroidInAppWebViewOptions(
|
||||
safeBrowsingEnabled: true,
|
||||
),
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
if(Platform.isAndroid)
|
||||
controller.android.startSafeBrowsing();
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
setState(() {
|
||||
appBarTitle = url;
|
||||
});
|
||||
},
|
||||
androidOnSafeBrowsingHit: (InAppWebViewController controller, String url, SafeBrowsingThreat threatType) async {
|
||||
return SafeBrowsingResponse(report: true, action: SafeBrowsingResponseAction.PROCEED);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'custom_widget_test.dart';
|
||||
import 'main_test.dart';
|
||||
|
||||
class InAppWebViewOnScrollChangedTest extends WidgetTest {
|
||||
final InAppWebViewOnScrollChangedTestState state = InAppWebViewOnScrollChangedTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewOnScrollChangedTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewOnScrollChangedTestState extends WidgetTestState {
|
||||
|
||||
String appBarTitle = "InAppWebViewOnScrollChangedTest";
|
||||
bool scrolled = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
controller.scrollTo(x: 0, y: 500);
|
||||
},
|
||||
onScrollChanged: (InAppWebViewController controller, int x, int y) {
|
||||
if (!scrolled) {
|
||||
scrolled = true;
|
||||
setState(() {
|
||||
appBarTitle = "true";
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'dart:io' show Platform;
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'custom_widget_test.dart';
|
||||
import 'main_test.dart';
|
||||
|
||||
class InAppWebViewShouldOverrideUrlLoadingTest extends WidgetTest {
|
||||
final InAppWebViewShouldOverrideUrlLoadingTestState state = InAppWebViewShouldOverrideUrlLoadingTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewShouldOverrideUrlLoadingTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewShouldOverrideUrlLoadingTestState extends WidgetTestState {
|
||||
String appBarTitle = "InAppWebViewShouldOverrideUrlLoadingTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_initial_file_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
useShouldOverrideUrlLoading: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) {
|
||||
if (url == "https://flutter.dev/") {
|
||||
setState(() {
|
||||
appBarTitle = url;
|
||||
});
|
||||
} else {
|
||||
controller.evaluateJavascript(source: "document.querySelector('#link').click();");
|
||||
}
|
||||
},
|
||||
shouldOverrideUrlLoading: (InAppWebViewController controller, ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest) async {
|
||||
if (Platform.isAndroid || shouldOverrideUrlLoadingRequest.iosWKNavigationType == IOSWKNavigationType.LINK_ACTIVATED) {
|
||||
await controller.loadUrl(url: "https://flutter.dev/");
|
||||
return ShouldOverrideUrlLoadingAction.CANCEL;
|
||||
}
|
||||
return ShouldOverrideUrlLoadingAction.ALLOW;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'custom_widget_test.dart';
|
||||
import 'main_test.dart';
|
||||
import '.env.dart';
|
||||
|
||||
class InAppWebViewSslRequestTest extends WidgetTest {
|
||||
final InAppWebViewSslRequestTestState state = InAppWebViewSslRequestTestState();
|
||||
|
||||
@override
|
||||
InAppWebViewSslRequestTestState createState() => state;
|
||||
}
|
||||
|
||||
class InAppWebViewSslRequestTestState extends WidgetTestState {
|
||||
|
||||
String appBarTitle = "InAppWebViewSslRequestTest";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: this.scaffoldKey,
|
||||
appBar: myAppBar(state: this, title: appBarTitle),
|
||||
drawer: myDrawer(context: context),
|
||||
body: Container(
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialUrl: "https://${environment["NODE_SERVER_IP"]}:4433/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
)
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (InAppWebViewController controller, String url) {
|
||||
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) async {
|
||||
String h1Content = await controller.evaluateJavascript(source: "document.body.querySelector('h1').textContent");
|
||||
setState(() {
|
||||
appBarTitle = h1Content;
|
||||
});
|
||||
},
|
||||
onReceivedServerTrustAuthRequest: (InAppWebViewController controller, ServerTrustChallenge challenge) async {
|
||||
return new ServerTrustAuthResponse(action: ServerTrustAuthResponseAction.PROCEED);
|
||||
},
|
||||
onReceivedClientCertRequest: (InAppWebViewController controller, ClientCertChallenge challenge) async {
|
||||
return new ClientCertResponse(
|
||||
certificatePath: "test_assets/certificate.pfx",
|
||||
certificatePassword: "",
|
||||
androidKeyStoreType: "PKCS12",
|
||||
action: ClientCertResponseAction.PROCEED);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// @dart = 2.9
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:flutter_driver/flutter_driver.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
final FlutterDriver driver = await FlutterDriver.connect();
|
||||
final String data =
|
||||
await driver.requestData(null, timeout: const Duration(minutes: 1));
|
||||
await driver.close();
|
||||
final Map<String, dynamic> result = jsonDecode(data);
|
||||
exit(result['result'] == 'true' ? 0 : 1);
|
||||
}
|
|
@ -1,153 +0,0 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'custom_widget_test.dart';
|
||||
import 'in_app_webview_ajax_test.dart';
|
||||
import 'in_app_webview_content_blocker_test.dart';
|
||||
import 'in_app_webview_cookie_manager_test.dart';
|
||||
import 'in_app_webview_fetch_test.dart';
|
||||
import 'in_app_webview_http_auth_credential_database_test.dart';
|
||||
import 'in_app_webview_initial_data_test.dart';
|
||||
import 'in_app_webview_initial_file_test.dart';
|
||||
import 'in_app_webview_initial_url_test.dart';
|
||||
import 'in_app_webview_javascript_handler_test.dart';
|
||||
import 'in_app_webview_on_console_message_test.dart';
|
||||
import 'in_app_webview_on_download_start_test.dart';
|
||||
import 'in_app_webview_on_find_result_received_test.dart';
|
||||
import 'in_app_webview_on_js_dialog_test.dart';
|
||||
import 'in_app_webview_on_load_error_test.dart';
|
||||
import 'in_app_webview_on_load_http_error_test.dart';
|
||||
import 'in_app_webview_on_load_resource_custom_scheme_test.dart';
|
||||
import 'in_app_webview_on_load_resource_test.dart';
|
||||
import 'in_app_webview_on_navigation_state_change_test.dart';
|
||||
import 'in_app_webview_on_progress_changed_test.dart';
|
||||
import 'in_app_webview_on_received_http_auth_request_test.dart';
|
||||
import 'in_app_webview_on_safe_browsing_hit_test.dart';
|
||||
import 'in_app_webview_on_scroll_changed_test.dart';
|
||||
import 'in_app_webview_on_create_window_test.dart';
|
||||
import 'in_app_webview_should_override_url_loading_test.dart';
|
||||
import 'in_app_webview_ssl_request_test.dart';
|
||||
|
||||
Map<String, WidgetBuilder> getTestRoutes({@required BuildContext context}) {
|
||||
var routes = {
|
||||
'/': (context) => InAppWebViewInitialUrlTest(),
|
||||
'/InAppWebViewInitialFileTest': (context) => InAppWebViewInitialFileTest(),
|
||||
'/InAppWebViewInitialDataTest': (context) => InAppWebViewInitialDataTest(),
|
||||
'/InAppWebViewOnProgressChangedTest': (context) => InAppWebViewOnProgressChangedTest(),
|
||||
'/InAppWebViewOnScrollChangedTest': (context) => InAppWebViewOnScrollChangedTest(),
|
||||
'/InAppWebViewOnLoadResourceTest': (context) => InAppWebViewOnLoadResourceTest(),
|
||||
'/InAppWebViewJavaScriptHandlerTest': (context) => InAppWebViewJavaScriptHandlerTest(),
|
||||
'/InAppWebViewAjaxTest': (context) => InAppWebViewAjaxTest(),
|
||||
'/InAppWebViewFetchTest': (context) => InAppWebViewFetchTest(),
|
||||
'/InAppWebViewOnLoadResourceCustomSchemeTest': (context) => InAppWebViewOnLoadResourceCustomSchemeTest(),
|
||||
'/InAppWebViewShouldOverrideUrlLoadingTest': (context) => InAppWebViewShouldOverrideUrlLoadingTest(),
|
||||
'/InAppWebViewOnConsoleMessageTest': (context) => InAppWebViewOnConsoleMessageTest(),
|
||||
'/InAppWebViewOnDownloadStartTest': (context) => InAppWebViewOnDownloadStartTest(),
|
||||
'/InAppWebViewOnCreateWindowTest': (context) => InAppWebViewOnCreateWindowTest(),
|
||||
'/InAppWebViewOnJsDialogTest': (context) => InAppWebViewOnJsDialogTest(),
|
||||
'/InAppWebViewOnSafeBrowsingHitTest': (context) => InAppWebViewOnSafeBrowsingHitTest(),
|
||||
'/InAppWebViewOnReceivedHttpAuthRequestTest': (context) => InAppWebViewOnReceivedHttpAuthRequestTest(),
|
||||
'/InAppWebViewSslRequestTest': (context) => InAppWebViewSslRequestTest(),
|
||||
'/InAppWebViewOnFindResultReceivedTest': (context) => InAppWebViewOnFindResultReceivedTest(),
|
||||
'/InAppWebViewOnNavigationStateChangeTest': (context) => InAppWebViewOnNavigationStateChangeTest(),
|
||||
'/InAppWebViewOnLoadErrorTest': (context) => InAppWebViewOnLoadErrorTest(),
|
||||
'/InAppWebViewOnLoadHttpErrorTest': (context) => InAppWebViewOnLoadHttpErrorTest(),
|
||||
'/InAppWebViewCookieManagerTest': (context) => InAppWebViewCookieManagerTest(),
|
||||
'/InAppWebViewHttpAuthCredentialDatabaseTest': (context) => InAppWebViewHttpAuthCredentialDatabaseTest(),
|
||||
'/InAppWebViewContentBlockerTest': (context) => InAppWebViewContentBlockerTest(),
|
||||
};
|
||||
return routes;
|
||||
}
|
||||
|
||||
AppBar myAppBar({@required WidgetTestState state, @required String title}) {
|
||||
|
||||
return AppBar(
|
||||
title: Text(
|
||||
title,
|
||||
key: Key("AppBarTitle")
|
||||
),
|
||||
actions: <Widget>[
|
||||
IconButton(
|
||||
icon: Icon(Icons.menu),
|
||||
key: Key("SideMenu"),
|
||||
onPressed: () {
|
||||
state.scaffoldKey.currentState.openDrawer();
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(Icons.refresh),
|
||||
onPressed: () {
|
||||
if (state.webView != null)
|
||||
state.webView.reload();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Drawer myDrawer({@required context}) {
|
||||
var routes = getTestRoutes(context: context);
|
||||
List<Widget> listTiles = [
|
||||
DrawerHeader(
|
||||
child: Text('Tests'),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue,
|
||||
),
|
||||
)
|
||||
];
|
||||
for (String k in routes.keys) {
|
||||
var title = "";
|
||||
if (k == "/") {
|
||||
title = "InAppWebViewInitialUrlTest";
|
||||
} else {
|
||||
title = k.substring(1);
|
||||
}
|
||||
listTiles.add(ListTile(
|
||||
title: Text(title),
|
||||
key: Key(title),
|
||||
onTap: () {
|
||||
Navigator.pushReplacementNamed(context, k);
|
||||
},
|
||||
));
|
||||
}
|
||||
return Drawer(
|
||||
child: ListView(
|
||||
key: Key("ListTiles"),
|
||||
padding: EdgeInsets.zero,
|
||||
children: listTiles,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
runApp(new MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatefulWidget {
|
||||
@override
|
||||
_MyAppState createState() => new _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'flutter_inappbrowser tests',
|
||||
initialRoute: '/',
|
||||
routes: getTestRoutes(context: context)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -14,6 +14,12 @@
|
|||
<excludeFolder url="file://$MODULE_DIR$/example/flutter_plugin/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/flutter_plugin/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/flutter_plugin/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_downloader/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_downloader/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_downloader/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_downloader/example/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_downloader/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_downloader/example/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/build" />
|
||||
|
@ -27,6 +33,33 @@
|
|||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/ios/Flutter/App.framework/flutter_assets/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/integration_test/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/integration_test/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/integration_test/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/integration_test/example/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/integration_test/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/integration_test/example/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/integration_test/integration_test_macos/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/integration_test/integration_test_macos/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/integration_test/integration_test_macos/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider/example/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider/example/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/permission_handler/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/permission_handler/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/permission_handler/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/permission_handler/example/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/permission_handler/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/permission_handler/example/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/url_launcher/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/url_launcher/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/url_launcher/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/url_launcher/example/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/url_launcher/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/url_launcher/example/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/Flutter/App.framework/flutter_assets/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/flutter_inappbrowser_tests/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/flutter_inappbrowser_tests/.pub" />
|
||||
|
|
|
@ -65,7 +65,9 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
|
|||
|
||||
if #available(iOS 9.0, *) {
|
||||
|
||||
if let flutterViewController = UIApplication.shared.delegate?.window.unsafelyUnwrapped?.rootViewController as? FlutterViewController {
|
||||
if let flutterViewController = UIApplication.shared.delegate?.window.unsafelyUnwrapped?.rootViewController {
|
||||
// flutterViewController could be casted to FlutterViewController if needed
|
||||
|
||||
let safariOptions = SafariBrowserOptions()
|
||||
let _ = safariOptions.parse(options: options)
|
||||
|
||||
|
|
|
@ -1153,7 +1153,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
scrollView.maximumZoomScale = CGFloat(options.maximumZoomScale)
|
||||
scrollView.minimumZoomScale = CGFloat(options.minimumZoomScale)
|
||||
|
||||
// options.debuggingEnabled is always enabled for iOS,
|
||||
// debugging is always enabled for iOS,
|
||||
// there isn't any option to set about it such as on Android.
|
||||
|
||||
if options.clearCache {
|
||||
|
@ -1352,6 +1352,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
configuration.suppressesIncrementalRendering = options.suppressesIncrementalRendering
|
||||
configuration.selectionGranularity = WKSelectionGranularity.init(rawValue: options.selectionGranularity)!
|
||||
|
||||
if options.allowUniversalAccessFromFileURLs {
|
||||
configuration.setValue(options.allowUniversalAccessFromFileURLs, forKey: "allowUniversalAccessFromFileURLs")
|
||||
}
|
||||
|
||||
if options.allowFileAccessFromFileURLs {
|
||||
configuration.preferences.setValue(options.allowFileAccessFromFileURLs, forKey: "allowFileAccessFromFileURLs")
|
||||
}
|
||||
|
||||
if #available(iOS 9.0, *) {
|
||||
if options.incognito {
|
||||
configuration.websiteDataStore = WKWebsiteDataStore.nonPersistent()
|
||||
|
@ -1748,6 +1756,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
}
|
||||
}
|
||||
|
||||
if newOptionsMap["allowUniversalAccessFromFileURLs"] != nil && options?.allowUniversalAccessFromFileURLs != newOptions.allowUniversalAccessFromFileURLs {
|
||||
configuration.setValue(newOptions.allowUniversalAccessFromFileURLs, forKey: "allowUniversalAccessFromFileURLs")
|
||||
}
|
||||
|
||||
if newOptionsMap["allowFileAccessFromFileURLs"] != nil && options?.allowFileAccessFromFileURLs != newOptions.allowFileAccessFromFileURLs {
|
||||
configuration.preferences.setValue(newOptions.allowFileAccessFromFileURLs, forKey: "allowFileAccessFromFileURLs")
|
||||
}
|
||||
|
||||
if newOptionsMap["clearCache"] != nil && newOptions.clearCache {
|
||||
clearCache()
|
||||
}
|
||||
|
@ -2025,7 +2041,9 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
|
||||
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic ||
|
||||
challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodDefault ||
|
||||
challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPDigest {
|
||||
challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPDigest ||
|
||||
challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNegotiate ||
|
||||
challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM {
|
||||
let host = challenge.protectionSpace.host
|
||||
let prot = challenge.protectionSpace.protocol
|
||||
let realm = challenge.protectionSpace.realm
|
||||
|
@ -2498,6 +2516,9 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
}
|
||||
if !handledByClient, InAppWebView.windowWebViews[windowId] != nil {
|
||||
InAppWebView.windowWebViews.removeValue(forKey: windowId)
|
||||
if let url = navigationAction.request.url {
|
||||
self.loadUrl(url: url, headers: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -18,7 +18,6 @@ public class InAppWebViewOptions: Options<InAppWebView> {
|
|||
var userAgent = ""
|
||||
var applicationNameForUserAgent = ""
|
||||
var javaScriptEnabled = true
|
||||
var debuggingEnabled = true
|
||||
var javaScriptCanOpenWindowsAutomatically = false
|
||||
var mediaPlaybackRequiresUserGesture = true
|
||||
var verticalScrollBarEnabled = true
|
||||
|
@ -35,6 +34,8 @@ public class InAppWebViewOptions: Options<InAppWebView> {
|
|||
var disableHorizontalScroll = false
|
||||
var disableContextMenu = false
|
||||
var supportZoom = true
|
||||
var allowUniversalAccessFromFileURLs = false
|
||||
var allowFileAccessFromFileURLs = false
|
||||
|
||||
var disallowOverScroll = false
|
||||
var enableViewportScale = false
|
||||
|
@ -106,6 +107,8 @@ public class InAppWebViewOptions: Options<InAppWebView> {
|
|||
realOptions["isPagingEnabled"] = webView.scrollView.isPagingEnabled
|
||||
realOptions["maximumZoomScale"] = webView.scrollView.maximumZoomScale
|
||||
realOptions["minimumZoomScale"] = webView.scrollView.minimumZoomScale
|
||||
realOptions["allowUniversalAccessFromFileURLs"] = configuration.value(forKey: "allowUniversalAccessFromFileURLs")
|
||||
realOptions["allowFileAccessFromFileURLs"] = configuration.preferences.value(forKey: "allowFileAccessFromFileURLs")
|
||||
}
|
||||
return realOptions
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ class MyCookieManager: NSObject, FlutterPlugin {
|
|||
if let urlHost = URL(string: url)?.host {
|
||||
MyCookieManager.httpCookieStore!.getAllCookies { (cookies) in
|
||||
for cookie in cookies {
|
||||
if cookie.domain.contains(urlHost) {
|
||||
if urlHost.hasSuffix(cookie.domain) {
|
||||
var sameSite: String? = nil
|
||||
if #available(iOS 13.0, *) {
|
||||
if let sameSiteValue = cookie.sameSitePolicy?.rawValue {
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'asn1_identifier.dart';
|
||||
import 'asn1_object.dart';
|
||||
|
||||
class ASN1DERDecoder {
|
||||
static List<ASN1Object> decode({@required List<int> data}) {
|
||||
static List<ASN1Object> decode({required List<int> data}) {
|
||||
var iterator = data.iterator;
|
||||
return parse(iterator: iterator);
|
||||
}
|
||||
|
||||
static List<ASN1Object> parse({@required Iterator<int> iterator}) {
|
||||
static List<ASN1Object> parse({required Iterator<int> iterator}) {
|
||||
var result = <ASN1Object>[];
|
||||
|
||||
while (iterator.moveNext()) {
|
||||
|
@ -20,7 +19,7 @@ class ASN1DERDecoder {
|
|||
var asn1obj = ASN1Object();
|
||||
asn1obj.identifier = ASN1Identifier(nextValue);
|
||||
|
||||
if (asn1obj.identifier.isConstructed()) {
|
||||
if (asn1obj.identifier!.isConstructed()) {
|
||||
var contentData = loadSubContent(iterator: iterator);
|
||||
|
||||
if (contentData.isEmpty) {
|
||||
|
@ -34,18 +33,20 @@ class ASN1DERDecoder {
|
|||
|
||||
asn1obj.encoded = Uint8List.fromList(contentData);
|
||||
|
||||
for (var item in asn1obj.sub) {
|
||||
item.parent = asn1obj;
|
||||
if (asn1obj.sub != null) {
|
||||
for (var item in asn1obj.sub!) {
|
||||
item.parent = asn1obj;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (asn1obj.identifier.typeClass() == ASN1IdentifierClass.UNIVERSAL) {
|
||||
if (asn1obj.identifier!.typeClass() == ASN1IdentifierClass.UNIVERSAL) {
|
||||
var contentData = loadSubContent(iterator: iterator);
|
||||
|
||||
asn1obj.encoded = Uint8List.fromList(contentData);
|
||||
|
||||
// decode the content data with come more convenient format
|
||||
|
||||
var tagNumber = asn1obj.identifier.tagNumber();
|
||||
var tagNumber = asn1obj.identifier!.tagNumber();
|
||||
|
||||
if (tagNumber == ASN1IdentifierTagNumber.END_OF_CONTENT) {
|
||||
return result;
|
||||
|
@ -130,9 +131,12 @@ class ASN1DERDecoder {
|
|||
return result;
|
||||
}
|
||||
|
||||
static BigInt getContentLength({@required Iterator<int> iterator}) {
|
||||
static BigInt getContentLength({required Iterator<int> iterator}) {
|
||||
if (iterator.moveNext()) {
|
||||
var first = iterator.current;
|
||||
int? first;
|
||||
try {
|
||||
first = iterator.current;
|
||||
} catch (e) {}
|
||||
if (first != null) {
|
||||
if ((first & 0x80) != 0) {
|
||||
// long
|
||||
|
@ -141,7 +145,10 @@ class ASN1DERDecoder {
|
|||
var data = <int>[];
|
||||
for (var i = 0; i < octetsToRead; i++) {
|
||||
if (iterator.moveNext()) {
|
||||
var n = iterator.current;
|
||||
int? n;
|
||||
try {
|
||||
n = iterator.current;
|
||||
} catch (e) {}
|
||||
if (n != null) {
|
||||
data.add(n);
|
||||
}
|
||||
|
@ -158,7 +165,7 @@ class ASN1DERDecoder {
|
|||
return BigInt.from(0);
|
||||
}
|
||||
|
||||
static List<int> loadSubContent({@required Iterator<int> iterator}) {
|
||||
static List<int> loadSubContent({required Iterator<int> iterator}) {
|
||||
var len = getContentLength(iterator: iterator);
|
||||
int int64MaxValue = double.maxFinite.toInt();
|
||||
|
||||
|
@ -170,7 +177,10 @@ class ASN1DERDecoder {
|
|||
|
||||
for (var i = 0; i < len.toInt(); i++) {
|
||||
if (iterator.moveNext()) {
|
||||
var n = iterator.current;
|
||||
int? n;
|
||||
try {
|
||||
n = iterator.current;
|
||||
} catch (e) {}
|
||||
if (n != null) {
|
||||
byteArray.add(n);
|
||||
}
|
||||
|
@ -183,7 +193,7 @@ class ASN1DERDecoder {
|
|||
}
|
||||
|
||||
/// Decode DER OID bytes to String with dot notation
|
||||
static String decodeOid({@required List<int> contentData}) {
|
||||
static String decodeOid({required List<int> contentData}) {
|
||||
if (contentData.isEmpty) {
|
||||
return "";
|
||||
}
|
||||
|
@ -211,7 +221,7 @@ class ASN1DERDecoder {
|
|||
///dates past 2049. Parsing that structure hasn't been implemented yet.
|
||||
///
|
||||
///[contentData] the UTCTime value to convert.
|
||||
static DateTime utcTimeToDate({@required List<int> contentData}) {
|
||||
static DateTime? utcTimeToDate({required List<int> contentData}) {
|
||||
/* The following formats can be used:
|
||||
YYMMDDhhmmZ
|
||||
YYMMDDhhmm+hh'mm'
|
||||
|
@ -231,7 +241,7 @@ class ASN1DERDecoder {
|
|||
hh' is the absolute value of the offset from GMT in hours
|
||||
mm' is the absolute value of the offset from GMT in minutes */
|
||||
|
||||
String utc;
|
||||
String? utc;
|
||||
try {
|
||||
utc = utf8.decode(contentData);
|
||||
} catch (e) {}
|
||||
|
@ -250,8 +260,8 @@ class ASN1DERDecoder {
|
|||
var mm = int.parse(utc.substring(8, 10), radix: 10);
|
||||
var ss = 0;
|
||||
|
||||
int end;
|
||||
String c;
|
||||
int? end;
|
||||
String? c;
|
||||
// not just YYMMDDhhmmZ
|
||||
if (utc.length > 11) {
|
||||
// get character after minutes
|
||||
|
@ -298,7 +308,7 @@ class ASN1DERDecoder {
|
|||
///Converts a GeneralizedTime value to a date.
|
||||
///
|
||||
///[contentData] the GeneralizedTime value to convert.
|
||||
static DateTime generalizedTimeToDate({@required List<int> contentData}) {
|
||||
static DateTime? generalizedTimeToDate({required List<int> contentData}) {
|
||||
/* The following formats can be used:
|
||||
YYYYMMDDHHMMSS
|
||||
YYYYMMDDHHMMSS.fff
|
||||
|
@ -321,7 +331,7 @@ class ASN1DERDecoder {
|
|||
hh' is the absolute value of the offset from GMT in hours
|
||||
mm' is the absolute value of the offset from GMT in minutes */
|
||||
|
||||
String gentime;
|
||||
String? gentime;
|
||||
try {
|
||||
gentime = utf8.decode(contentData);
|
||||
} catch (e) {}
|
||||
|
@ -385,7 +395,7 @@ class ASN1DERDecoder {
|
|||
}
|
||||
}
|
||||
|
||||
BigInt toIntValue(List<int> data) {
|
||||
BigInt? toIntValue(List<int> data) {
|
||||
if (data.length > 8) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -19,10 +19,15 @@ class ASN1DistinguishedNames {
|
|||
ASN1DistinguishedNames.EMAIL,
|
||||
].toSet();
|
||||
|
||||
static ASN1DistinguishedNames fromValue(String oid) {
|
||||
if (oid != null)
|
||||
return ASN1DistinguishedNames.values
|
||||
.firstWhere((element) => element.oid() == oid, orElse: () => null);
|
||||
static ASN1DistinguishedNames? fromValue(String? oid) {
|
||||
if (oid != null) {
|
||||
try {
|
||||
return ASN1DistinguishedNames.values
|
||||
.firstWhere((element) => element.oid() == oid);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,11 +10,15 @@ class ASN1IdentifierClass {
|
|||
ASN1IdentifierClass.PRIVATE,
|
||||
].toSet();
|
||||
|
||||
static ASN1IdentifierClass fromValue(int value) {
|
||||
if (value != null)
|
||||
return ASN1IdentifierClass.values.firstWhere(
|
||||
(element) => element.toValue() == value,
|
||||
orElse: () => null);
|
||||
static ASN1IdentifierClass? fromValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return ASN1IdentifierClass.values.firstWhere(
|
||||
(element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -83,11 +87,15 @@ class ASN1IdentifierTagNumber {
|
|||
ASN1IdentifierTagNumber.BMP_STRING,
|
||||
].toSet();
|
||||
|
||||
static ASN1IdentifierTagNumber fromValue(int value) {
|
||||
if (value != null)
|
||||
return ASN1IdentifierTagNumber.values.firstWhere(
|
||||
(element) => element.toValue() == value,
|
||||
orElse: () => null);
|
||||
static ASN1IdentifierTagNumber? fromValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return ASN1IdentifierTagNumber.values.firstWhere(
|
||||
(element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,34 +7,34 @@ import 'oid.dart';
|
|||
|
||||
class ASN1Object {
|
||||
/// This property contains the DER encoded object
|
||||
Uint8List encoded;
|
||||
Uint8List? encoded;
|
||||
|
||||
/// This property contains the decoded Swift object whenever is possible
|
||||
dynamic value;
|
||||
|
||||
ASN1Identifier identifier;
|
||||
ASN1Identifier? identifier;
|
||||
|
||||
List<ASN1Object> sub;
|
||||
List<ASN1Object>? sub;
|
||||
|
||||
ASN1Object parent;
|
||||
ASN1Object? parent;
|
||||
|
||||
ASN1Object subAtIndex(int index) {
|
||||
if (sub != null && index >= 0 && index < sub.length) {
|
||||
return sub[index];
|
||||
ASN1Object? subAtIndex(int index) {
|
||||
if (sub != null && index >= 0 && index < sub!.length) {
|
||||
return sub![index];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
ASN1Object firstSub() {
|
||||
ASN1Object? firstSub() {
|
||||
if (subCount() > 0) {
|
||||
return sub.first;
|
||||
return sub!.first;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
ASN1Object lastSub() {
|
||||
ASN1Object? lastSub() {
|
||||
if (subCount() > 0) {
|
||||
return sub.last;
|
||||
return sub!.last;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ class ASN1Object {
|
|||
return sub?.length ?? 0;
|
||||
}
|
||||
|
||||
ASN1Object findOid({OID oid, String oidValue}) {
|
||||
ASN1Object? findOid({OID? oid, String? oidValue}) {
|
||||
oidValue = oid != null ? oid.toValue() : oidValue;
|
||||
for (var child in (sub ?? <ASN1Object>[])) {
|
||||
if (child.identifier?.tagNumber() ==
|
||||
|
@ -67,7 +67,7 @@ class ASN1Object {
|
|||
|
||||
String printAsn1({insets = ""}) {
|
||||
var output = insets;
|
||||
output += identifier?.description?.toUpperCase() ?? "";
|
||||
output += identifier?.description.toUpperCase() ?? "";
|
||||
output += (value != null ? ": $value" : "");
|
||||
if (identifier?.typeClass() == ASN1IdentifierClass.UNIVERSAL &&
|
||||
identifier?.tagNumber() == ASN1IdentifierTagNumber.OBJECT_IDENTIFIER) {
|
||||
|
@ -76,12 +76,12 @@ class ASN1Object {
|
|||
output += " ($descr)";
|
||||
}
|
||||
}
|
||||
output += sub != null && sub.length > 0 ? " {" : "";
|
||||
output += sub != null && sub!.length > 0 ? " {" : "";
|
||||
output += "\n";
|
||||
for (var item in (sub ?? <ASN1Object>[])) {
|
||||
output += item.printAsn1(insets: insets + " ");
|
||||
}
|
||||
output += sub != null && sub.length > 0 ? "}\n" : "";
|
||||
output += sub != null && sub!.length > 0 ? "}\n" : "";
|
||||
return output;
|
||||
}
|
||||
|
||||
|
@ -90,9 +90,9 @@ class ASN1Object {
|
|||
return description;
|
||||
}
|
||||
|
||||
ASN1Object atIndex(X509BlockPosition x509blockPosition) {
|
||||
if (sub != null && x509blockPosition.index < sub.length) {
|
||||
return sub[x509blockPosition.index];
|
||||
ASN1Object? atIndex(X509BlockPosition x509blockPosition) {
|
||||
if (sub != null && x509blockPosition.index < sub!.length) {
|
||||
return sub![x509blockPosition.index];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -15,14 +15,20 @@ class KeyUsage {
|
|||
KeyUsage.decipherOnly,
|
||||
].toSet();
|
||||
|
||||
static KeyUsage fromIndex(int value) {
|
||||
return KeyUsage.values.firstWhere((element) => element.toValue() == value,
|
||||
orElse: () => null);
|
||||
static KeyUsage? fromIndex(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return KeyUsage.values.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int toValue() => _value;
|
||||
|
||||
String name() => _KeyUsageMapName[this._value];
|
||||
String name() => _KeyUsageMapName.containsKey(this._value) ? _KeyUsageMapName[this._value]! : "";
|
||||
|
||||
@override
|
||||
String toString() => "($_value, ${name()})";
|
||||
|
|
|
@ -102,14 +102,20 @@ class OID {
|
|||
OID.timeStamping,
|
||||
].toSet();
|
||||
|
||||
static OID fromValue(String value) {
|
||||
return OID.values.firstWhere((element) => element.toValue() == value,
|
||||
orElse: () => null);
|
||||
static OID? fromValue(String? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return OID.values.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String toValue() => _value;
|
||||
|
||||
String name() => _oidMapName[this._value];
|
||||
String name() => _oidMapName.containsKey(this._value) ? _oidMapName[this._value]! : "";
|
||||
|
||||
@override
|
||||
String toString() => "($_value, ${name()})";
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'asn1_decoder.dart';
|
||||
import 'asn1_object.dart';
|
||||
import 'oid.dart';
|
||||
|
@ -13,19 +12,19 @@ import 'asn1_distinguished_names.dart';
|
|||
///Class that represents a X.509 certificate.
|
||||
///This provides a standard way to access all the attributes of an X.509 certificate.
|
||||
class X509Certificate {
|
||||
List<ASN1Object> asn1;
|
||||
ASN1Object block1;
|
||||
List<ASN1Object>? asn1;
|
||||
ASN1Object? block1;
|
||||
|
||||
///Returns the encoded form of this certificate. It is
|
||||
///assumed that each certificate type would have only a single
|
||||
///form of encoding; for example, X.509 certificates would
|
||||
///be encoded as ASN.1 DER.
|
||||
Uint8List encoded;
|
||||
Uint8List? encoded;
|
||||
|
||||
static const beginPemBlock = "-----BEGIN CERTIFICATE-----";
|
||||
static const endPemBlock = "-----END CERTIFICATE-----";
|
||||
|
||||
X509Certificate({ASN1Object asn1}) {
|
||||
X509Certificate({ASN1Object? asn1}) {
|
||||
if (asn1 != null) {
|
||||
var block1 = asn1.subAtIndex(0);
|
||||
if (block1 == null) {
|
||||
|
@ -34,7 +33,7 @@ class X509Certificate {
|
|||
}
|
||||
}
|
||||
|
||||
static X509Certificate fromData({@required Uint8List data}) {
|
||||
static X509Certificate fromData({required Uint8List data}) {
|
||||
var decoded = utf8.decode(data, allowMalformed: true);
|
||||
if (decoded.contains(X509Certificate.beginPemBlock)) {
|
||||
return X509Certificate.fromPemData(pem: data);
|
||||
|
@ -43,10 +42,10 @@ class X509Certificate {
|
|||
}
|
||||
}
|
||||
|
||||
static X509Certificate fromDerData({@required Uint8List der}) {
|
||||
static X509Certificate fromDerData({required Uint8List der}) {
|
||||
var asn1 = ASN1DERDecoder.decode(data: der.toList(growable: true));
|
||||
if (asn1.length > 0) {
|
||||
var block1 = asn1.first?.subAtIndex(0);
|
||||
var block1 = asn1.first.subAtIndex(0);
|
||||
if (block1 != null) {
|
||||
var certificate = X509Certificate();
|
||||
certificate.asn1 = asn1;
|
||||
|
@ -58,7 +57,7 @@ class X509Certificate {
|
|||
throw ASN1ParseError();
|
||||
}
|
||||
|
||||
static X509Certificate fromPemData({@required Uint8List pem}) {
|
||||
static X509Certificate fromPemData({required Uint8List pem}) {
|
||||
var derData = X509Certificate.decodeToDER(pemData: pem);
|
||||
if (derData == null) {
|
||||
throw ASN1ParseError();
|
||||
|
@ -67,9 +66,9 @@ class X509Certificate {
|
|||
}
|
||||
|
||||
///Read possible PEM encoding
|
||||
static Uint8List decodeToDER({@required pemData}) {
|
||||
static Uint8List? decodeToDER({required pemData}) {
|
||||
var pem = String.fromCharCodes(pemData);
|
||||
if (pem != null && pem.contains(X509Certificate.beginPemBlock)) {
|
||||
if (pem.contains(X509Certificate.beginPemBlock)) {
|
||||
var lines = pem.split("\n");
|
||||
var base64buffer = "";
|
||||
var certLine = false;
|
||||
|
@ -85,7 +84,7 @@ class X509Certificate {
|
|||
}
|
||||
}
|
||||
|
||||
Uint8List derDataDecoded;
|
||||
Uint8List? derDataDecoded;
|
||||
try {
|
||||
derDataDecoded = Uint8List.fromList(utf8.encode(base64buffer));
|
||||
} catch (e) {}
|
||||
|
@ -97,26 +96,28 @@ class X509Certificate {
|
|||
}
|
||||
|
||||
String get description =>
|
||||
asn1.fold("", (value, element) => value + element.description + "\n");
|
||||
asn1?.fold("", (value, element) => (value ?? '') + element.description + '\n') ?? '';
|
||||
|
||||
///Checks that the given date is within the certificate's validity period.
|
||||
bool checkValidity({DateTime date}) {
|
||||
bool checkValidity({DateTime? date}) {
|
||||
if (date == null) {
|
||||
date = DateTime.now();
|
||||
}
|
||||
if (notBefore != null && notAfter != null) {
|
||||
return date.isAfter(notBefore) && date.isBefore(notAfter);
|
||||
return date.isAfter(notBefore!) && date.isBefore(notAfter!);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
///Gets the version (version number) value from the certificate.
|
||||
int get version {
|
||||
var v = firstLeafValue(block: block1) as List<int>;
|
||||
if (v != null) {
|
||||
var index = toIntValue(v);
|
||||
if (index != null) {
|
||||
return index.toInt() + 1;
|
||||
int? get version {
|
||||
if (block1 != null) {
|
||||
var v = firstLeafValue(block: block1!) as List<int>?;
|
||||
if (v != null) {
|
||||
var index = toIntValue(v);
|
||||
if (index != null) {
|
||||
return index.toInt() + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -124,11 +125,11 @@ class X509Certificate {
|
|||
|
||||
///Gets the serialNumber value from the certificate.
|
||||
List<int> get serialNumber =>
|
||||
block1.atIndex(X509BlockPosition.serialNumber)?.value as List<int>;
|
||||
block1?.atIndex(X509BlockPosition.serialNumber)?.value as List<int>;
|
||||
|
||||
///Returns the issuer (issuer distinguished name) value from the certificate as a String.
|
||||
String get issuerDistinguishedName {
|
||||
var issuerBlock = block1.atIndex(X509BlockPosition.issuer);
|
||||
String? get issuerDistinguishedName {
|
||||
var issuerBlock = block1?.atIndex(X509BlockPosition.issuer);
|
||||
if (issuerBlock != null) {
|
||||
return blockDistinguishedName(block: issuerBlock);
|
||||
}
|
||||
|
@ -137,10 +138,10 @@ class X509Certificate {
|
|||
|
||||
List<String> get issuerOIDs {
|
||||
var result = <String>[];
|
||||
var issuerBlock = block1.atIndex(X509BlockPosition.issuer);
|
||||
var issuerBlock = block1?.atIndex(X509BlockPosition.issuer);
|
||||
if (issuerBlock != null) {
|
||||
for (var sub in (issuerBlock.sub ?? <ASN1Object>[])) {
|
||||
var value = firstLeafValue(block: sub) as String;
|
||||
var value = firstLeafValue(block: sub) as String?;
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
|
@ -149,12 +150,12 @@ class X509Certificate {
|
|||
return result;
|
||||
}
|
||||
|
||||
String issuer({String oid, ASN1DistinguishedNames dn}) {
|
||||
String? issuer({String? oid, ASN1DistinguishedNames? dn}) {
|
||||
if (oid == null && dn != null) {
|
||||
oid = dn.oid();
|
||||
}
|
||||
if (oid != null) {
|
||||
var issuerBlock = block1.atIndex(X509BlockPosition.issuer);
|
||||
var issuerBlock = block1?.atIndex(X509BlockPosition.issuer);
|
||||
if (issuerBlock != null) {
|
||||
var oidBlock = issuerBlock.findOid(oidValue: oid);
|
||||
if (oidBlock != null) {
|
||||
|
@ -171,8 +172,8 @@ class X509Certificate {
|
|||
}
|
||||
|
||||
///Returns the subject (subject distinguished name) value from the certificate as a String.
|
||||
String get subjectDistinguishedName {
|
||||
var subjectBlock = block1.atIndex(X509BlockPosition.subject);
|
||||
String? get subjectDistinguishedName {
|
||||
var subjectBlock = block1?.atIndex(X509BlockPosition.subject);
|
||||
if (subjectBlock != null) {
|
||||
return blockDistinguishedName(block: subjectBlock);
|
||||
}
|
||||
|
@ -181,10 +182,10 @@ class X509Certificate {
|
|||
|
||||
List<String> get subjectOIDs {
|
||||
var result = <String>[];
|
||||
var subjectBlock = block1.atIndex(X509BlockPosition.subject);
|
||||
var subjectBlock = block1?.atIndex(X509BlockPosition.subject);
|
||||
if (subjectBlock != null) {
|
||||
for (var sub in (subjectBlock.sub ?? <ASN1Object>[])) {
|
||||
var value = firstLeafValue(block: sub) as String;
|
||||
var value = firstLeafValue(block: sub) as String?;
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
|
@ -193,12 +194,12 @@ class X509Certificate {
|
|||
return result;
|
||||
}
|
||||
|
||||
String subject({String oid, ASN1DistinguishedNames dn}) {
|
||||
String? subject({String? oid, ASN1DistinguishedNames? dn}) {
|
||||
if (oid == null && dn != null) {
|
||||
oid = dn.oid();
|
||||
}
|
||||
if (oid != null) {
|
||||
var subjectBlock = block1.atIndex(X509BlockPosition.subject);
|
||||
var subjectBlock = block1?.atIndex(X509BlockPosition.subject);
|
||||
if (subjectBlock != null) {
|
||||
var oidBlock = subjectBlock.findOid(oidValue: oid);
|
||||
if (oidBlock != null) {
|
||||
|
@ -215,30 +216,29 @@ class X509Certificate {
|
|||
}
|
||||
|
||||
///Gets the notBefore date from the validity period of the certificate.
|
||||
DateTime get notBefore =>
|
||||
block1.atIndex(X509BlockPosition.dateValidity)?.subAtIndex(0)?.value
|
||||
as DateTime;
|
||||
DateTime? get notBefore =>
|
||||
block1?.atIndex(X509BlockPosition.dateValidity)?.subAtIndex(0)?.value
|
||||
as DateTime?;
|
||||
|
||||
///Gets the notAfter date from the validity period of the certificate.
|
||||
DateTime get notAfter {
|
||||
var value = block1
|
||||
.atIndex(X509BlockPosition.dateValidity)
|
||||
DateTime? get notAfter {
|
||||
var value = block1?.atIndex(X509BlockPosition.dateValidity)
|
||||
?.subAtIndex(1)
|
||||
?.value as DateTime;
|
||||
?.value as DateTime?;
|
||||
return value;
|
||||
}
|
||||
|
||||
///Gets the signature value (the raw signature bits) from the certificate.
|
||||
List<int> get signature => asn1[0].subAtIndex(2)?.value as List<int>;
|
||||
List<int>? get signature => asn1?[0].subAtIndex(2)?.value as List<int>;
|
||||
|
||||
///Gets the signature algorithm name for the certificate signature algorithm.
|
||||
String get sigAlgName => OID.fromValue(sigAlgOID ?? "")?.name();
|
||||
String? get sigAlgName => OID.fromValue(sigAlgOID ?? '')?.name();
|
||||
|
||||
///Gets the signature algorithm OID string from the certificate.
|
||||
String get sigAlgOID => block1.subAtIndex(2)?.subAtIndex(0)?.value as String;
|
||||
String? get sigAlgOID => block1?.subAtIndex(2)?.subAtIndex(0)?.value as String?;
|
||||
|
||||
///Gets the DER-encoded signature algorithm parameters from this certificate's signature algorithm.
|
||||
List<int> get sigAlgParams => null;
|
||||
List<int>? get sigAlgParams => null;
|
||||
|
||||
///Gets a boolean array representing bits of the KeyUsage extension, (OID = 2.5.29.15).
|
||||
///```
|
||||
|
@ -256,12 +256,12 @@ class X509Certificate {
|
|||
///```
|
||||
List<bool> get keyUsage {
|
||||
var result = <bool>[];
|
||||
var oidBlock = block1.findOid(oid: OID.keyUsage);
|
||||
var oidBlock = block1?.findOid(oid: OID.keyUsage);
|
||||
if (oidBlock != null) {
|
||||
var sub = oidBlock.parent?.sub;
|
||||
if (sub != null && sub.length > 0) {
|
||||
var data = sub.last.subAtIndex(0)?.value as List<int>;
|
||||
int bits = (data != null && data.length > 0) ? data.first ?? 0 : 0;
|
||||
var data = sub.last.subAtIndex(0)?.value as List<int>?;
|
||||
int bits = (data != null && data.length > 0) ? data.first : 0;
|
||||
for (var index = 0; index < 8; index++) {
|
||||
var value = bits & (1 << index).toUnsigned(8) != 0;
|
||||
result.insert(0, value);
|
||||
|
@ -285,8 +285,8 @@ class X509Certificate {
|
|||
extensionObject(oid: OID.issuerAltName)?.valueAsStrings ?? <String>[];
|
||||
|
||||
///Gets the informations of the public key from this certificate.
|
||||
X509PublicKey get publicKey {
|
||||
var pkBlock = block1.atIndex(X509BlockPosition.publicKey);
|
||||
X509PublicKey? get publicKey {
|
||||
var pkBlock = block1?.atIndex(X509BlockPosition.publicKey);
|
||||
if (pkBlock != null) {
|
||||
return X509PublicKey(pkBlock: pkBlock);
|
||||
}
|
||||
|
@ -302,7 +302,7 @@ class X509Certificate {
|
|||
return extensionBlocks
|
||||
.map((block) => X509Extension(block: block))
|
||||
.where((extension) => extension.isCritical)
|
||||
.map((extension) => extension.oid)
|
||||
.map((extension) => extension.oid ?? '')
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
@ -315,7 +315,7 @@ class X509Certificate {
|
|||
return extensionBlocks
|
||||
.map((block) => X509Extension(block: block))
|
||||
.where((extension) => !extension.isCritical)
|
||||
.map((extension) => extension.oid)
|
||||
.map((extension) => extension.oid ?? '')
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
@ -362,7 +362,7 @@ class X509Certificate {
|
|||
?.firstSub()
|
||||
?.sub
|
||||
?.map((e) => e.firstSub()?.value as String)
|
||||
?.toList() ??
|
||||
.toList() ??
|
||||
<String>[];
|
||||
|
||||
///Gets the list of CRL distribution points from the CRLDistributionPoints extension, (OID = 2.5.29.31).
|
||||
|
@ -373,7 +373,7 @@ class X509Certificate {
|
|||
?.firstSub()
|
||||
?.sub
|
||||
?.map((e) => e.firstSub()?.firstSub()?.firstSub()?.value as String)
|
||||
?.toList() ??
|
||||
.toList() ??
|
||||
<String>[];
|
||||
|
||||
///Gets the map of the format (as a key) and location (as a value) of additional information
|
||||
|
@ -390,24 +390,23 @@ class X509Certificate {
|
|||
sub.forEach((element) {
|
||||
if (element.subCount() > 1) {
|
||||
result.putIfAbsent(
|
||||
element.subAtIndex(0).value, () => element.subAtIndex(1).value);
|
||||
element.subAtIndex(0)!.value, () => element.subAtIndex(1)!.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
List<ASN1Object> get extensionBlocks =>
|
||||
block1.atIndex(X509BlockPosition.extensions)?.subAtIndex(0)?.sub;
|
||||
List<ASN1Object>? get extensionBlocks =>
|
||||
block1?.atIndex(X509BlockPosition.extensions)?.subAtIndex(0)?.sub;
|
||||
|
||||
///Gets the extension information of the given OID code or enum string value.
|
||||
X509Extension extensionObject({String oidValue, OID oid}) {
|
||||
X509Extension? extensionObject({String? oidValue, OID? oid}) {
|
||||
if (oidValue == null && oid != null) {
|
||||
oidValue = oid.toValue();
|
||||
}
|
||||
if (oidValue != null) {
|
||||
var block = block1
|
||||
.atIndex(X509BlockPosition.extensions)
|
||||
var block = block1?.atIndex(X509BlockPosition.extensions)
|
||||
?.findOid(oidValue: oidValue)
|
||||
?.parent;
|
||||
if (block != null) {
|
||||
|
@ -418,7 +417,7 @@ class X509Certificate {
|
|||
}
|
||||
|
||||
///Format subject/issuer information in RFC1779
|
||||
String blockDistinguishedName({@required ASN1Object block}) {
|
||||
String blockDistinguishedName({required ASN1Object block}) {
|
||||
var result = "";
|
||||
for (var oidName in ASN1DistinguishedNames.values) {
|
||||
var oidBlock = block.findOid(oidValue: oidName.oid());
|
||||
|
@ -431,7 +430,7 @@ class X509Certificate {
|
|||
|
||||
var sub = oidBlock.parent?.sub;
|
||||
if (sub != null && sub.length > 0) {
|
||||
var value = sub.last.value as String;
|
||||
var value = sub.last.value as String?;
|
||||
if (value != null) {
|
||||
var specialChar = ",+=\n<>#;\\";
|
||||
var quote = "";
|
||||
|
@ -490,10 +489,13 @@ class X509Certificate {
|
|||
}
|
||||
}
|
||||
|
||||
dynamic firstLeafValue({@required ASN1Object block}) {
|
||||
dynamic firstLeafValue({required ASN1Object block}) {
|
||||
var sub = block.sub;
|
||||
if (sub != null && sub.length > 0) {
|
||||
var subFirst = sub.first;
|
||||
ASN1Object? subFirst;
|
||||
try {
|
||||
subFirst = sub.first;
|
||||
} catch (e) {}
|
||||
if (subFirst != null) {
|
||||
return firstLeafValue(block: subFirst);
|
||||
}
|
||||
|
|
|
@ -3,25 +3,28 @@ import 'asn1_object.dart';
|
|||
import 'oid.dart';
|
||||
|
||||
class X509Extension {
|
||||
ASN1Object block;
|
||||
ASN1Object? block;
|
||||
|
||||
X509Extension({this.block});
|
||||
X509Extension({required this.block});
|
||||
|
||||
String get oid => block.subAtIndex(0)?.value;
|
||||
String? get oid => block?.subAtIndex(0)?.value;
|
||||
|
||||
String get name => OID.fromValue(oid ?? "")?.name();
|
||||
String? get name => OID.fromValue(oid)?.name();
|
||||
|
||||
bool get isCritical {
|
||||
if ((block.sub?.length ?? 0) > 2) {
|
||||
return block.subAtIndex(1)?.value ?? false;
|
||||
if ((block?.sub?.length ?? 0) > 2) {
|
||||
return block?.subAtIndex(1)?.value ?? false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
dynamic get value {
|
||||
var sub = block.sub;
|
||||
var sub = block?.sub;
|
||||
if (sub != null && sub.length > 0) {
|
||||
var valueBlock = sub.last;
|
||||
ASN1Object? valueBlock;
|
||||
try {
|
||||
valueBlock = sub.last;
|
||||
} catch (e) {}
|
||||
if (valueBlock != null) {
|
||||
return firstLeafValue(block: valueBlock);
|
||||
}
|
||||
|
@ -29,19 +32,23 @@ class X509Extension {
|
|||
return null;
|
||||
}
|
||||
|
||||
ASN1Object get valueAsBlock {
|
||||
var sub = block.sub;
|
||||
ASN1Object? get valueAsBlock {
|
||||
var sub = block?.sub;
|
||||
if (sub != null && sub.length > 0) {
|
||||
return sub.last;
|
||||
ASN1Object? valueBlock;
|
||||
try {
|
||||
valueBlock = sub.last;
|
||||
} catch (e) {}
|
||||
return valueBlock;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
List<String> get valueAsStrings {
|
||||
var result = <String>[];
|
||||
var sub;
|
||||
var sub = <ASN1Object>[];
|
||||
try {
|
||||
sub = block.sub?.last?.sub?.last?.sub ?? <ASN1Object>[];
|
||||
sub = block?.sub?.last.sub?.last.sub ?? <ASN1Object>[];
|
||||
} catch (e) {}
|
||||
|
||||
for (var item in sub) {
|
||||
|
|
|
@ -5,17 +5,17 @@ import 'asn1_object.dart';
|
|||
import 'oid.dart';
|
||||
|
||||
class X509PublicKey {
|
||||
ASN1Object pkBlock;
|
||||
ASN1Object? pkBlock;
|
||||
|
||||
X509PublicKey({this.pkBlock});
|
||||
|
||||
String get algOid => pkBlock?.subAtIndex(0)?.subAtIndex(0)?.value;
|
||||
String? get algOid => pkBlock?.subAtIndex(0)?.subAtIndex(0)?.value;
|
||||
|
||||
String get algName => OID.fromValue(algOid ?? "")?.name();
|
||||
String? get algName => OID.fromValue(algOid)?.name();
|
||||
|
||||
String get algParams => pkBlock?.subAtIndex(0)?.subAtIndex(1)?.value;
|
||||
String? get algParams => pkBlock?.subAtIndex(0)?.subAtIndex(1)?.value;
|
||||
|
||||
Uint8List get encoded {
|
||||
Uint8List? get encoded {
|
||||
var oid = OID.fromValue(algOid);
|
||||
var keyData = pkBlock?.subAtIndex(1)?.value ?? null;
|
||||
|
||||
|
@ -23,7 +23,7 @@ class X509PublicKey {
|
|||
if (oid == OID.ecPublicKey) {
|
||||
return Uint8List.fromList(keyData);
|
||||
} else if (oid == OID.rsaEncryption) {
|
||||
List<ASN1Object> publicKeyAsn1Objects;
|
||||
List<ASN1Object>? publicKeyAsn1Objects;
|
||||
try {
|
||||
publicKeyAsn1Objects =
|
||||
ASN1DERDecoder.decode(data: keyData.toList(growable: true));
|
||||
|
@ -31,7 +31,7 @@ class X509PublicKey {
|
|||
|
||||
if (publicKeyAsn1Objects != null && publicKeyAsn1Objects.length > 0) {
|
||||
var publicKeyModulus =
|
||||
publicKeyAsn1Objects.first?.subAtIndex(0)?.value;
|
||||
publicKeyAsn1Objects.first.subAtIndex(0)?.value;
|
||||
if (publicKeyModulus != null) {
|
||||
return Uint8List.fromList(publicKeyModulus);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'types.dart';
|
||||
|
@ -14,11 +13,11 @@ import 'in_app_browser.dart';
|
|||
///
|
||||
///Note: Requires modification of Android 11+: https://developers.google.com/web/android/custom-tabs/best-practices#applications_targeting_android_11_api_level_30_or_above
|
||||
class ChromeSafariBrowser {
|
||||
String uuid;
|
||||
InAppBrowser browserFallback;
|
||||
late String uuid;
|
||||
InAppBrowser? browserFallback;
|
||||
Map<int, ChromeSafariBrowserMenuItem> _menuItems = new HashMap();
|
||||
bool _isOpened = false;
|
||||
MethodChannel _channel;
|
||||
late MethodChannel _channel;
|
||||
static const MethodChannel _sharedChannel =
|
||||
const MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser');
|
||||
|
||||
|
@ -48,7 +47,9 @@ class ChromeSafariBrowser {
|
|||
String url = call.arguments["url"];
|
||||
String title = call.arguments["title"];
|
||||
int id = call.arguments["id"].toInt();
|
||||
this._menuItems[id].action(url, title);
|
||||
if (this._menuItems[id] != null) {
|
||||
this._menuItems[id]!.action(url, title);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw UnimplementedError("Unimplemented ${call.method} method");
|
||||
|
@ -67,14 +68,14 @@ class ChromeSafariBrowser {
|
|||
///
|
||||
///[contextMenuFallback]: Context Menu used by the [InAppBrowser] instance fallback.
|
||||
Future<void> open(
|
||||
{@required String url,
|
||||
ChromeSafariBrowserClassOptions options,
|
||||
Map<String, String> headersFallback = const {},
|
||||
InAppBrowserClassOptions optionsFallback}) async {
|
||||
assert(url != null && url.isNotEmpty);
|
||||
{required String url,
|
||||
ChromeSafariBrowserClassOptions? options,
|
||||
Map<String, String>? headersFallback = const {},
|
||||
InAppBrowserClassOptions? optionsFallback}) async {
|
||||
assert(url.isNotEmpty);
|
||||
this.throwIsAlreadyOpened(message: 'Cannot open $url!');
|
||||
|
||||
List<Map<String, dynamic>> menuItemList = new List();
|
||||
List<Map<String, dynamic>> menuItemList = [];
|
||||
_menuItems.forEach((key, value) {
|
||||
menuItemList.add({"id": value.id, "label": value.label});
|
||||
});
|
||||
|
@ -162,7 +163,7 @@ class ChromeSafariBrowserMenuItem {
|
|||
final void Function(String url, String title) action;
|
||||
|
||||
ChromeSafariBrowserMenuItem(
|
||||
{@required this.id, @required this.label, @required this.action});
|
||||
{required this.id, required this.label, required this.action});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {"id": id, "label": label};
|
||||
|
|
|
@ -15,7 +15,7 @@ class ContentBlocker {
|
|||
///Action associated to the trigger. The action tells to the WebView what to do when the trigger is matched.
|
||||
ContentBlockerAction action;
|
||||
|
||||
ContentBlocker({@required this.trigger, @required this.action});
|
||||
ContentBlocker({required this.trigger, required this.action});
|
||||
|
||||
Map<String, Map<String, dynamic>> toMap() {
|
||||
return {"trigger": trigger.toMap(), "action": action.toMap()};
|
||||
|
@ -24,9 +24,9 @@ class ContentBlocker {
|
|||
static ContentBlocker fromMap(Map<dynamic, Map<dynamic, dynamic>> map) {
|
||||
return ContentBlocker(
|
||||
trigger: ContentBlockerTrigger.fromMap(
|
||||
Map<String, dynamic>.from(map["trigger"])),
|
||||
Map<String, dynamic>.from(map["trigger"]!)),
|
||||
action: ContentBlockerAction.fromMap(
|
||||
Map<String, dynamic>.from(map["action"])));
|
||||
Map<String, dynamic>.from(map["action"]!)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,36 +36,36 @@ class ContentBlocker {
|
|||
///For example, you can limit the trigger to specific domains or have it not apply when a match is found on a specific domain.
|
||||
class ContentBlockerTrigger {
|
||||
///A regular expression pattern to match the URL against.
|
||||
String urlFilter;
|
||||
late String urlFilter;
|
||||
|
||||
///Used only by iOS. A Boolean value. The default value is false.
|
||||
bool urlFilterIsCaseSensitive;
|
||||
late bool urlFilterIsCaseSensitive;
|
||||
|
||||
///A list of [ContentBlockerTriggerResourceType] representing the resource types (how the browser intends to use the resource) that the rule should match.
|
||||
///If not specified, the rule matches all resource types.
|
||||
List<ContentBlockerTriggerResourceType> resourceType;
|
||||
late List<ContentBlockerTriggerResourceType> resourceType;
|
||||
|
||||
///A list of strings matched to a URL's domain; limits action to a list of specific domains.
|
||||
///Values must be lowercase ASCII, or punycode for non-ASCII. Add * in front to match domain and subdomains. Can't be used with [ContentBlockerTrigger.unlessDomain].
|
||||
List<String> ifDomain;
|
||||
late List<String> ifDomain;
|
||||
|
||||
///A list of strings matched to a URL's domain; acts on any site except domains in a provided list.
|
||||
///Values must be lowercase ASCII, or punycode for non-ASCII. Add * in front to match domain and subdomains. Can't be used with [ContentBlockerTrigger.ifDomain].
|
||||
List<String> unlessDomain;
|
||||
late List<String> unlessDomain;
|
||||
|
||||
///A list of [ContentBlockerTriggerLoadType] that can include one of two mutually exclusive values. If not specified, the rule matches all load types.
|
||||
List<ContentBlockerTriggerLoadType> loadType;
|
||||
late List<ContentBlockerTriggerLoadType> loadType;
|
||||
|
||||
///A list of strings matched to the entire main document URL; limits the action to a specific list of URL patterns.
|
||||
///Values must be lowercase ASCII, or punycode for non-ASCII. Can't be used with [ContentBlockerTrigger.unlessTopUrl].
|
||||
List<String> ifTopUrl;
|
||||
late List<String> ifTopUrl;
|
||||
|
||||
///An array of strings matched to the entire main document URL; acts on any site except URL patterns in provided list.
|
||||
///Values must be lowercase ASCII, or punycode for non-ASCII. Can't be used with [ContentBlockerTrigger.ifTopUrl].
|
||||
List<String> unlessTopUrl;
|
||||
late List<String> unlessTopUrl;
|
||||
|
||||
ContentBlockerTrigger(
|
||||
{@required String urlFilter,
|
||||
{required String urlFilter,
|
||||
bool urlFilterIsCaseSensitive = false,
|
||||
List<ContentBlockerTriggerResourceType> resourceType = const [],
|
||||
List<String> ifDomain = const [],
|
||||
|
@ -74,7 +74,6 @@ class ContentBlockerTrigger {
|
|||
List<String> ifTopUrl = const [],
|
||||
List<String> unlessTopUrl = const []}) {
|
||||
this.urlFilter = urlFilter;
|
||||
assert(this.urlFilter != null);
|
||||
this.resourceType = resourceType;
|
||||
this.urlFilterIsCaseSensitive = urlFilterIsCaseSensitive;
|
||||
this.ifDomain = ifDomain;
|
||||
|
@ -124,13 +123,19 @@ class ContentBlockerTrigger {
|
|||
|
||||
List<String> resourceTypeStringList =
|
||||
List<String>.from(map["resource-type"] ?? []);
|
||||
resourceTypeStringList.forEach((type) {
|
||||
resourceType.add(ContentBlockerTriggerResourceType.fromValue(type));
|
||||
resourceTypeStringList.forEach((typeValue) {
|
||||
var type = ContentBlockerTriggerResourceType.fromValue(typeValue);
|
||||
if (type != null) {
|
||||
resourceType.add(type);
|
||||
}
|
||||
});
|
||||
|
||||
List<String> loadTypeStringList = List<String>.from(map["load-type"] ?? []);
|
||||
loadTypeStringList.forEach((type) {
|
||||
loadType.add(ContentBlockerTriggerLoadType.fromValue(type));
|
||||
loadTypeStringList.forEach((typeValue) {
|
||||
var type = ContentBlockerTriggerLoadType.fromValue(typeValue);
|
||||
if (type != null) {
|
||||
loadType.add(type);
|
||||
}
|
||||
});
|
||||
|
||||
return ContentBlockerTrigger(
|
||||
|
@ -152,16 +157,15 @@ class ContentBlockerTrigger {
|
|||
///Group the rules with similar actions together to improve performance.
|
||||
class ContentBlockerAction {
|
||||
///Type of the action.
|
||||
ContentBlockerActionType type;
|
||||
late ContentBlockerActionType type;
|
||||
|
||||
///If the action type is [ContentBlockerActionType.CSS_DISPLAY_NONE], then also the [selector] property is required, otherwise it is ignored.
|
||||
///It specify a string that defines a selector list. Use CSS identifiers as the individual selector values, separated by commas.
|
||||
String selector;
|
||||
String? selector;
|
||||
|
||||
ContentBlockerAction(
|
||||
{@required ContentBlockerActionType type, String selector}) {
|
||||
{required ContentBlockerActionType type, String? selector}) {
|
||||
this.type = type;
|
||||
assert(this.type != null);
|
||||
if (this.type == ContentBlockerActionType.CSS_DISPLAY_NONE) {
|
||||
assert(selector != null);
|
||||
}
|
||||
|
@ -183,7 +187,7 @@ class ContentBlockerAction {
|
|||
|
||||
static ContentBlockerAction fromMap(Map<String, dynamic> map) {
|
||||
return ContentBlockerAction(
|
||||
type: ContentBlockerActionType.fromValue(map["type"]),
|
||||
type: ContentBlockerActionType.fromValue(map["type"])!,
|
||||
selector: map["selector"]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,20 +10,20 @@ class ContextMenu {
|
|||
///Event fired when the context menu for this WebView is being built.
|
||||
///
|
||||
///[hitTestResult] represents the hit result for hitting an HTML elements.
|
||||
final void Function(InAppWebViewHitTestResult hitTestResult)
|
||||
final void Function(InAppWebViewHitTestResult hitTestResult)?
|
||||
onCreateContextMenu;
|
||||
|
||||
///Event fired when the context menu for this WebView is being hidden.
|
||||
final void Function() onHideContextMenu;
|
||||
final void Function()? onHideContextMenu;
|
||||
|
||||
///Event fired when a context menu item has been clicked.
|
||||
///
|
||||
///[contextMenuItemClicked] represents the [ContextMenuItem] clicked.
|
||||
final void Function(ContextMenuItem contextMenuItemClicked)
|
||||
final void Function(ContextMenuItem contextMenuItemClicked)?
|
||||
onContextMenuActionItemClicked;
|
||||
|
||||
///Context menu options.
|
||||
final ContextMenuOptions options;
|
||||
final ContextMenuOptions? options;
|
||||
|
||||
///List of the custom [ContextMenuItem].
|
||||
final List<ContextMenuItem> menuItems;
|
||||
|
@ -33,12 +33,11 @@ class ContextMenu {
|
|||
this.onCreateContextMenu,
|
||||
this.onHideContextMenu,
|
||||
this.options,
|
||||
this.onContextMenuActionItemClicked})
|
||||
: assert(menuItems != null);
|
||||
this.onContextMenuActionItemClicked});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"menuItems": menuItems.map((menuItem) => menuItem?.toMap()).toList(),
|
||||
"menuItems": menuItems.map((menuItem) => menuItem.toMap()).toList(),
|
||||
"options": options?.toMap()
|
||||
};
|
||||
}
|
||||
|
@ -56,21 +55,21 @@ class ContextMenu {
|
|||
///Class that represent an item of the [ContextMenu].
|
||||
class ContextMenuItem {
|
||||
///Android menu item ID.
|
||||
int androidId;
|
||||
int? androidId;
|
||||
|
||||
///iOS menu item ID.
|
||||
String iosId;
|
||||
String? iosId;
|
||||
|
||||
///Menu item title.
|
||||
String title;
|
||||
|
||||
///Menu item action that will be called when an user clicks on it.
|
||||
Function() action;
|
||||
Function()? action;
|
||||
|
||||
ContextMenuItem(
|
||||
{@required this.androidId,
|
||||
@required this.iosId,
|
||||
@required this.title,
|
||||
{this.androidId,
|
||||
this.iosId,
|
||||
required this.title,
|
||||
this.action});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'types.dart';
|
||||
|
@ -11,19 +10,19 @@ import 'types.dart';
|
|||
///
|
||||
///**NOTE for iOS**: available from iOS 11.0+.
|
||||
class CookieManager {
|
||||
static CookieManager _instance;
|
||||
static CookieManager? _instance;
|
||||
static const MethodChannel _channel = const MethodChannel(
|
||||
'com.pichillilorenzo/flutter_inappwebview_cookiemanager');
|
||||
|
||||
///Gets the cookie manager shared instance.
|
||||
static CookieManager instance() {
|
||||
return (_instance != null) ? _instance : _init();
|
||||
return (_instance != null) ? _instance! : _init();
|
||||
}
|
||||
|
||||
static CookieManager _init() {
|
||||
_channel.setMethodCallHandler(_handleMethod);
|
||||
_instance = CookieManager();
|
||||
return _instance;
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
static Future<dynamic> _handleMethod(MethodCall call) async {}
|
||||
|
@ -33,23 +32,23 @@ class CookieManager {
|
|||
///The default value of [path] is `"/"`.
|
||||
///If [domain] is `null`, its default value will be the domain name of [url].
|
||||
Future<void> setCookie(
|
||||
{@required String url,
|
||||
@required String name,
|
||||
@required String value,
|
||||
String domain,
|
||||
{required String url,
|
||||
required String name,
|
||||
required String value,
|
||||
String? domain,
|
||||
String path = "/",
|
||||
int expiresDate,
|
||||
int maxAge,
|
||||
bool isSecure,
|
||||
bool isHttpOnly,
|
||||
HTTPCookieSameSitePolicy sameSite}) async {
|
||||
int? expiresDate,
|
||||
int? maxAge,
|
||||
bool? isSecure,
|
||||
bool? isHttpOnly,
|
||||
HTTPCookieSameSitePolicy? sameSite}) async {
|
||||
if (domain == null) domain = _getDomainName(url);
|
||||
|
||||
assert(url != null && url.isNotEmpty);
|
||||
assert(name != null && name.isNotEmpty);
|
||||
assert(value != null && value.isNotEmpty);
|
||||
assert(domain != null && domain.isNotEmpty);
|
||||
assert(path != null && path.isNotEmpty);
|
||||
assert(url.isNotEmpty);
|
||||
assert(name.isNotEmpty);
|
||||
assert(value.isNotEmpty);
|
||||
assert(domain.isNotEmpty);
|
||||
assert(path.isNotEmpty);
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('url', () => url);
|
||||
|
@ -67,8 +66,8 @@ class CookieManager {
|
|||
}
|
||||
|
||||
///Gets all the cookies for the given [url].
|
||||
Future<List<Cookie>> getCookies({@required String url}) async {
|
||||
assert(url != null && url.isNotEmpty);
|
||||
Future<List<Cookie>> getCookies({required String url}) async {
|
||||
assert(url.isNotEmpty);
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('url', () => url);
|
||||
|
@ -94,10 +93,10 @@ class CookieManager {
|
|||
}
|
||||
|
||||
///Gets a cookie by its [name] for the given [url].
|
||||
Future<Cookie> getCookie(
|
||||
{@required String url, @required String name}) async {
|
||||
assert(url != null && url.isNotEmpty);
|
||||
assert(name != null && name.isNotEmpty);
|
||||
Future<Cookie?> getCookie(
|
||||
{required String url, required String name}) async {
|
||||
assert(url.isNotEmpty);
|
||||
assert(name.isNotEmpty);
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('url', () => url);
|
||||
|
@ -126,16 +125,16 @@ class CookieManager {
|
|||
///The default value of [path] is `"/"`.
|
||||
///If [domain] is `null` or empty, its default value will be the domain name of [url].
|
||||
Future<void> deleteCookie(
|
||||
{@required String url,
|
||||
@required String name,
|
||||
{required String url,
|
||||
required String name,
|
||||
String domain = "",
|
||||
String path = "/"}) async {
|
||||
if (domain == null || domain.isEmpty) domain = _getDomainName(url);
|
||||
if (domain.isEmpty) domain = _getDomainName(url);
|
||||
|
||||
assert(url != null && url.isNotEmpty);
|
||||
assert(name != null && name.isNotEmpty);
|
||||
assert(domain != null && url.isNotEmpty);
|
||||
assert(path != null && url.isNotEmpty);
|
||||
assert(url.isNotEmpty);
|
||||
assert(name.isNotEmpty);
|
||||
assert(url.isNotEmpty);
|
||||
assert(url.isNotEmpty);
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('url', () => url);
|
||||
|
@ -150,12 +149,12 @@ class CookieManager {
|
|||
///The default value of [path] is `"/"`.
|
||||
///If [domain] is `null` or empty, its default value will be the domain name of [url].
|
||||
Future<void> deleteCookies(
|
||||
{@required String url, String domain = "", String path = "/"}) async {
|
||||
if (domain == null || domain.isEmpty) domain = _getDomainName(url);
|
||||
{required String url, String domain = "", String path = "/"}) async {
|
||||
if (domain.isEmpty) domain = _getDomainName(url);
|
||||
|
||||
assert(url != null && url.isNotEmpty);
|
||||
assert(domain != null && url.isNotEmpty);
|
||||
assert(path != null && url.isNotEmpty);
|
||||
assert(url.isNotEmpty);
|
||||
assert(url.isNotEmpty);
|
||||
assert(url.isNotEmpty);
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('url', () => url);
|
||||
|
@ -173,6 +172,7 @@ class CookieManager {
|
|||
String _getDomainName(String url) {
|
||||
Uri uri = Uri.parse(url);
|
||||
String domain = uri.host;
|
||||
// ignore: unnecessary_null_comparison
|
||||
if (domain == null) return "";
|
||||
return domain.startsWith("www.") ? domain.substring(4) : domain;
|
||||
}
|
||||
|
|
|
@ -12,16 +12,16 @@ import 'in_app_webview_controller.dart';
|
|||
///
|
||||
///Remember to dispose it when you don't need it anymore.
|
||||
class HeadlessInAppWebView implements WebView {
|
||||
String uuid;
|
||||
late String uuid;
|
||||
bool _isDisposed = true;
|
||||
static const MethodChannel _sharedChannel =
|
||||
const MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview');
|
||||
|
||||
///WebView Controller that can be used to access the [InAppWebViewController] API.
|
||||
InAppWebViewController webViewController;
|
||||
late InAppWebViewController webViewController;
|
||||
|
||||
///The window id of a [CreateWindowRequest.windowId].
|
||||
final int windowId;
|
||||
final int? windowId;
|
||||
|
||||
HeadlessInAppWebView(
|
||||
{this.windowId,
|
||||
|
@ -89,7 +89,9 @@ class HeadlessInAppWebView implements WebView {
|
|||
Future<dynamic> handleMethod(MethodCall call) async {
|
||||
switch (call.method) {
|
||||
case "onHeadlessWebViewCreated":
|
||||
onWebViewCreated(webViewController);
|
||||
if (onWebViewCreated != null) {
|
||||
onWebViewCreated!(webViewController);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return webViewController.handleMethod(call);
|
||||
|
@ -107,12 +109,13 @@ class HeadlessInAppWebView implements WebView {
|
|||
args.putIfAbsent(
|
||||
'params',
|
||||
() => <String, dynamic>{
|
||||
'initialUrl': '${Uri.parse(this.initialUrl)}',
|
||||
'initialUrl': this.initialUrl != null ? '${Uri.parse(this.initialUrl!)}' : '',
|
||||
'initialFile': this.initialFile,
|
||||
'initialData': this.initialData?.toMap(),
|
||||
'initialHeaders': this.initialHeaders,
|
||||
'initialOptions': this.initialOptions?.toMap() ?? {},
|
||||
'contextMenu': this.contextMenu?.toMap() ?? {}
|
||||
'contextMenu': this.contextMenu?.toMap() ?? {},
|
||||
'windowId': this.windowId
|
||||
});
|
||||
await _sharedChannel.invokeMethod('createHeadlessWebView', args);
|
||||
}
|
||||
|
@ -129,242 +132,242 @@ class HeadlessInAppWebView implements WebView {
|
|||
}
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)?
|
||||
androidOnGeolocationPermissionsHidePrompt;
|
||||
|
||||
@override
|
||||
final Future<GeolocationPermissionShowPromptResponse> Function(
|
||||
InAppWebViewController controller, String origin)
|
||||
final Future<GeolocationPermissionShowPromptResponse?> Function(
|
||||
InAppWebViewController controller, String origin)?
|
||||
androidOnGeolocationPermissionsShowPrompt;
|
||||
|
||||
@override
|
||||
final Future<PermissionRequestResponse> Function(
|
||||
final Future<PermissionRequestResponse?> Function(
|
||||
InAppWebViewController controller,
|
||||
String origin,
|
||||
List<String> resources) androidOnPermissionRequest;
|
||||
List<String> resources)? androidOnPermissionRequest;
|
||||
|
||||
@override
|
||||
final Future<SafeBrowsingResponse> Function(InAppWebViewController controller,
|
||||
String url, SafeBrowsingThreat threatType) androidOnSafeBrowsingHit;
|
||||
final Future<SafeBrowsingResponse?> Function(InAppWebViewController controller,
|
||||
String url, SafeBrowsingThreat? threatType)? androidOnSafeBrowsingHit;
|
||||
|
||||
@override
|
||||
final InAppWebViewInitialData initialData;
|
||||
final InAppWebViewInitialData? initialData;
|
||||
|
||||
@override
|
||||
final String initialFile;
|
||||
final String? initialFile;
|
||||
|
||||
@override
|
||||
final Map<String, String> initialHeaders;
|
||||
final Map<String, String>? initialHeaders;
|
||||
|
||||
@override
|
||||
final InAppWebViewGroupOptions initialOptions;
|
||||
final InAppWebViewGroupOptions? initialOptions;
|
||||
|
||||
@override
|
||||
final ContextMenu contextMenu;
|
||||
final ContextMenu? contextMenu;
|
||||
|
||||
@override
|
||||
final String initialUrl;
|
||||
final String? initialUrl;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
final void Function(InAppWebViewController controller, String? url)?
|
||||
onPageCommitVisible;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String title)
|
||||
final void Function(InAppWebViewController controller, String? title)?
|
||||
onTitleChanged;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)?
|
||||
iosOnDidReceiveServerRedirectForProvisionalNavigation;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)?
|
||||
iosOnWebContentProcessDidTerminate;
|
||||
|
||||
@override
|
||||
final Future<AjaxRequestAction> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)?
|
||||
onAjaxProgress;
|
||||
|
||||
@override
|
||||
final Future<AjaxRequestAction> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
final Future<AjaxRequestAction?> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)?
|
||||
onAjaxReadyStateChange;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, ConsoleMessage consoleMessage)
|
||||
InAppWebViewController controller, ConsoleMessage consoleMessage)?
|
||||
onConsoleMessage;
|
||||
|
||||
@override
|
||||
final Future<bool> Function(InAppWebViewController controller,
|
||||
CreateWindowRequest createWindowRequest) onCreateWindow;
|
||||
final Future<bool?> Function(InAppWebViewController controller,
|
||||
CreateWindowRequest createWindowRequest)? onCreateWindow;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) onCloseWindow;
|
||||
final void Function(InAppWebViewController controller)? onCloseWindow;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) onWindowFocus;
|
||||
final void Function(InAppWebViewController controller)? onWindowFocus;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) onWindowBlur;
|
||||
final void Function(InAppWebViewController controller)? onWindowBlur;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) androidOnRequestFocus;
|
||||
final void Function(InAppWebViewController controller)? androidOnRequestFocus;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
final void Function(InAppWebViewController controller, String url)?
|
||||
onDownloadStart;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, int activeMatchOrdinal,
|
||||
int numberOfMatches, bool isDoneCounting) onFindResultReceived;
|
||||
int numberOfMatches, bool isDoneCounting)? onFindResultReceived;
|
||||
|
||||
@override
|
||||
final Future<JsAlertResponse> Function(
|
||||
InAppWebViewController controller, JsAlertRequest jsAlertRequest)
|
||||
final Future<JsAlertResponse?> Function(
|
||||
InAppWebViewController controller, JsAlertRequest jsAlertRequest)?
|
||||
onJsAlert;
|
||||
|
||||
@override
|
||||
final Future<JsConfirmResponse> Function(
|
||||
InAppWebViewController controller, JsConfirmRequest jsConfirmRequest)
|
||||
final Future<JsConfirmResponse?> Function(
|
||||
InAppWebViewController controller, JsConfirmRequest jsConfirmRequest)?
|
||||
onJsConfirm;
|
||||
|
||||
@override
|
||||
final Future<JsPromptResponse> Function(
|
||||
InAppWebViewController controller, JsPromptRequest jsPromptRequest)
|
||||
final Future<JsPromptResponse?> Function(
|
||||
InAppWebViewController controller, JsPromptRequest jsPromptRequest)?
|
||||
onJsPrompt;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url, int code,
|
||||
String message) onLoadError;
|
||||
final void Function(InAppWebViewController controller, String? url, int code,
|
||||
String message)? onLoadError;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url,
|
||||
int statusCode, String description) onLoadHttpError;
|
||||
final void Function(InAppWebViewController controller, String? url,
|
||||
int statusCode, String description)? onLoadHttpError;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, LoadedResource resource)
|
||||
InAppWebViewController controller, LoadedResource resource)?
|
||||
onLoadResource;
|
||||
|
||||
@override
|
||||
final Future<CustomSchemeResponse> Function(
|
||||
InAppWebViewController controller, String scheme, String url)
|
||||
final Future<CustomSchemeResponse?> Function(
|
||||
InAppWebViewController controller, String scheme, String url)?
|
||||
onLoadResourceCustomScheme;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
final void Function(InAppWebViewController controller, String? url)?
|
||||
onLoadStart;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url) onLoadStop;
|
||||
final void Function(InAppWebViewController controller, String? url)? onLoadStop;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller,
|
||||
InAppWebViewHitTestResult hitTestResult) onLongPressHitTestResult;
|
||||
InAppWebViewHitTestResult hitTestResult)? onLongPressHitTestResult;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url) onPrint;
|
||||
final void Function(InAppWebViewController controller, String? url)? onPrint;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, int progress)
|
||||
final void Function(InAppWebViewController controller, int progress)?
|
||||
onProgressChanged;
|
||||
|
||||
@override
|
||||
final Future<ClientCertResponse> Function(
|
||||
InAppWebViewController controller, ClientCertChallenge challenge)
|
||||
final Future<ClientCertResponse?> Function(
|
||||
InAppWebViewController controller, ClientCertChallenge challenge)?
|
||||
onReceivedClientCertRequest;
|
||||
|
||||
@override
|
||||
final Future<HttpAuthResponse> Function(
|
||||
InAppWebViewController controller, HttpAuthChallenge challenge)
|
||||
final Future<HttpAuthResponse?> Function(
|
||||
InAppWebViewController controller, HttpAuthChallenge challenge)?
|
||||
onReceivedHttpAuthRequest;
|
||||
|
||||
@override
|
||||
final Future<ServerTrustAuthResponse> Function(
|
||||
InAppWebViewController controller, ServerTrustChallenge challenge)
|
||||
final Future<ServerTrustAuthResponse?> Function(
|
||||
InAppWebViewController controller, ServerTrustChallenge challenge)?
|
||||
onReceivedServerTrustAuthRequest;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, int x, int y)
|
||||
final void Function(InAppWebViewController controller, int x, int y)?
|
||||
onScrollChanged;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, String url, bool androidIsReload)
|
||||
InAppWebViewController controller, String? url, bool? androidIsReload)?
|
||||
onUpdateVisitedHistory;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) onWebViewCreated;
|
||||
final void Function(InAppWebViewController controller)? onWebViewCreated;
|
||||
|
||||
@override
|
||||
final Future<AjaxRequest> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
final Future<AjaxRequest?> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)?
|
||||
shouldInterceptAjaxRequest;
|
||||
|
||||
@override
|
||||
final Future<FetchRequest> Function(
|
||||
InAppWebViewController controller, FetchRequest fetchRequest)
|
||||
final Future<FetchRequest?> Function(
|
||||
InAppWebViewController controller, FetchRequest fetchRequest)?
|
||||
shouldInterceptFetchRequest;
|
||||
|
||||
@override
|
||||
final Future<ShouldOverrideUrlLoadingAction> Function(
|
||||
final Future<ShouldOverrideUrlLoadingAction?> Function(
|
||||
InAppWebViewController controller,
|
||||
ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest)
|
||||
ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest)?
|
||||
shouldOverrideUrlLoading;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) onEnterFullscreen;
|
||||
final void Function(InAppWebViewController controller)? onEnterFullscreen;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) onExitFullscreen;
|
||||
final void Function(InAppWebViewController controller)? onExitFullscreen;
|
||||
|
||||
@override
|
||||
final Future<WebResourceResponse> Function(
|
||||
InAppWebViewController controller, WebResourceRequest request)
|
||||
final Future<WebResourceResponse?> Function(
|
||||
InAppWebViewController controller, WebResourceRequest request)?
|
||||
androidShouldInterceptRequest;
|
||||
|
||||
@override
|
||||
final Future<WebViewRenderProcessAction> Function(
|
||||
InAppWebViewController controller, String url)
|
||||
final Future<WebViewRenderProcessAction?> Function(
|
||||
InAppWebViewController controller, String? url)?
|
||||
androidOnRenderProcessUnresponsive;
|
||||
|
||||
@override
|
||||
final Future<WebViewRenderProcessAction> Function(
|
||||
InAppWebViewController controller, String url)
|
||||
final Future<WebViewRenderProcessAction?> Function(
|
||||
InAppWebViewController controller, String? url)?
|
||||
androidOnRenderProcessResponsive;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, RenderProcessGoneDetail detail)
|
||||
InAppWebViewController controller, RenderProcessGoneDetail detail)?
|
||||
androidOnRenderProcessGone;
|
||||
|
||||
@override
|
||||
final Future<FormResubmissionAction> Function(
|
||||
InAppWebViewController controller, String url) androidOnFormResubmission;
|
||||
final Future<FormResubmissionAction?> Function(
|
||||
InAppWebViewController controller, String? url)? androidOnFormResubmission;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, double oldScale, double newScale)
|
||||
InAppWebViewController controller, double oldScale, double newScale)?
|
||||
androidOnScaleChanged;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, Uint8List icon)
|
||||
final void Function(InAppWebViewController controller, Uint8List icon)?
|
||||
androidOnReceivedIcon;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, String url, bool precomposed)
|
||||
InAppWebViewController controller, String url, bool precomposed)?
|
||||
androidOnReceivedTouchIconUrl;
|
||||
|
||||
@override
|
||||
final Future<JsBeforeUnloadResponse> Function(
|
||||
final Future<JsBeforeUnloadResponse?> Function(
|
||||
InAppWebViewController controller,
|
||||
JsBeforeUnloadRequest jsBeforeUnloadRequest) androidOnJsBeforeUnload;
|
||||
JsBeforeUnloadRequest jsBeforeUnloadRequest)? androidOnJsBeforeUnload;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, LoginRequest loginRequest)
|
||||
InAppWebViewController controller, LoginRequest loginRequest)?
|
||||
androidOnReceivedLoginRequest;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'types.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
|
@ -11,19 +9,19 @@ import 'package:flutter/services.dart';
|
|||
///[WebViewDatabase](https://developer.android.com/reference/android/webkit/WebViewDatabase)
|
||||
///doesn't offer the same functionalities as iOS `URLCredentialStorage`.
|
||||
class HttpAuthCredentialDatabase {
|
||||
static HttpAuthCredentialDatabase _instance;
|
||||
static HttpAuthCredentialDatabase? _instance;
|
||||
static const MethodChannel _channel = const MethodChannel(
|
||||
'com.pichillilorenzo/flutter_inappwebview_credential_database');
|
||||
|
||||
///Gets the database shared instance.
|
||||
static HttpAuthCredentialDatabase instance() {
|
||||
return (_instance != null) ? _instance : _init();
|
||||
return (_instance != null) ? _instance! : _init();
|
||||
}
|
||||
|
||||
static HttpAuthCredentialDatabase _init() {
|
||||
_channel.setMethodCallHandler(_handleMethod);
|
||||
_instance = HttpAuthCredentialDatabase();
|
||||
return _instance;
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
static Future<dynamic> _handleMethod(MethodCall call) async {}
|
||||
|
@ -59,7 +57,7 @@ class HttpAuthCredentialDatabase {
|
|||
|
||||
///Gets all the HTTP auth credentials saved for that [protectionSpace].
|
||||
Future<List<HttpAuthCredential>> getHttpAuthCredentials(
|
||||
{@required ProtectionSpace protectionSpace}) async {
|
||||
{required ProtectionSpace protectionSpace}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("host", () => protectionSpace.host);
|
||||
args.putIfAbsent("protocol", () => protectionSpace.protocol);
|
||||
|
@ -77,8 +75,8 @@ class HttpAuthCredentialDatabase {
|
|||
|
||||
///Saves an HTTP auth [credential] for that [protectionSpace].
|
||||
Future<void> setHttpAuthCredential(
|
||||
{@required ProtectionSpace protectionSpace,
|
||||
@required HttpAuthCredential credential}) async {
|
||||
{required ProtectionSpace protectionSpace,
|
||||
required HttpAuthCredential credential}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("host", () => protectionSpace.host);
|
||||
args.putIfAbsent("protocol", () => protectionSpace.protocol);
|
||||
|
@ -91,8 +89,8 @@ class HttpAuthCredentialDatabase {
|
|||
|
||||
///Removes an HTTP auth [credential] for that [protectionSpace].
|
||||
Future<void> removeHttpAuthCredential(
|
||||
{@required ProtectionSpace protectionSpace,
|
||||
@required HttpAuthCredential credential}) async {
|
||||
{required ProtectionSpace protectionSpace,
|
||||
required HttpAuthCredential credential}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("host", () => protectionSpace.host);
|
||||
args.putIfAbsent("protocol", () => protectionSpace.protocol);
|
||||
|
@ -105,7 +103,7 @@ class HttpAuthCredentialDatabase {
|
|||
|
||||
///Removes all the HTTP auth credentials saved for that [protectionSpace].
|
||||
Future<void> removeHttpAuthCredentials(
|
||||
{@required ProtectionSpace protectionSpace}) async {
|
||||
{required ProtectionSpace protectionSpace}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("host", () => protectionSpace.host);
|
||||
args.putIfAbsent("protocol", () => protectionSpace.protocol);
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'dart:async';
|
|||
import 'dart:collection';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
import 'context_menu.dart';
|
||||
|
@ -15,23 +14,23 @@ import 'types.dart';
|
|||
///The [webViewController] field can be used to access the [InAppWebViewController] API.
|
||||
class InAppBrowser {
|
||||
///Browser's UUID.
|
||||
String uuid;
|
||||
late String uuid;
|
||||
|
||||
///Context menu used by the browser. It should be set before opening the browser.
|
||||
ContextMenu contextMenu;
|
||||
ContextMenu? contextMenu;
|
||||
|
||||
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap =
|
||||
HashMap<String, JavaScriptHandlerCallback>();
|
||||
bool _isOpened = false;
|
||||
MethodChannel _channel;
|
||||
late MethodChannel _channel;
|
||||
static const MethodChannel _sharedChannel =
|
||||
const MethodChannel('com.pichillilorenzo/flutter_inappbrowser');
|
||||
|
||||
/// WebView Controller that can be used to access the [InAppWebViewController] API.
|
||||
InAppWebViewController webViewController;
|
||||
late InAppWebViewController webViewController;
|
||||
|
||||
///The window id of a [CreateWindowRequest.windowId].
|
||||
final int windowId;
|
||||
final int? windowId;
|
||||
|
||||
///
|
||||
InAppBrowser({this.windowId}) {
|
||||
|
@ -67,10 +66,10 @@ class InAppBrowser {
|
|||
///
|
||||
///[options]: Options for the [InAppBrowser].
|
||||
Future<void> openUrl(
|
||||
{@required String url,
|
||||
{required String url,
|
||||
Map<String, String> headers = const {},
|
||||
InAppBrowserClassOptions options}) async {
|
||||
assert(url != null && url.isNotEmpty);
|
||||
InAppBrowserClassOptions? options}) async {
|
||||
assert(url.isNotEmpty);
|
||||
this.throwIsAlreadyOpened(message: 'Cannot open $url!');
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -117,10 +116,10 @@ class InAppBrowser {
|
|||
///
|
||||
///[options]: Options for the [InAppBrowser].
|
||||
Future<void> openFile(
|
||||
{@required String assetFilePath,
|
||||
{required String assetFilePath,
|
||||
Map<String, String> headers = const {},
|
||||
InAppBrowserClassOptions options}) async {
|
||||
assert(assetFilePath != null && assetFilePath.isNotEmpty);
|
||||
InAppBrowserClassOptions? options}) async {
|
||||
assert(assetFilePath.isNotEmpty);
|
||||
this.throwIsAlreadyOpened(message: 'Cannot open $assetFilePath!');
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -143,14 +142,12 @@ class InAppBrowser {
|
|||
///
|
||||
///The [options] parameter specifies the options for the [InAppBrowser].
|
||||
Future<void> openData(
|
||||
{@required String data,
|
||||
{required String data,
|
||||
String mimeType = "text/html",
|
||||
String encoding = "utf8",
|
||||
String baseUrl = "about:blank",
|
||||
String androidHistoryUrl = "about:blank",
|
||||
InAppBrowserClassOptions options}) async {
|
||||
assert(data != null);
|
||||
|
||||
InAppBrowserClassOptions? options}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('uuid', () => uuid);
|
||||
args.putIfAbsent('options', () => options?.toMap() ?? {});
|
||||
|
@ -165,8 +162,8 @@ class InAppBrowser {
|
|||
}
|
||||
|
||||
///This is a static method that opens an [url] in the system browser. You wont be able to use the [InAppBrowser] methods here!
|
||||
static Future<void> openWithSystemBrowser({@required String url}) async {
|
||||
assert(url != null && url.isNotEmpty);
|
||||
static Future<void> openWithSystemBrowser({required String url}) async {
|
||||
assert(url.isNotEmpty);
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('url', () => url);
|
||||
return await _sharedChannel.invokeMethod('openWithSystemBrowser', args);
|
||||
|
@ -202,24 +199,24 @@ class InAppBrowser {
|
|||
}
|
||||
|
||||
///Sets the [InAppBrowser] options with the new [options] and evaluates them.
|
||||
Future<void> setOptions({@required InAppBrowserClassOptions options}) async {
|
||||
Future<void> setOptions({required InAppBrowserClassOptions options}) async {
|
||||
this.throwIsNotOpened();
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('options', () => options?.toMap() ?? {});
|
||||
args.putIfAbsent('options', () => options.toMap());
|
||||
await _channel.invokeMethod('setOptions', args);
|
||||
}
|
||||
|
||||
///Gets the current [InAppBrowser] options. Returns `null` if it wasn't able to get them.
|
||||
Future<InAppBrowserClassOptions> getOptions() async {
|
||||
Future<InAppBrowserClassOptions?> getOptions() async {
|
||||
this.throwIsNotOpened();
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
||||
Map<dynamic, dynamic> options =
|
||||
Map<dynamic, dynamic>? options =
|
||||
await _channel.invokeMethod('getOptions', args);
|
||||
if (options != null) {
|
||||
options = options.cast<String, dynamic>();
|
||||
return InAppBrowserClassOptions.fromMap(options);
|
||||
return InAppBrowserClassOptions.fromMap(options as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -241,21 +238,21 @@ class InAppBrowser {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageStarted(android.webkit.WebView,%20java.lang.String,%20android.graphics.Bitmap)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455621-webview
|
||||
void onLoadStart(String url) {}
|
||||
void onLoadStart(String? url) {}
|
||||
|
||||
///Event fired when the [InAppBrowser] finishes loading an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageFinished(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview
|
||||
void onLoadStop(String url) {}
|
||||
void onLoadStop(String? url) {}
|
||||
|
||||
///Event fired when the [InAppBrowser] encounters an error loading an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedError(android.webkit.WebView,%20int,%20java.lang.String,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455623-webview
|
||||
void onLoadError(String url, int code, String message) {}
|
||||
void onLoadError(String? url, int code, String message) {}
|
||||
|
||||
///Event fired when the [InAppBrowser] main page receives an HTTP error.
|
||||
///
|
||||
|
@ -270,7 +267,7 @@ class InAppBrowser {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedHttpError(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20android.webkit.WebResourceResponse)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview
|
||||
void onLoadHttpError(String url, int statusCode, String description) {}
|
||||
void onLoadHttpError(String? url, int statusCode, String description) {}
|
||||
|
||||
///Event fired when the current [progress] (range 0-100) of loading a page is changed.
|
||||
///
|
||||
|
@ -297,8 +294,7 @@ class InAppBrowser {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#shouldOverrideUrlLoading(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455641-webview
|
||||
// ignore: missing_return
|
||||
Future<ShouldOverrideUrlLoadingAction> shouldOverrideUrlLoading(
|
||||
Future<ShouldOverrideUrlLoadingAction?>? shouldOverrideUrlLoading(
|
||||
ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest) {}
|
||||
|
||||
///Event fired when the [InAppBrowser] webview loads a resource.
|
||||
|
@ -335,8 +331,7 @@ class InAppBrowser {
|
|||
///[url] represents the url of the request.
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkurlschemehandler
|
||||
// ignore: missing_return
|
||||
Future<CustomSchemeResponse> onLoadResourceCustomScheme(
|
||||
Future<CustomSchemeResponse?>? onLoadResourceCustomScheme(
|
||||
String scheme, String url) {}
|
||||
|
||||
///Event fired when the [InAppBrowser] webview requests the host application to create a new window,
|
||||
|
@ -369,8 +364,7 @@ class InAppBrowser {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onCreateWindow(android.webkit.WebView,%20boolean,%20boolean,%20android.os.Message)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1536907-webview
|
||||
// ignore: missing_return
|
||||
Future<bool> onCreateWindow(CreateWindowRequest createWindowRequest) {}
|
||||
Future<bool?>? onCreateWindow(CreateWindowRequest createWindowRequest) {}
|
||||
|
||||
///Event fired when the host application should close the given WebView and remove it from the view system if necessary.
|
||||
///At this point, WebCore has stopped any loading in this window and has removed any cross-scripting ability in javascript.
|
||||
|
@ -396,8 +390,7 @@ class InAppBrowser {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsAlert(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1537406-webview
|
||||
// ignore: missing_return
|
||||
Future<JsAlertResponse> onJsAlert(JsAlertRequest jsAlertRequest) {}
|
||||
Future<JsAlertResponse?>? onJsAlert(JsAlertRequest jsAlertRequest) {}
|
||||
|
||||
///Event fired when javascript calls the `confirm()` method to display a confirm dialog.
|
||||
///If [JsConfirmResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
|
@ -407,8 +400,7 @@ class InAppBrowser {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsConfirm(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1536489-webview
|
||||
// ignore: missing_return
|
||||
Future<JsConfirmResponse> onJsConfirm(JsConfirmRequest jsConfirmRequest) {}
|
||||
Future<JsConfirmResponse?>? onJsConfirm(JsConfirmRequest jsConfirmRequest) {}
|
||||
|
||||
///Event fired when javascript calls the `prompt()` method to display a prompt dialog.
|
||||
///If [JsPromptResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
|
@ -418,8 +410,7 @@ class InAppBrowser {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsPrompt(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20java.lang.String,%20android.webkit.JsPromptResult)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1538086-webview
|
||||
// ignore: missing_return
|
||||
Future<JsPromptResponse> onJsPrompt(JsPromptRequest jsPromptRequest) {}
|
||||
Future<JsPromptResponse?>? onJsPrompt(JsPromptRequest jsPromptRequest) {}
|
||||
|
||||
///Event fired when the WebView received an HTTP authentication request. The default behavior is to cancel the request.
|
||||
///
|
||||
|
@ -428,8 +419,7 @@ class InAppBrowser {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedHttpAuthRequest(android.webkit.WebView,%20android.webkit.HttpAuthHandler,%20java.lang.String,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview
|
||||
// ignore: missing_return
|
||||
Future<HttpAuthResponse> onReceivedHttpAuthRequest(
|
||||
Future<HttpAuthResponse?>? onReceivedHttpAuthRequest(
|
||||
HttpAuthChallenge challenge) {}
|
||||
|
||||
///Event fired when the WebView need to perform server trust authentication (certificate validation).
|
||||
|
@ -440,8 +430,7 @@ class InAppBrowser {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedSslError(android.webkit.WebView,%20android.webkit.SslErrorHandler,%20android.net.http.SslError)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview
|
||||
// ignore: missing_return
|
||||
Future<ServerTrustAuthResponse> onReceivedServerTrustAuthRequest(
|
||||
Future<ServerTrustAuthResponse?>? onReceivedServerTrustAuthRequest(
|
||||
ServerTrustChallenge challenge) {}
|
||||
|
||||
///Notify the host application to handle an SSL client certificate request.
|
||||
|
@ -454,8 +443,7 @@ class InAppBrowser {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedClientCertRequest(android.webkit.WebView,%20android.webkit.ClientCertRequest)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview
|
||||
// ignore: missing_return
|
||||
Future<ClientCertResponse> onReceivedClientCertRequest(
|
||||
Future<ClientCertResponse?>? onReceivedClientCertRequest(
|
||||
ClientCertChallenge challenge) {}
|
||||
|
||||
///Event fired as find-on-page operations progress.
|
||||
|
@ -477,8 +465,7 @@ class InAppBrowser {
|
|||
///[ajaxRequest] represents the `XMLHttpRequest`.
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptAjaxRequest] option to `true`.
|
||||
// ignore: missing_return
|
||||
Future<AjaxRequest> shouldInterceptAjaxRequest(AjaxRequest ajaxRequest) {}
|
||||
Future<AjaxRequest?>? shouldInterceptAjaxRequest(AjaxRequest ajaxRequest) {}
|
||||
|
||||
///Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes.
|
||||
///It gives the host application a chance to abort the request.
|
||||
|
@ -486,8 +473,7 @@ class InAppBrowser {
|
|||
///[ajaxRequest] represents the [XMLHttpRequest].
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptAjaxRequest] option to `true`.
|
||||
// ignore: missing_return
|
||||
Future<AjaxRequestAction> onAjaxReadyStateChange(AjaxRequest ajaxRequest) {}
|
||||
Future<AjaxRequestAction?>? onAjaxReadyStateChange(AjaxRequest ajaxRequest) {}
|
||||
|
||||
///Event fired as an `XMLHttpRequest` progress.
|
||||
///It gives the host application a chance to abort the request.
|
||||
|
@ -495,8 +481,7 @@ class InAppBrowser {
|
|||
///[ajaxRequest] represents the [XMLHttpRequest].
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptAjaxRequest] option to `true`.
|
||||
// ignore: missing_return
|
||||
Future<AjaxRequestAction> onAjaxProgress(AjaxRequest ajaxRequest) {}
|
||||
Future<AjaxRequestAction?>? onAjaxProgress(AjaxRequest ajaxRequest) {}
|
||||
|
||||
///Event fired when a request is sent to a server through [Fetch API](https://developer.mozilla.org/it/docs/Web/API/Fetch_API).
|
||||
///It gives the host application a chance to take control over the request before sending it.
|
||||
|
@ -504,8 +489,7 @@ class InAppBrowser {
|
|||
///[fetchRequest] represents a resource request.
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptFetchRequest] option to `true`.
|
||||
// ignore: missing_return
|
||||
Future<FetchRequest> shouldInterceptFetchRequest(FetchRequest fetchRequest) {}
|
||||
Future<FetchRequest?>? shouldInterceptFetchRequest(FetchRequest fetchRequest) {}
|
||||
|
||||
///Event fired when the host application updates its visited links database.
|
||||
///This event is also fired when the navigation state of the [InAppWebView] changes through the usage of
|
||||
|
@ -517,14 +501,14 @@ class InAppBrowser {
|
|||
///[androidIsReload] indicates if this url is being reloaded. Available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#doUpdateVisitedHistory(android.webkit.WebView,%20java.lang.String,%20boolean)
|
||||
void onUpdateVisitedHistory(String url, bool androidIsReload) {}
|
||||
void onUpdateVisitedHistory(String? url, bool? androidIsReload) {}
|
||||
|
||||
///Event fired when `window.print()` is called from JavaScript side.
|
||||
///
|
||||
///[url] represents the url on which is called.
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
void onPrint(String url) {}
|
||||
void onPrint(String? url) {}
|
||||
|
||||
///Event fired when an HTML element of the webview has been clicked and held.
|
||||
///
|
||||
|
@ -559,14 +543,14 @@ class InAppBrowser {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageCommitVisible(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455635-webview
|
||||
void onPageCommitVisible(String url) {}
|
||||
void onPageCommitVisible(String? url) {}
|
||||
|
||||
///Event fired when a change in the document title occurred.
|
||||
///
|
||||
///[title] represents the string containing the new title of the document.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onReceivedTitle(android.webkit.WebView,%20java.lang.String)
|
||||
void onTitleChanged(String title) {}
|
||||
void onTitleChanged(String? title) {}
|
||||
|
||||
///Event fired when the WebView notifies that a loading URL has been flagged by Safe Browsing.
|
||||
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
|
||||
|
@ -578,9 +562,8 @@ class InAppBrowser {
|
|||
///**NOTE**: available only on Android 27+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onSafeBrowsingHit(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20int,%20android.webkit.SafeBrowsingResponse)
|
||||
// ignore: missing_return
|
||||
Future<SafeBrowsingResponse> androidOnSafeBrowsingHit(
|
||||
String url, SafeBrowsingThreat threatType) {}
|
||||
Future<SafeBrowsingResponse?>? androidOnSafeBrowsingHit(
|
||||
String url, SafeBrowsingThreat? threatType) {}
|
||||
|
||||
///Event fired when the WebView is requesting permission to access the specified resources and the permission currently isn't granted or denied.
|
||||
///
|
||||
|
@ -591,8 +574,7 @@ class InAppBrowser {
|
|||
///**NOTE**: available only on Android 23+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onPermissionRequest(android.webkit.PermissionRequest)
|
||||
// ignore: missing_return
|
||||
Future<PermissionRequestResponse> androidOnPermissionRequest(
|
||||
Future<PermissionRequestResponse?>? androidOnPermissionRequest(
|
||||
String origin, List<String> resources) {}
|
||||
|
||||
///Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin.
|
||||
|
@ -604,8 +586,7 @@ class InAppBrowser {
|
|||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onGeolocationPermissionsShowPrompt(java.lang.String,%20android.webkit.GeolocationPermissions.Callback)
|
||||
Future<GeolocationPermissionShowPromptResponse>
|
||||
// ignore: missing_return
|
||||
Future<GeolocationPermissionShowPromptResponse?>?
|
||||
androidOnGeolocationPermissionsShowPrompt(String origin) {}
|
||||
|
||||
///Notify the host application that a request for Geolocation permissions, made with a previous call to [androidOnGeolocationPermissionsShowPrompt] has been canceled.
|
||||
|
@ -633,8 +614,7 @@ class InAppBrowser {
|
|||
///**Official Android API**:
|
||||
///- https://developer.android.com/reference/android/webkit/WebViewClient#shouldInterceptRequest(android.webkit.WebView,%20android.webkit.WebResourceRequest)
|
||||
///- https://developer.android.com/reference/android/webkit/WebViewClient#shouldInterceptRequest(android.webkit.WebView,%20java.lang.String)
|
||||
Future<WebResourceResponse>
|
||||
// ignore: missing_return
|
||||
Future<WebResourceResponse?>?
|
||||
androidShouldInterceptRequest(WebResourceRequest request) {}
|
||||
|
||||
///Event called when the renderer currently associated with the WebView becomes unresponsive as a result of a long running blocking task such as the execution of JavaScript.
|
||||
|
@ -655,9 +635,8 @@ class InAppBrowser {
|
|||
///**NOTE**: available only on Android 29+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewRenderProcessClient#onRenderProcessUnresponsive(android.webkit.WebView,%20android.webkit.WebViewRenderProcess)
|
||||
Future<WebViewRenderProcessAction>
|
||||
// ignore: missing_return
|
||||
androidOnRenderProcessUnresponsive(String url) {}
|
||||
Future<WebViewRenderProcessAction?>?
|
||||
androidOnRenderProcessUnresponsive(String? url) {}
|
||||
|
||||
///Event called once when an unresponsive renderer currently associated with the WebView becomes responsive.
|
||||
///
|
||||
|
@ -670,9 +649,8 @@ class InAppBrowser {
|
|||
///**NOTE**: available only on Android 29+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewRenderProcessClient#onRenderProcessResponsive(android.webkit.WebView,%20android.webkit.WebViewRenderProcess)
|
||||
Future<WebViewRenderProcessAction>
|
||||
// ignore: missing_return
|
||||
androidOnRenderProcessResponsive(String url) {}
|
||||
Future<WebViewRenderProcessAction?>?
|
||||
androidOnRenderProcessResponsive(String? url) {}
|
||||
|
||||
///Event fired when the given WebView's render process has exited.
|
||||
///The application's implementation of this callback should only attempt to clean up the WebView.
|
||||
|
@ -690,9 +668,8 @@ class InAppBrowser {
|
|||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onFormResubmission(android.webkit.WebView,%20android.os.Message,%20android.os.Message)
|
||||
Future<FormResubmissionAction>
|
||||
// ignore: missing_return
|
||||
androidOnFormResubmission(String url) {}
|
||||
Future<FormResubmissionAction?>?
|
||||
androidOnFormResubmission(String? url) {}
|
||||
|
||||
///Event fired when the scale applied to the WebView has changed.
|
||||
///
|
||||
|
@ -746,8 +723,7 @@ class InAppBrowser {
|
|||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsBeforeUnload(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult)
|
||||
// ignore: missing_return
|
||||
Future<JsBeforeUnloadResponse> androidOnJsBeforeUnload(
|
||||
Future<JsBeforeUnloadResponse?>? androidOnJsBeforeUnload(
|
||||
JsBeforeUnloadRequest jsBeforeUnloadRequest) {}
|
||||
|
||||
///Event fired when a request to automatically log in the user has been processed.
|
||||
|
|
|
@ -6,7 +6,7 @@ import 'package:mime/mime.dart';
|
|||
|
||||
///This class allows you to create a simple server on `http://localhost:[port]/` in order to be able to load your assets file on a server. The default [port] value is `8080`.
|
||||
class InAppLocalhostServer {
|
||||
HttpServer _server;
|
||||
HttpServer? _server;
|
||||
int _port = 8080;
|
||||
|
||||
InAppLocalhostServer({int port = 8080}) {
|
||||
|
@ -38,7 +38,7 @@ class InAppLocalhostServer {
|
|||
this._server = server;
|
||||
|
||||
server.listen((HttpRequest request) async {
|
||||
var body = List<int>();
|
||||
var body = [] as List<int>;
|
||||
var path = request.requestedUri.path;
|
||||
path = (path.startsWith('/')) ? path.substring(1) : path;
|
||||
path += (path.endsWith('/')) ? 'index.html' : '';
|
||||
|
@ -77,7 +77,7 @@ class InAppLocalhostServer {
|
|||
///Closes the server.
|
||||
Future<void> close() async {
|
||||
if (this._server != null) {
|
||||
await this._server.close(force: true);
|
||||
await this._server!.close(force: true);
|
||||
print('Server running on http://localhost:$_port closed');
|
||||
this._server = null;
|
||||
}
|
||||
|
|
|
@ -22,13 +22,13 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
/// recognizers on this list.
|
||||
/// When `gestureRecognizers` is empty or null, the web view will only handle pointer events for gestures that
|
||||
/// were not claimed by any other gesture recognizer.
|
||||
final Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers;
|
||||
final Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers;
|
||||
|
||||
///The window id of a [CreateWindowRequest.windowId].
|
||||
final int windowId;
|
||||
final int? windowId;
|
||||
|
||||
const InAppWebView({
|
||||
Key key,
|
||||
Key? key,
|
||||
this.windowId,
|
||||
this.initialUrl = "about:blank",
|
||||
this.initialFile,
|
||||
|
@ -94,248 +94,248 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
_InAppWebViewState createState() => _InAppWebViewState();
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)?
|
||||
androidOnGeolocationPermissionsHidePrompt;
|
||||
|
||||
@override
|
||||
final Future<GeolocationPermissionShowPromptResponse> Function(
|
||||
InAppWebViewController controller, String origin)
|
||||
final Future<GeolocationPermissionShowPromptResponse?> Function(
|
||||
InAppWebViewController controller, String origin)?
|
||||
androidOnGeolocationPermissionsShowPrompt;
|
||||
|
||||
@override
|
||||
final Future<PermissionRequestResponse> Function(
|
||||
final Future<PermissionRequestResponse?> Function(
|
||||
InAppWebViewController controller,
|
||||
String origin,
|
||||
List<String> resources) androidOnPermissionRequest;
|
||||
List<String> resources)? androidOnPermissionRequest;
|
||||
|
||||
@override
|
||||
final Future<SafeBrowsingResponse> Function(InAppWebViewController controller,
|
||||
String url, SafeBrowsingThreat threatType) androidOnSafeBrowsingHit;
|
||||
final Future<SafeBrowsingResponse?> Function(InAppWebViewController controller,
|
||||
String url, SafeBrowsingThreat? threatType)? androidOnSafeBrowsingHit;
|
||||
|
||||
@override
|
||||
final InAppWebViewInitialData initialData;
|
||||
final InAppWebViewInitialData? initialData;
|
||||
|
||||
@override
|
||||
final String initialFile;
|
||||
final String? initialFile;
|
||||
|
||||
@override
|
||||
final Map<String, String> initialHeaders;
|
||||
final Map<String, String>? initialHeaders;
|
||||
|
||||
@override
|
||||
final InAppWebViewGroupOptions initialOptions;
|
||||
final InAppWebViewGroupOptions? initialOptions;
|
||||
|
||||
@override
|
||||
final String initialUrl;
|
||||
final String? initialUrl;
|
||||
|
||||
@override
|
||||
final ContextMenu contextMenu;
|
||||
final ContextMenu? contextMenu;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
final void Function(InAppWebViewController controller, String? url)?
|
||||
onPageCommitVisible;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String title)
|
||||
final void Function(InAppWebViewController controller, String? title)?
|
||||
onTitleChanged;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)?
|
||||
iosOnDidReceiveServerRedirectForProvisionalNavigation;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)?
|
||||
iosOnWebContentProcessDidTerminate;
|
||||
|
||||
@override
|
||||
final Future<AjaxRequestAction> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)?
|
||||
onAjaxProgress;
|
||||
|
||||
@override
|
||||
final Future<AjaxRequestAction> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
final Future<AjaxRequestAction?> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)?
|
||||
onAjaxReadyStateChange;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, ConsoleMessage consoleMessage)
|
||||
InAppWebViewController controller, ConsoleMessage consoleMessage)?
|
||||
onConsoleMessage;
|
||||
|
||||
@override
|
||||
final Future<bool> Function(InAppWebViewController controller,
|
||||
CreateWindowRequest createWindowRequest) onCreateWindow;
|
||||
final Future<bool?> Function(InAppWebViewController controller,
|
||||
CreateWindowRequest createWindowRequest)? onCreateWindow;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) onCloseWindow;
|
||||
final void Function(InAppWebViewController controller)? onCloseWindow;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) onWindowFocus;
|
||||
final void Function(InAppWebViewController controller)? onWindowFocus;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) onWindowBlur;
|
||||
final void Function(InAppWebViewController controller)? onWindowBlur;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) androidOnRequestFocus;
|
||||
final void Function(InAppWebViewController controller)? androidOnRequestFocus;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, Uint8List icon)
|
||||
final void Function(InAppWebViewController controller, Uint8List icon)?
|
||||
androidOnReceivedIcon;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, String url, bool precomposed)
|
||||
InAppWebViewController controller, String url, bool precomposed)?
|
||||
androidOnReceivedTouchIconUrl;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
final void Function(InAppWebViewController controller, String url)?
|
||||
onDownloadStart;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, int activeMatchOrdinal,
|
||||
int numberOfMatches, bool isDoneCounting) onFindResultReceived;
|
||||
int numberOfMatches, bool isDoneCounting)? onFindResultReceived;
|
||||
|
||||
@override
|
||||
final Future<JsAlertResponse> Function(
|
||||
InAppWebViewController controller, JsAlertRequest jsAlertRequest)
|
||||
final Future<JsAlertResponse?> Function(
|
||||
InAppWebViewController controller, JsAlertRequest jsAlertRequest)?
|
||||
onJsAlert;
|
||||
|
||||
@override
|
||||
final Future<JsConfirmResponse> Function(
|
||||
InAppWebViewController controller, JsConfirmRequest jsConfirmRequest)
|
||||
final Future<JsConfirmResponse?> Function(
|
||||
InAppWebViewController controller, JsConfirmRequest jsConfirmRequest)?
|
||||
onJsConfirm;
|
||||
|
||||
@override
|
||||
final Future<JsPromptResponse> Function(
|
||||
InAppWebViewController controller, JsPromptRequest jsPromptRequest)
|
||||
final Future<JsPromptResponse?> Function(
|
||||
InAppWebViewController controller, JsPromptRequest jsPromptRequest)?
|
||||
onJsPrompt;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url, int code,
|
||||
String message) onLoadError;
|
||||
final void Function(InAppWebViewController controller, String? url, int code,
|
||||
String message)? onLoadError;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url,
|
||||
int statusCode, String description) onLoadHttpError;
|
||||
final void Function(InAppWebViewController controller, String? url,
|
||||
int statusCode, String description)? onLoadHttpError;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, LoadedResource resource)
|
||||
InAppWebViewController controller, LoadedResource resource)?
|
||||
onLoadResource;
|
||||
|
||||
@override
|
||||
final Future<CustomSchemeResponse> Function(
|
||||
InAppWebViewController controller, String scheme, String url)
|
||||
final Future<CustomSchemeResponse?> Function(
|
||||
InAppWebViewController controller, String scheme, String url)?
|
||||
onLoadResourceCustomScheme;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
final void Function(InAppWebViewController controller, String? url)?
|
||||
onLoadStart;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url) onLoadStop;
|
||||
final void Function(InAppWebViewController controller, String? url)? onLoadStop;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller,
|
||||
InAppWebViewHitTestResult hitTestResult) onLongPressHitTestResult;
|
||||
InAppWebViewHitTestResult hitTestResult)? onLongPressHitTestResult;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url) onPrint;
|
||||
final void Function(InAppWebViewController controller, String? url)? onPrint;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, int progress)
|
||||
final void Function(InAppWebViewController controller, int progress)?
|
||||
onProgressChanged;
|
||||
|
||||
@override
|
||||
final Future<ClientCertResponse> Function(
|
||||
InAppWebViewController controller, ClientCertChallenge challenge)
|
||||
final Future<ClientCertResponse?> Function(
|
||||
InAppWebViewController controller, ClientCertChallenge challenge)?
|
||||
onReceivedClientCertRequest;
|
||||
|
||||
@override
|
||||
final Future<HttpAuthResponse> Function(
|
||||
InAppWebViewController controller, HttpAuthChallenge challenge)
|
||||
final Future<HttpAuthResponse?> Function(
|
||||
InAppWebViewController controller, HttpAuthChallenge challenge)?
|
||||
onReceivedHttpAuthRequest;
|
||||
|
||||
@override
|
||||
final Future<ServerTrustAuthResponse> Function(
|
||||
InAppWebViewController controller, ServerTrustChallenge challenge)
|
||||
final Future<ServerTrustAuthResponse?> Function(
|
||||
InAppWebViewController controller, ServerTrustChallenge challenge)?
|
||||
onReceivedServerTrustAuthRequest;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, int x, int y)
|
||||
final void Function(InAppWebViewController controller, int x, int y)?
|
||||
onScrollChanged;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, String url, bool androidIsReload)
|
||||
InAppWebViewController controller, String? url, bool? androidIsReload)?
|
||||
onUpdateVisitedHistory;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) onWebViewCreated;
|
||||
final void Function(InAppWebViewController controller)? onWebViewCreated;
|
||||
|
||||
@override
|
||||
final Future<AjaxRequest> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
final Future<AjaxRequest?> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)?
|
||||
shouldInterceptAjaxRequest;
|
||||
|
||||
@override
|
||||
final Future<FetchRequest> Function(
|
||||
InAppWebViewController controller, FetchRequest fetchRequest)
|
||||
final Future<FetchRequest?> Function(
|
||||
InAppWebViewController controller, FetchRequest fetchRequest)?
|
||||
shouldInterceptFetchRequest;
|
||||
|
||||
@override
|
||||
final Future<ShouldOverrideUrlLoadingAction> Function(
|
||||
final Future<ShouldOverrideUrlLoadingAction?> Function(
|
||||
InAppWebViewController controller,
|
||||
ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest)
|
||||
ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest)?
|
||||
shouldOverrideUrlLoading;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) onEnterFullscreen;
|
||||
final void Function(InAppWebViewController controller)? onEnterFullscreen;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) onExitFullscreen;
|
||||
final void Function(InAppWebViewController controller)? onExitFullscreen;
|
||||
|
||||
@override
|
||||
final Future<WebResourceResponse> Function(
|
||||
InAppWebViewController controller, WebResourceRequest request)
|
||||
final Future<WebResourceResponse?> Function(
|
||||
InAppWebViewController controller, WebResourceRequest request)?
|
||||
androidShouldInterceptRequest;
|
||||
|
||||
@override
|
||||
final Future<WebViewRenderProcessAction> Function(
|
||||
InAppWebViewController controller, String url)
|
||||
final Future<WebViewRenderProcessAction?> Function(
|
||||
InAppWebViewController controller, String? url)?
|
||||
androidOnRenderProcessUnresponsive;
|
||||
|
||||
@override
|
||||
final Future<WebViewRenderProcessAction> Function(
|
||||
InAppWebViewController controller, String url)
|
||||
final Future<WebViewRenderProcessAction?> Function(
|
||||
InAppWebViewController controller, String? url)?
|
||||
androidOnRenderProcessResponsive;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, RenderProcessGoneDetail detail)
|
||||
InAppWebViewController controller, RenderProcessGoneDetail detail)?
|
||||
androidOnRenderProcessGone;
|
||||
|
||||
@override
|
||||
final Future<FormResubmissionAction> Function(
|
||||
InAppWebViewController controller, String url) androidOnFormResubmission;
|
||||
final Future<FormResubmissionAction?> Function(
|
||||
InAppWebViewController controller, String? url)? androidOnFormResubmission;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, double oldScale, double newScale)
|
||||
InAppWebViewController controller, double oldScale, double newScale)?
|
||||
androidOnScaleChanged;
|
||||
|
||||
@override
|
||||
final Future<JsBeforeUnloadResponse> Function(
|
||||
final Future<JsBeforeUnloadResponse?> Function(
|
||||
InAppWebViewController controller,
|
||||
JsBeforeUnloadRequest jsBeforeUnloadRequest) androidOnJsBeforeUnload;
|
||||
JsBeforeUnloadRequest jsBeforeUnloadRequest)? androidOnJsBeforeUnload;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, LoginRequest loginRequest)
|
||||
InAppWebViewController controller, LoginRequest loginRequest)?
|
||||
androidOnReceivedLoginRequest;
|
||||
}
|
||||
|
||||
class _InAppWebViewState extends State<InAppWebView> {
|
||||
InAppWebViewController _controller;
|
||||
late InAppWebViewController _controller;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -348,7 +348,7 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||
PlatformViewController controller,
|
||||
) {
|
||||
return AndroidViewSurface(
|
||||
controller: controller,
|
||||
controller: controller as AndroidViewController,
|
||||
gestureRecognizers: widget.gestureRecognizers ?? const <Factory<OneSequenceGestureRecognizer>>{},
|
||||
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
||||
);
|
||||
|
@ -359,7 +359,7 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||
viewType: 'com.pichillilorenzo/flutter_inappwebview',
|
||||
layoutDirection: TextDirection.rtl,
|
||||
creationParams: <String, dynamic>{
|
||||
'initialUrl': '${Uri.parse(widget.initialUrl)}',
|
||||
'initialUrl': widget.initialUrl != null ? '${Uri.parse(widget.initialUrl!)}' : '',
|
||||
'initialFile': widget.initialFile,
|
||||
'initialData': widget.initialData?.toMap(),
|
||||
'initialHeaders': widget.initialHeaders,
|
||||
|
@ -381,7 +381,7 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||
gestureRecognizers: widget.gestureRecognizers,
|
||||
layoutDirection: TextDirection.rtl,
|
||||
creationParams: <String, dynamic>{
|
||||
'initialUrl': '${Uri.parse(widget.initialUrl)}',
|
||||
'initialUrl': widget.initialUrl != null ? '${Uri.parse(widget.initialUrl!)}' : '',
|
||||
'initialFile': widget.initialFile,
|
||||
'initialData': widget.initialData?.toMap(),
|
||||
'initialHeaders': widget.initialHeaders,
|
||||
|
@ -398,7 +398,7 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||
onPlatformViewCreated: _onPlatformViewCreated,
|
||||
gestureRecognizers: widget.gestureRecognizers,
|
||||
creationParams: <String, dynamic>{
|
||||
'initialUrl': '${Uri.parse(widget.initialUrl)}',
|
||||
'initialUrl': widget.initialUrl != null ? '${Uri.parse(widget.initialUrl!)}' : '',
|
||||
'initialFile': widget.initialFile,
|
||||
'initialData': widget.initialData?.toMap(),
|
||||
'initialHeaders': widget.initialHeaders,
|
||||
|
@ -426,7 +426,7 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||
void _onPlatformViewCreated(int id) {
|
||||
_controller = InAppWebViewController(id, widget);
|
||||
if (widget.onWebViewCreated != null) {
|
||||
widget.onWebViewCreated(_controller);
|
||||
widget.onWebViewCreated!(_controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@ import 'dart:math';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class Util {
|
||||
static Color convertColorFromStringRepresentation(String colorValue) {
|
||||
static Color? convertColorFromStringRepresentation(String colorValue) {
|
||||
if (colorValue.startsWith("#")) {
|
||||
return Util.getColorFromHex(colorValue);
|
||||
} else if (colorValue.startsWith("rgb(")) {
|
||||
|
@ -391,7 +391,7 @@ class Util {
|
|||
rgbaValues[0], rgbaValues[1], rgbaValues[2], hlsaValues[3]);
|
||||
}
|
||||
|
||||
static List<num> hslToRgb(double h, double s, double l) {
|
||||
static List<int> hslToRgb(double h, double s, double l) {
|
||||
double r, g, b;
|
||||
|
||||
if (s == 0) {
|
||||
|
@ -407,8 +407,8 @@ class Util {
|
|||
return rgb;
|
||||
}
|
||||
|
||||
static num to255(double v) {
|
||||
return min(255, 256 * v);
|
||||
static int to255(double v) {
|
||||
return min(255, (256 * v).round());
|
||||
}
|
||||
|
||||
/// Helper method that converts hue to rgb
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'in_app_webview_controller.dart';
|
||||
import 'types.dart';
|
||||
|
||||
|
@ -14,13 +12,13 @@ class WebStorage {
|
|||
///Represents `window.sessionStorage`.
|
||||
SessionStorage sessionStorage;
|
||||
|
||||
WebStorage({@required this.localStorage, @required this.sessionStorage});
|
||||
WebStorage({required this.localStorage, required this.sessionStorage});
|
||||
}
|
||||
|
||||
///Class that represents a single web storage item of the JavaScript `window.sessionStorage` and `window.localStorage` objects.
|
||||
class WebStorageItem {
|
||||
///Item key.
|
||||
String key;
|
||||
String? key;
|
||||
|
||||
///Item value.
|
||||
dynamic value;
|
||||
|
@ -47,18 +45,17 @@ class WebStorageItem {
|
|||
///Class that provides methods to manage the JavaScript [Storage](https://developer.mozilla.org/en-US/docs/Web/API/Storage) object.
|
||||
///It is used by [LocalStorage] and [SessionStorage].
|
||||
class Storage {
|
||||
InAppWebViewController _controller;
|
||||
late InAppWebViewController _controller;
|
||||
|
||||
///The web storage type: `window.sessionStorage` or `window.localStorage`.
|
||||
WebStorageType webStorageType;
|
||||
|
||||
Storage(InAppWebViewController controller, this.webStorageType) {
|
||||
assert(controller != null && this.webStorageType != null);
|
||||
this._controller = controller;
|
||||
}
|
||||
|
||||
///Returns an integer representing the number of data items stored in the Storage object.
|
||||
Future<int> length() async {
|
||||
Future<int?> length() async {
|
||||
var result = await _controller.evaluateJavascript(source: """
|
||||
window.$webStorageType.length;
|
||||
""");
|
||||
|
@ -66,7 +63,7 @@ class Storage {
|
|||
}
|
||||
|
||||
///When passed a [key] name and [value], will add that key to the storage, or update that key's value if it already exists.
|
||||
Future<void> setItem({@required String key, @required dynamic value}) async {
|
||||
Future<void> setItem({required String key, required dynamic value}) async {
|
||||
var encodedValue = json.encode(value);
|
||||
await _controller.evaluateJavascript(source: """
|
||||
window.$webStorageType.setItem("$key", ${value is String ? encodedValue : "JSON.stringify($encodedValue)"});
|
||||
|
@ -74,7 +71,7 @@ class Storage {
|
|||
}
|
||||
|
||||
///When passed a [key] name, will return that key's value, or `null` if the key does not exist, in the given Storage object.
|
||||
Future<dynamic> getItem({@required String key}) async {
|
||||
Future<dynamic> getItem({required String key}) async {
|
||||
var itemValue = await _controller.evaluateJavascript(source: """
|
||||
window.$webStorageType.getItem("$key");
|
||||
""");
|
||||
|
@ -91,7 +88,7 @@ class Storage {
|
|||
}
|
||||
|
||||
///When passed a [key] name, will remove that key from the given Storage object if it exists.
|
||||
Future<void> removeItem({@required String key}) async {
|
||||
Future<void> removeItem({required String key}) async {
|
||||
await _controller.evaluateJavascript(source: """
|
||||
window.$webStorageType.removeItem("$key");
|
||||
""");
|
||||
|
@ -139,7 +136,7 @@ class Storage {
|
|||
|
||||
///When passed a number [index], returns the name of the nth key in a given Storage object.
|
||||
///The order of keys is user-agent defined, so you should not rely on it.
|
||||
Future<String> key({@required int index}) async {
|
||||
Future<String> key({required int index}) async {
|
||||
var result = await _controller.evaluateJavascript(source: """
|
||||
window.$webStorageType.key($index);
|
||||
""");
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'types.dart';
|
||||
|
@ -11,7 +10,7 @@ import 'types.dart';
|
|||
///
|
||||
///**NOTE for iOS**: available from iOS 9.0+.
|
||||
class WebStorageManager {
|
||||
static WebStorageManager _instance;
|
||||
static WebStorageManager? _instance;
|
||||
static const MethodChannel _channel = const MethodChannel(
|
||||
'com.pichillilorenzo/flutter_inappwebview_webstoragemanager');
|
||||
|
||||
|
@ -20,13 +19,13 @@ class WebStorageManager {
|
|||
|
||||
///Gets the WebStorage manager shared instance.
|
||||
static WebStorageManager instance() {
|
||||
return (_instance != null) ? _instance : _init();
|
||||
return (_instance != null) ? _instance! : _init();
|
||||
}
|
||||
|
||||
static WebStorageManager _init() {
|
||||
_channel.setMethodCallHandler(_handleMethod);
|
||||
_instance = new WebStorageManager();
|
||||
return _instance;
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
static Future<dynamic> _handleMethod(MethodCall call) async {}
|
||||
|
@ -63,8 +62,7 @@ class AndroidWebStorageManager {
|
|||
|
||||
///Clears the storage currently being used by both the Application Cache and Web SQL Database APIs by the given [origin].
|
||||
///The origin is specified using its string representation.
|
||||
Future<void> deleteOrigin({@required String origin}) async {
|
||||
assert(origin != null);
|
||||
Future<void> deleteOrigin({required String origin}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("origin", () => origin);
|
||||
await WebStorageManager._channel.invokeMethod('deleteOrigin', args);
|
||||
|
@ -73,8 +71,7 @@ class AndroidWebStorageManager {
|
|||
///Gets the storage quota for the Web SQL Database API for the given [origin].
|
||||
///The quota is given in bytes and the origin is specified using its string representation.
|
||||
///Note that a quota is not enforced on a per-origin basis for the Application Cache API.
|
||||
Future<int> getQuotaForOrigin({@required String origin}) async {
|
||||
assert(origin != null);
|
||||
Future<int> getQuotaForOrigin({required String origin}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("origin", () => origin);
|
||||
return await WebStorageManager._channel
|
||||
|
@ -83,8 +80,7 @@ class AndroidWebStorageManager {
|
|||
|
||||
///Gets the amount of storage currently being used by both the Application Cache and Web SQL Database APIs by the given [origin].
|
||||
///The amount is given in bytes and the origin is specified using its string representation.
|
||||
Future<int> getUsageForOrigin({@required String origin}) async {
|
||||
assert(origin != null);
|
||||
Future<int> getUsageForOrigin({required String origin}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("origin", () => origin);
|
||||
return await WebStorageManager._channel
|
||||
|
@ -101,8 +97,7 @@ class IOSWebStorageManager {
|
|||
///
|
||||
///[dataTypes] represents the website data types to fetch records for.
|
||||
Future<List<IOSWKWebsiteDataRecord>> fetchDataRecords(
|
||||
{@required Set<IOSWKWebsiteDataType> dataTypes}) async {
|
||||
assert(dataTypes != null);
|
||||
{required Set<IOSWKWebsiteDataType> dataTypes}) async {
|
||||
List<IOSWKWebsiteDataRecord> recordList = [];
|
||||
List<String> dataTypesList = [];
|
||||
for (var dataType in dataTypes) {
|
||||
|
@ -116,8 +111,11 @@ class IOSWebStorageManager {
|
|||
for (var record in records) {
|
||||
List<String> dataTypesString = record["dataTypes"].cast<String>();
|
||||
Set<IOSWKWebsiteDataType> dataTypes = Set();
|
||||
for (var dataType in dataTypesString) {
|
||||
dataTypes.add(IOSWKWebsiteDataType.fromValue(dataType));
|
||||
for (var dataTypeValue in dataTypesString) {
|
||||
var dataType = IOSWKWebsiteDataType.fromValue(dataTypeValue);
|
||||
if (dataType != null) {
|
||||
dataTypes.add(dataType);
|
||||
}
|
||||
}
|
||||
recordList.add(IOSWKWebsiteDataRecord(
|
||||
displayName: record["displayName"], dataTypes: dataTypes));
|
||||
|
@ -131,10 +129,8 @@ class IOSWebStorageManager {
|
|||
///
|
||||
///[dataRecords] represents the website data records to delete website data for.
|
||||
Future<void> removeDataFor(
|
||||
{@required Set<IOSWKWebsiteDataType> dataTypes,
|
||||
@required List<IOSWKWebsiteDataRecord> dataRecords}) async {
|
||||
assert(dataTypes != null && dataRecords != null);
|
||||
|
||||
{required Set<IOSWKWebsiteDataType> dataTypes,
|
||||
required List<IOSWKWebsiteDataRecord> dataRecords}) async {
|
||||
List<String> dataTypesList = [];
|
||||
for (var dataType in dataTypes) {
|
||||
dataTypesList.add(dataType.toValue());
|
||||
|
@ -157,10 +153,8 @@ class IOSWebStorageManager {
|
|||
///
|
||||
///[date] represents a date. All website data modified after this date will be removed.
|
||||
Future<void> removeDataModifiedSince(
|
||||
{@required Set<IOSWKWebsiteDataType> dataTypes,
|
||||
@required DateTime date}) async {
|
||||
assert(dataTypes != null && date != null);
|
||||
|
||||
{required Set<IOSWKWebsiteDataType> dataTypes,
|
||||
required DateTime date}) async {
|
||||
List<String> dataTypesList = [];
|
||||
for (var dataType in dataTypes) {
|
||||
dataTypesList.add(dataType.toValue());
|
||||
|
|
|
@ -7,20 +7,20 @@ import 'in_app_webview_controller.dart';
|
|||
import 'webview_options.dart';
|
||||
import 'headless_in_app_webview.dart';
|
||||
|
||||
///Abstract class that represents a WebView. Used by [WebView] and [HeadlessInAppWebView].
|
||||
///Abstract class that represents a WebView. Used by [InAppWebView] and [HeadlessInAppWebView].
|
||||
abstract class WebView {
|
||||
///The window id of a [CreateWindowRequest.windowId].
|
||||
final int windowId;
|
||||
final int? windowId;
|
||||
|
||||
///Event fired when the [WebView] is created.
|
||||
final void Function(InAppWebViewController controller) onWebViewCreated;
|
||||
final void Function(InAppWebViewController controller)? onWebViewCreated;
|
||||
|
||||
///Event fired when the [WebView] starts to load an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageStarted(android.webkit.WebView,%20java.lang.String,%20android.graphics.Bitmap)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455621-webview
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
final void Function(InAppWebViewController controller, String? url)?
|
||||
onLoadStart;
|
||||
|
||||
///Event fired when the [WebView] finishes loading an [url].
|
||||
|
@ -28,15 +28,15 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageFinished(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview
|
||||
final void Function(InAppWebViewController controller, String url) onLoadStop;
|
||||
final void Function(InAppWebViewController controller, String? url)? onLoadStop;
|
||||
|
||||
///Event fired when the [WebView] encounters an error loading an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedError(android.webkit.WebView,%20int,%20java.lang.String,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455623-webview
|
||||
final void Function(InAppWebViewController controller, String url, int code,
|
||||
String message) onLoadError;
|
||||
final void Function(InAppWebViewController controller, String? url, int code,
|
||||
String message)? onLoadError;
|
||||
|
||||
///Event fired when the [WebView] main page receives an HTTP error.
|
||||
///
|
||||
|
@ -51,20 +51,20 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedHttpError(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20android.webkit.WebResourceResponse)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview
|
||||
final void Function(InAppWebViewController controller, String url,
|
||||
int statusCode, String description) onLoadHttpError;
|
||||
final void Function(InAppWebViewController controller, String? url,
|
||||
int statusCode, String description)? onLoadHttpError;
|
||||
|
||||
///Event fired when the current [progress] of loading a page is changed.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onProgressChanged(android.webkit.WebView,%20int)
|
||||
final void Function(InAppWebViewController controller, int progress)
|
||||
final void Function(InAppWebViewController controller, int progress)?
|
||||
onProgressChanged;
|
||||
|
||||
///Event fired when the [WebView] receives a [ConsoleMessage].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onConsoleMessage(android.webkit.ConsoleMessage)
|
||||
final void Function(
|
||||
InAppWebViewController controller, ConsoleMessage consoleMessage)
|
||||
InAppWebViewController controller, ConsoleMessage consoleMessage)?
|
||||
onConsoleMessage;
|
||||
|
||||
///Give the host application a chance to take control when a URL is about to be loaded in the current WebView. This event is not called on the initial load of the WebView.
|
||||
|
@ -82,16 +82,16 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#shouldOverrideUrlLoading(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455641-webview
|
||||
final Future<ShouldOverrideUrlLoadingAction> Function(
|
||||
final Future<ShouldOverrideUrlLoadingAction?> Function(
|
||||
InAppWebViewController controller,
|
||||
ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest)
|
||||
ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest)?
|
||||
shouldOverrideUrlLoading;
|
||||
|
||||
///Event fired when the [WebView] loads a resource.
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnLoadResource] and [InAppWebViewOptions.javaScriptEnabled] options to `true`.
|
||||
final void Function(
|
||||
InAppWebViewController controller, LoadedResource resource)
|
||||
InAppWebViewController controller, LoadedResource resource)?
|
||||
onLoadResource;
|
||||
|
||||
///Event fired when the [WebView] scrolls.
|
||||
|
@ -103,7 +103,7 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#onScrollChanged(int,%20int,%20int,%20int)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollviewdelegate/1619392-scrollviewdidscroll
|
||||
final void Function(InAppWebViewController controller, int x, int y)
|
||||
final void Function(InAppWebViewController controller, int x, int y)?
|
||||
onScrollChanged;
|
||||
|
||||
///Event fired when [WebView] recognizes a downloadable file.
|
||||
|
@ -116,7 +116,7 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#setDownloadListener(android.webkit.DownloadListener)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
final void Function(InAppWebViewController controller, String url)?
|
||||
onDownloadStart;
|
||||
|
||||
///Event fired when the [WebView] finds the `custom-scheme` while loading a resource. Here you can handle the url request and return a [CustomSchemeResponse] to load a specific resource encoded to `base64`.
|
||||
|
@ -126,8 +126,8 @@ abstract class WebView {
|
|||
///[url] represents the url of the request.
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkurlschemehandler
|
||||
final Future<CustomSchemeResponse> Function(
|
||||
InAppWebViewController controller, String scheme, String url)
|
||||
final Future<CustomSchemeResponse?> Function(
|
||||
InAppWebViewController controller, String scheme, String url)?
|
||||
onLoadResourceCustomScheme;
|
||||
|
||||
///Event fired when the [WebView] requests the host application to create a new window,
|
||||
|
@ -160,8 +160,8 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onCreateWindow(android.webkit.WebView,%20boolean,%20boolean,%20android.os.Message)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1536907-webview
|
||||
final Future<bool> Function(InAppWebViewController controller,
|
||||
CreateWindowRequest createWindowRequest) onCreateWindow;
|
||||
final Future<bool?> Function(InAppWebViewController controller,
|
||||
CreateWindowRequest createWindowRequest)? onCreateWindow;
|
||||
|
||||
///Event fired when the host application should close the given WebView and remove it from the view system if necessary.
|
||||
///At this point, WebCore has stopped any loading in this window and has removed any cross-scripting ability in javascript.
|
||||
|
@ -169,15 +169,15 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onCloseWindow(android.webkit.WebView)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1537390-webviewdidclose
|
||||
final void Function(InAppWebViewController controller) onCloseWindow;
|
||||
final void Function(InAppWebViewController controller)? onCloseWindow;
|
||||
|
||||
///Event fired when the JavaScript `window` object of the WebView has received focus.
|
||||
///This is the result of the `focus` JavaScript event applied to the `window` object.
|
||||
final void Function(InAppWebViewController controller) onWindowFocus;
|
||||
final void Function(InAppWebViewController controller)? onWindowFocus;
|
||||
|
||||
///Event fired when the JavaScript `window` object of the WebView has lost focus.
|
||||
///This is the result of the `blur` JavaScript event applied to the `window` object.
|
||||
final void Function(InAppWebViewController controller) onWindowBlur;
|
||||
final void Function(InAppWebViewController controller)? onWindowBlur;
|
||||
|
||||
///Event fired when javascript calls the `alert()` method to display an alert dialog.
|
||||
///If [JsAlertResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
|
@ -187,8 +187,8 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsAlert(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1537406-webview
|
||||
final Future<JsAlertResponse> Function(
|
||||
InAppWebViewController controller, JsAlertRequest jsAlertRequest)
|
||||
final Future<JsAlertResponse?> Function(
|
||||
InAppWebViewController controller, JsAlertRequest jsAlertRequest)?
|
||||
onJsAlert;
|
||||
|
||||
///Event fired when javascript calls the `confirm()` method to display a confirm dialog.
|
||||
|
@ -199,8 +199,8 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsConfirm(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1536489-webview
|
||||
final Future<JsConfirmResponse> Function(
|
||||
InAppWebViewController controller, JsConfirmRequest jsConfirmRequest)
|
||||
final Future<JsConfirmResponse?> Function(
|
||||
InAppWebViewController controller, JsConfirmRequest jsConfirmRequest)?
|
||||
onJsConfirm;
|
||||
|
||||
///Event fired when javascript calls the `prompt()` method to display a prompt dialog.
|
||||
|
@ -211,8 +211,8 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsPrompt(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20java.lang.String,%20android.webkit.JsPromptResult)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkuidelegate/1538086-webview
|
||||
final Future<JsPromptResponse> Function(
|
||||
InAppWebViewController controller, JsPromptRequest jsPromptRequest)
|
||||
final Future<JsPromptResponse?> Function(
|
||||
InAppWebViewController controller, JsPromptRequest jsPromptRequest)?
|
||||
onJsPrompt;
|
||||
|
||||
///Event fired when the WebView received an HTTP authentication request. The default behavior is to cancel the request.
|
||||
|
@ -222,8 +222,8 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedHttpAuthRequest(android.webkit.WebView,%20android.webkit.HttpAuthHandler,%20java.lang.String,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview
|
||||
final Future<HttpAuthResponse> Function(
|
||||
InAppWebViewController controller, HttpAuthChallenge challenge)
|
||||
final Future<HttpAuthResponse?> Function(
|
||||
InAppWebViewController controller, HttpAuthChallenge challenge)?
|
||||
onReceivedHttpAuthRequest;
|
||||
|
||||
///Event fired when the WebView need to perform server trust authentication (certificate validation).
|
||||
|
@ -234,8 +234,8 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedSslError(android.webkit.WebView,%20android.webkit.SslErrorHandler,%20android.net.http.SslError)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview
|
||||
final Future<ServerTrustAuthResponse> Function(
|
||||
InAppWebViewController controller, ServerTrustChallenge challenge)
|
||||
final Future<ServerTrustAuthResponse?> Function(
|
||||
InAppWebViewController controller, ServerTrustChallenge challenge)?
|
||||
onReceivedServerTrustAuthRequest;
|
||||
|
||||
///Notify the host application to handle an SSL client certificate request.
|
||||
|
@ -248,8 +248,8 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedClientCertRequest(android.webkit.WebView,%20android.webkit.ClientCertRequest)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview
|
||||
final Future<ClientCertResponse> Function(
|
||||
InAppWebViewController controller, ClientCertChallenge challenge)
|
||||
final Future<ClientCertResponse?> Function(
|
||||
InAppWebViewController controller, ClientCertChallenge challenge)?
|
||||
onReceivedClientCertRequest;
|
||||
|
||||
///Event fired as find-on-page operations progress.
|
||||
|
@ -263,7 +263,7 @@ abstract class WebView {
|
|||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#setFindListener(android.webkit.WebView.FindListener)
|
||||
final void Function(InAppWebViewController controller, int activeMatchOrdinal,
|
||||
int numberOfMatches, bool isDoneCounting) onFindResultReceived;
|
||||
int numberOfMatches, bool isDoneCounting)? onFindResultReceived;
|
||||
|
||||
///Event fired when an `XMLHttpRequest` is sent to a server.
|
||||
///It gives the host application a chance to take control over the request before sending it.
|
||||
|
@ -275,8 +275,8 @@ abstract class WebView {
|
|||
///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code
|
||||
///used to intercept ajax requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms).
|
||||
///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the ajax requests will be intercept for sure.
|
||||
final Future<AjaxRequest> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
final Future<AjaxRequest?> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)?
|
||||
shouldInterceptAjaxRequest;
|
||||
|
||||
///Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes.
|
||||
|
@ -289,8 +289,8 @@ abstract class WebView {
|
|||
///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code
|
||||
///used to intercept ajax requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms).
|
||||
///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the ajax requests will be intercept for sure.
|
||||
final Future<AjaxRequestAction> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
final Future<AjaxRequestAction?> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)?
|
||||
onAjaxReadyStateChange;
|
||||
|
||||
///Event fired as an `XMLHttpRequest` progress.
|
||||
|
@ -303,8 +303,8 @@ abstract class WebView {
|
|||
///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code
|
||||
///used to intercept ajax requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms).
|
||||
///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the ajax requests will be intercept for sure.
|
||||
final Future<AjaxRequestAction> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
final Future<AjaxRequestAction?> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)?
|
||||
onAjaxProgress;
|
||||
|
||||
///Event fired when a request is sent to a server through [Fetch API](https://developer.mozilla.org/it/docs/Web/API/Fetch_API).
|
||||
|
@ -317,8 +317,8 @@ abstract class WebView {
|
|||
///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code
|
||||
///used to intercept fetch requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms).
|
||||
///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the fetch requests will be intercept for sure.
|
||||
final Future<FetchRequest> Function(
|
||||
InAppWebViewController controller, FetchRequest fetchRequest)
|
||||
final Future<FetchRequest?> Function(
|
||||
InAppWebViewController controller, FetchRequest fetchRequest)?
|
||||
shouldInterceptFetchRequest;
|
||||
|
||||
///Event fired when the host application updates its visited links database.
|
||||
|
@ -332,7 +332,7 @@ abstract class WebView {
|
|||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#doUpdateVisitedHistory(android.webkit.WebView,%20java.lang.String,%20boolean)
|
||||
final void Function(
|
||||
InAppWebViewController controller, String url, bool androidIsReload)
|
||||
InAppWebViewController controller, String? url, bool? androidIsReload)?
|
||||
onUpdateVisitedHistory;
|
||||
|
||||
///Event fired when `window.print()` is called from JavaScript side.
|
||||
|
@ -340,7 +340,7 @@ abstract class WebView {
|
|||
///[url] represents the url on which is called.
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
final void Function(InAppWebViewController controller, String url) onPrint;
|
||||
final void Function(InAppWebViewController controller, String? url)? onPrint;
|
||||
|
||||
///Event fired when an HTML element of the webview has been clicked and held.
|
||||
///
|
||||
|
@ -350,21 +350,21 @@ abstract class WebView {
|
|||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uilongpressgesturerecognizer
|
||||
final void Function(InAppWebViewController controller,
|
||||
InAppWebViewHitTestResult hitTestResult) onLongPressHitTestResult;
|
||||
InAppWebViewHitTestResult hitTestResult)? onLongPressHitTestResult;
|
||||
|
||||
///Event fired when the current page has entered full screen mode.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onShowCustomView(android.view.View,%20android.webkit.WebChromeClient.CustomViewCallback)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiwindow/1621621-didbecomevisiblenotification
|
||||
final void Function(InAppWebViewController controller) onEnterFullscreen;
|
||||
final void Function(InAppWebViewController controller)? onEnterFullscreen;
|
||||
|
||||
///Event fired when the current page has exited full screen mode.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onHideCustomView()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiwindow/1621617-didbecomehiddennotification
|
||||
final void Function(InAppWebViewController controller) onExitFullscreen;
|
||||
final void Function(InAppWebViewController controller)? onExitFullscreen;
|
||||
|
||||
///Called when the web view begins to receive web content.
|
||||
///
|
||||
|
@ -376,7 +376,7 @@ abstract class WebView {
|
|||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageCommitVisible(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455635-webview
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
final void Function(InAppWebViewController controller, String? url)?
|
||||
onPageCommitVisible;
|
||||
|
||||
///Event fired when a change in the document title occurred.
|
||||
|
@ -384,7 +384,7 @@ abstract class WebView {
|
|||
///[title] represents the string containing the new title of the document.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onReceivedTitle(android.webkit.WebView,%20java.lang.String)
|
||||
final void Function(InAppWebViewController controller, String title)
|
||||
final void Function(InAppWebViewController controller, String? title)?
|
||||
onTitleChanged;
|
||||
|
||||
///Event fired when the webview notifies that a loading URL has been flagged by Safe Browsing.
|
||||
|
@ -397,8 +397,8 @@ abstract class WebView {
|
|||
///**NOTE**: available only on Android 27+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onSafeBrowsingHit(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20int,%20android.webkit.SafeBrowsingResponse)
|
||||
final Future<SafeBrowsingResponse> Function(InAppWebViewController controller,
|
||||
String url, SafeBrowsingThreat threatType) androidOnSafeBrowsingHit;
|
||||
final Future<SafeBrowsingResponse?> Function(InAppWebViewController controller,
|
||||
String url, SafeBrowsingThreat? threatType)? androidOnSafeBrowsingHit;
|
||||
|
||||
///Event fired when the WebView is requesting permission to access the specified resources and the permission currently isn't granted or denied.
|
||||
///
|
||||
|
@ -409,10 +409,10 @@ abstract class WebView {
|
|||
///**NOTE**: available only on Android 23+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onPermissionRequest(android.webkit.PermissionRequest)
|
||||
final Future<PermissionRequestResponse> Function(
|
||||
final Future<PermissionRequestResponse?> Function(
|
||||
InAppWebViewController controller,
|
||||
String origin,
|
||||
List<String> resources) androidOnPermissionRequest;
|
||||
List<String> resources)? androidOnPermissionRequest;
|
||||
|
||||
///Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin.
|
||||
///Note that for applications targeting Android N and later SDKs (API level > `Build.VERSION_CODES.M`) this method is only called for requests originating from secure origins such as https.
|
||||
|
@ -423,8 +423,8 @@ abstract class WebView {
|
|||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onGeolocationPermissionsShowPrompt(java.lang.String,%20android.webkit.GeolocationPermissions.Callback)
|
||||
final Future<GeolocationPermissionShowPromptResponse> Function(
|
||||
InAppWebViewController controller, String origin)
|
||||
final Future<GeolocationPermissionShowPromptResponse?> Function(
|
||||
InAppWebViewController controller, String origin)?
|
||||
androidOnGeolocationPermissionsShowPrompt;
|
||||
|
||||
///Notify the host application that a request for Geolocation permissions, made with a previous call to [androidOnGeolocationPermissionsShowPrompt] has been canceled.
|
||||
|
@ -433,7 +433,7 @@ abstract class WebView {
|
|||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onGeolocationPermissionsHidePrompt()
|
||||
final void Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)?
|
||||
androidOnGeolocationPermissionsHidePrompt;
|
||||
|
||||
///Notify the host application of a resource request and allow the application to return the data.
|
||||
|
@ -453,8 +453,8 @@ abstract class WebView {
|
|||
///**Official Android API**:
|
||||
///- https://developer.android.com/reference/android/webkit/WebViewClient#shouldInterceptRequest(android.webkit.WebView,%20android.webkit.WebResourceRequest)
|
||||
///- https://developer.android.com/reference/android/webkit/WebViewClient#shouldInterceptRequest(android.webkit.WebView,%20java.lang.String)
|
||||
final Future<WebResourceResponse> Function(
|
||||
InAppWebViewController controller, WebResourceRequest request)
|
||||
final Future<WebResourceResponse?> Function(
|
||||
InAppWebViewController controller, WebResourceRequest request)?
|
||||
androidShouldInterceptRequest;
|
||||
|
||||
///Event called when the renderer currently associated with the WebView becomes unresponsive as a result of a long running blocking task such as the execution of JavaScript.
|
||||
|
@ -475,8 +475,8 @@ abstract class WebView {
|
|||
///**NOTE**: available only on Android 29+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewRenderProcessClient#onRenderProcessUnresponsive(android.webkit.WebView,%20android.webkit.WebViewRenderProcess)
|
||||
final Future<WebViewRenderProcessAction> Function(
|
||||
InAppWebViewController controller, String url)
|
||||
final Future<WebViewRenderProcessAction?> Function(
|
||||
InAppWebViewController controller, String? url)?
|
||||
androidOnRenderProcessUnresponsive;
|
||||
|
||||
///Event called once when an unresponsive renderer currently associated with the WebView becomes responsive.
|
||||
|
@ -490,8 +490,8 @@ abstract class WebView {
|
|||
///**NOTE**: available only on Android 29+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewRenderProcessClient#onRenderProcessResponsive(android.webkit.WebView,%20android.webkit.WebViewRenderProcess)
|
||||
final Future<WebViewRenderProcessAction> Function(
|
||||
InAppWebViewController controller, String url)
|
||||
final Future<WebViewRenderProcessAction?> Function(
|
||||
InAppWebViewController controller, String? url)?
|
||||
androidOnRenderProcessResponsive;
|
||||
|
||||
///Event fired when the given WebView's render process has exited.
|
||||
|
@ -504,7 +504,7 @@ abstract class WebView {
|
|||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onRenderProcessGone(android.webkit.WebView,%20android.webkit.RenderProcessGoneDetail)
|
||||
final void Function(
|
||||
InAppWebViewController controller, RenderProcessGoneDetail detail)
|
||||
InAppWebViewController controller, RenderProcessGoneDetail detail)?
|
||||
androidOnRenderProcessGone;
|
||||
|
||||
///As the host application if the browser should resend data as the requested page was a result of a POST. The default is to not resend the data.
|
||||
|
@ -512,8 +512,8 @@ abstract class WebView {
|
|||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onFormResubmission(android.webkit.WebView,%20android.os.Message,%20android.os.Message)
|
||||
final Future<FormResubmissionAction> Function(
|
||||
InAppWebViewController controller, String url) androidOnFormResubmission;
|
||||
final Future<FormResubmissionAction?> Function(
|
||||
InAppWebViewController controller, String? url)? androidOnFormResubmission;
|
||||
|
||||
///Event fired when the scale applied to the WebView has changed.
|
||||
///
|
||||
|
@ -525,7 +525,7 @@ abstract class WebView {
|
|||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onScaleChanged(android.webkit.WebView,%20float,%20float)
|
||||
final void Function(
|
||||
InAppWebViewController controller, double oldScale, double newScale)
|
||||
InAppWebViewController controller, double oldScale, double newScale)?
|
||||
androidOnScaleChanged;
|
||||
|
||||
///Event fired when there is a request to display and focus for this WebView.
|
||||
|
@ -534,7 +534,7 @@ abstract class WebView {
|
|||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onRequestFocus(android.webkit.WebView)
|
||||
final void Function(InAppWebViewController controller) androidOnRequestFocus;
|
||||
final void Function(InAppWebViewController controller)? androidOnRequestFocus;
|
||||
|
||||
///Event fired when there is new favicon for the current page.
|
||||
///
|
||||
|
@ -543,7 +543,7 @@ abstract class WebView {
|
|||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onReceivedIcon(android.webkit.WebView,%20android.graphics.Bitmap)
|
||||
final void Function(InAppWebViewController controller, Uint8List icon)
|
||||
final void Function(InAppWebViewController controller, Uint8List icon)?
|
||||
androidOnReceivedIcon;
|
||||
|
||||
///Event fired when there is an url for an apple-touch-icon.
|
||||
|
@ -556,7 +556,7 @@ abstract class WebView {
|
|||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onReceivedTouchIconUrl(android.webkit.WebView,%20java.lang.String,%20boolean)
|
||||
final void Function(
|
||||
InAppWebViewController controller, String url, bool precomposed)
|
||||
InAppWebViewController controller, String url, bool precomposed)?
|
||||
androidOnReceivedTouchIconUrl;
|
||||
|
||||
///Event fired when the client should display a dialog to confirm navigation away from the current page.
|
||||
|
@ -572,9 +572,9 @@ abstract class WebView {
|
|||
///**NOTE**: available only on Android.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onJsBeforeUnload(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult)
|
||||
final Future<JsBeforeUnloadResponse> Function(
|
||||
final Future<JsBeforeUnloadResponse?> Function(
|
||||
InAppWebViewController controller,
|
||||
JsBeforeUnloadRequest jsBeforeUnloadRequest) androidOnJsBeforeUnload;
|
||||
JsBeforeUnloadRequest jsBeforeUnloadRequest)? androidOnJsBeforeUnload;
|
||||
|
||||
///Event fired when a request to automatically log in the user has been processed.
|
||||
///
|
||||
|
@ -584,7 +584,7 @@ abstract class WebView {
|
|||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedLoginRequest(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20java.lang.String)
|
||||
final void Function(
|
||||
InAppWebViewController controller, LoginRequest loginRequest)
|
||||
InAppWebViewController controller, LoginRequest loginRequest)?
|
||||
androidOnReceivedLoginRequest;
|
||||
|
||||
///Invoked when the web view's web content process is terminated.
|
||||
|
@ -592,7 +592,7 @@ abstract class WebView {
|
|||
///**NOTE**: available only on iOS.
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455639-webviewwebcontentprocessdidtermi
|
||||
final void Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)?
|
||||
iosOnWebContentProcessDidTerminate;
|
||||
|
||||
///Called when a web view receives a server redirect.
|
||||
|
@ -600,26 +600,26 @@ abstract class WebView {
|
|||
///**NOTE**: available only on iOS.
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455627-webview
|
||||
final void Function(InAppWebViewController controller)
|
||||
final void Function(InAppWebViewController controller)?
|
||||
iosOnDidReceiveServerRedirectForProvisionalNavigation;
|
||||
|
||||
///Initial url that will be loaded.
|
||||
final String initialUrl;
|
||||
final String? initialUrl;
|
||||
|
||||
///Initial asset file that will be loaded. See [InAppWebViewController.loadFile] for explanation.
|
||||
final String initialFile;
|
||||
final String? initialFile;
|
||||
|
||||
///Initial [InAppWebViewInitialData] that will be loaded.
|
||||
final InAppWebViewInitialData initialData;
|
||||
final InAppWebViewInitialData? initialData;
|
||||
|
||||
///Initial headers that will be used.
|
||||
final Map<String, String> initialHeaders;
|
||||
final Map<String, String>? initialHeaders;
|
||||
|
||||
///Initial options that will be used.
|
||||
final InAppWebViewGroupOptions initialOptions;
|
||||
final InAppWebViewGroupOptions? initialOptions;
|
||||
|
||||
///Context menu which contains custom menu items to be shown when [ContextMenu] is presented.
|
||||
final ContextMenu contextMenu;
|
||||
final ContextMenu? contextMenu;
|
||||
|
||||
WebView(
|
||||
{this.windowId,
|
||||
|
|
|
@ -14,7 +14,7 @@ class WebViewOptions {
|
|||
}
|
||||
|
||||
static WebViewOptions fromMap(Map<String, dynamic> map) {
|
||||
return null;
|
||||
return new WebViewOptions();
|
||||
}
|
||||
|
||||
WebViewOptions copy() {
|
||||
|
@ -37,7 +37,7 @@ class BrowserOptions {
|
|||
}
|
||||
|
||||
static BrowserOptions fromMap(Map<String, dynamic> map) {
|
||||
return null;
|
||||
return new BrowserOptions();
|
||||
}
|
||||
|
||||
BrowserOptions copy() {
|
||||
|
@ -60,7 +60,7 @@ class ChromeSafariBrowserOptions {
|
|||
}
|
||||
|
||||
static ChromeSafariBrowserOptions fromMap(Map<String, dynamic> map) {
|
||||
return null;
|
||||
return new ChromeSafariBrowserOptions();
|
||||
}
|
||||
|
||||
ChromeSafariBrowserOptions copy() {
|
||||
|
@ -105,12 +105,6 @@ class InAppWebViewOptions
|
|||
///Set to `true` to enable JavaScript. The default value is `true`.
|
||||
bool javaScriptEnabled;
|
||||
|
||||
///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. The default is `false`.
|
||||
///
|
||||
///**NOTE**: on iOS the debugging mode is always enabled.
|
||||
bool debuggingEnabled;
|
||||
|
||||
///Set to `true` to allow JavaScript open windows without user interaction. The default value is `false`.
|
||||
bool javaScriptCanOpenWindowsAutomatically;
|
||||
|
||||
|
@ -120,7 +114,7 @@ class InAppWebViewOptions
|
|||
bool mediaPlaybackRequiresUserGesture;
|
||||
|
||||
///Sets the minimum font size. The default value is `8` for Android, `0` for iOS.
|
||||
int minimumFontSize;
|
||||
int? minimumFontSize;
|
||||
|
||||
///Define whether the vertical scrollbar should be drawn or not. The default value is `true`.
|
||||
bool verticalScrollBarEnabled;
|
||||
|
@ -141,7 +135,7 @@ class InAppWebViewOptions
|
|||
///Sets the content mode that the WebView needs to use when loading and rendering a webpage. The default value is [UserPreferredContentMode.RECOMMENDED].
|
||||
///
|
||||
///**NOTE**: available on iOS 13.0+.
|
||||
UserPreferredContentMode preferredContentMode;
|
||||
UserPreferredContentMode? preferredContentMode;
|
||||
|
||||
///Set to `true` to be able to listen at the [shouldInterceptAjaxRequest] event. The default value is `false`.
|
||||
bool useShouldInterceptAjaxRequest;
|
||||
|
@ -152,6 +146,8 @@ class InAppWebViewOptions
|
|||
///Set to `true` to open a browser window with incognito mode. The default value is `false`.
|
||||
///
|
||||
///**NOTE**: available on iOS 9.0+.
|
||||
///On Android, by setting this option 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.
|
||||
bool incognito;
|
||||
|
||||
///Sets whether WebView should use browser caching. The default value is `true`.
|
||||
|
@ -174,6 +170,28 @@ class InAppWebViewOptions
|
|||
///Set to `false` if the WebView should not support zooming using its on-screen zoom controls and gestures. The default value is `true`.
|
||||
bool supportZoom;
|
||||
|
||||
///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.
|
||||
///
|
||||
///Don't enable this setting if you open files that may be created or altered by external sources.
|
||||
///Enabling this setting allows malicious scripts loaded in a `file://` context to access arbitrary local files including WebView cookies and app private data.
|
||||
///
|
||||
///Note that the value of this setting is ignored if the value of [allowUniversalAccessFromFileURLs] is `true`.
|
||||
///
|
||||
///The default value is `false`.
|
||||
bool allowFileAccessFromFileURLs;
|
||||
|
||||
///Sets whether cross-origin requests in the context of a file scheme URL should be allowed to access content from any origin.
|
||||
///This includes access to content from other file scheme URLs or web contexts.
|
||||
///Note that some access such as image HTML elements doesn't follow same-origin rules and isn't affected by this setting.
|
||||
///
|
||||
///Don't enable this setting if you open files that may be created or altered by external sources.
|
||||
///Enabling this setting allows malicious scripts loaded in a `file://` context to launch cross-site scripting attacks,
|
||||
///either accessing arbitrary local files including WebView cookies, app private data or even credentials used on arbitrary web sites.
|
||||
///
|
||||
///The default value is `false`.
|
||||
bool allowUniversalAccessFromFileURLs;
|
||||
|
||||
InAppWebViewOptions(
|
||||
{this.useShouldOverrideUrlLoading = false,
|
||||
this.useOnLoadResource = false,
|
||||
|
@ -182,7 +200,6 @@ class InAppWebViewOptions
|
|||
this.userAgent = "",
|
||||
this.applicationNameForUserAgent = "",
|
||||
this.javaScriptEnabled = true,
|
||||
this.debuggingEnabled = false,
|
||||
this.javaScriptCanOpenWindowsAutomatically = false,
|
||||
this.mediaPlaybackRequiresUserGesture = true,
|
||||
this.minimumFontSize,
|
||||
|
@ -199,7 +216,9 @@ class InAppWebViewOptions
|
|||
this.disableVerticalScroll = false,
|
||||
this.disableHorizontalScroll = false,
|
||||
this.disableContextMenu = false,
|
||||
this.supportZoom = true}) {
|
||||
this.supportZoom = true,
|
||||
this.allowFileAccessFromFileURLs = false,
|
||||
this.allowUniversalAccessFromFileURLs = false}) {
|
||||
if (this.minimumFontSize == null)
|
||||
this.minimumFontSize = defaultTargetPlatform == TargetPlatform.android ? 8 : 0;
|
||||
assert(!this.resourceCustomSchemes.contains("http") &&
|
||||
|
@ -221,7 +240,6 @@ class InAppWebViewOptions
|
|||
"userAgent": userAgent,
|
||||
"applicationNameForUserAgent": applicationNameForUserAgent,
|
||||
"javaScriptEnabled": javaScriptEnabled,
|
||||
"debuggingEnabled": debuggingEnabled,
|
||||
"javaScriptCanOpenWindowsAutomatically":
|
||||
javaScriptCanOpenWindowsAutomatically,
|
||||
"mediaPlaybackRequiresUserGesture": mediaPlaybackRequiresUserGesture,
|
||||
|
@ -238,13 +256,15 @@ class InAppWebViewOptions
|
|||
"disableVerticalScroll": disableVerticalScroll,
|
||||
"disableHorizontalScroll": disableHorizontalScroll,
|
||||
"disableContextMenu": disableContextMenu,
|
||||
"supportZoom": supportZoom
|
||||
"supportZoom": supportZoom,
|
||||
"allowFileAccessFromFileURLs": allowFileAccessFromFileURLs,
|
||||
"allowUniversalAccessFromFileURLs": allowUniversalAccessFromFileURLs
|
||||
};
|
||||
}
|
||||
|
||||
static InAppWebViewOptions fromMap(Map<String, dynamic> map) {
|
||||
List<ContentBlocker> contentBlockers = [];
|
||||
List<dynamic> contentBlockersMapList = map["contentBlockers"];
|
||||
List<dynamic>? contentBlockersMapList = map["contentBlockers"];
|
||||
if (contentBlockersMapList != null) {
|
||||
contentBlockersMapList.forEach((contentBlocker) {
|
||||
contentBlockers.add(ContentBlocker.fromMap(
|
||||
|
@ -261,7 +281,6 @@ class InAppWebViewOptions
|
|||
options.userAgent = map["userAgent"];
|
||||
options.applicationNameForUserAgent = map["applicationNameForUserAgent"];
|
||||
options.javaScriptEnabled = map["javaScriptEnabled"];
|
||||
options.debuggingEnabled = map["debuggingEnabled"];
|
||||
options.javaScriptCanOpenWindowsAutomatically =
|
||||
map["javaScriptCanOpenWindowsAutomatically"];
|
||||
options.mediaPlaybackRequiresUserGesture =
|
||||
|
@ -284,6 +303,8 @@ class InAppWebViewOptions
|
|||
options.disableHorizontalScroll = map["disableHorizontalScroll"];
|
||||
options.disableContextMenu = map["disableContextMenu"];
|
||||
options.supportZoom = map["supportZoom"];
|
||||
options.allowFileAccessFromFileURLs = map["allowFileAccessFromFileURLs"];
|
||||
options.allowUniversalAccessFromFileURLs = map["allowUniversalAccessFromFileURLs"];
|
||||
return options;
|
||||
}
|
||||
|
||||
|
@ -339,28 +360,18 @@ class AndroidInAppWebViewOptions
|
|||
///Configures the WebView's behavior when a secure origin attempts to load a resource from an insecure origin.
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
AndroidMixedContentMode mixedContentMode;
|
||||
AndroidMixedContentMode? 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`.
|
||||
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`.
|
||||
///Assets and resources are still accessible using `file:///android_asset` and `file:///android_res`. The default value is `true`.
|
||||
bool allowFileAccess;
|
||||
|
||||
///Sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from other file scheme URLs.
|
||||
///Note that the value of this setting is ignored if the value of [allowFileAccessFromFileURLs] is `true`.
|
||||
///Note too, that this setting affects only JavaScript access to file scheme resources. The default value is `false`.
|
||||
bool allowFileAccessFromFileURLs;
|
||||
|
||||
///Sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from any origin.
|
||||
///Note that this setting affects only JavaScript access to file scheme resources.
|
||||
///This includes access to content from other file scheme URLs. The default value is `false`.
|
||||
bool allowUniversalAccessFromFileURLs;
|
||||
|
||||
///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.
|
||||
String appCachePath;
|
||||
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`.
|
||||
bool blockNetworkImage;
|
||||
|
@ -370,7 +381,7 @@ class AndroidInAppWebViewOptions
|
|||
|
||||
///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 [AndroidCacheMode.LOAD_DEFAULT].
|
||||
AndroidCacheMode cacheMode;
|
||||
AndroidCacheMode? cacheMode;
|
||||
|
||||
///Sets the cursive font family name. The default value is `"cursive"`.
|
||||
String cursiveFontFamily;
|
||||
|
@ -387,7 +398,7 @@ class AndroidInAppWebViewOptions
|
|||
///Disables the action mode menu items according to menuItems flag.
|
||||
///
|
||||
///**NOTE**: available on Android 24+.
|
||||
AndroidActionModeMenuItem disabledActionModeMenuItems;
|
||||
AndroidActionModeMenuItem? disabledActionModeMenuItems;
|
||||
|
||||
///Sets the fantasy font family name. The default value is `"fantasy"`.
|
||||
String fantasyFontFamily;
|
||||
|
@ -398,13 +409,13 @@ class AndroidInAppWebViewOptions
|
|||
///Set the force dark mode for this WebView. The default value is [AndroidForceDark.FORCE_DARK_OFF].
|
||||
///
|
||||
///**NOTE**: available on Android 29+.
|
||||
AndroidForceDark forceDark;
|
||||
AndroidForceDark? forceDark;
|
||||
|
||||
///Sets whether Geolocation API is enabled. The default value is `true`.
|
||||
bool geolocationEnabled;
|
||||
|
||||
///Sets the underlying layout algorithm. This will cause a re-layout of the WebView.
|
||||
AndroidLayoutAlgorithm layoutAlgorithm;
|
||||
AndroidLayoutAlgorithm? 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.
|
||||
|
@ -468,7 +479,7 @@ class AndroidInAppWebViewOptions
|
|||
|
||||
///Regular expression used by [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.
|
||||
String regexToCancelSubFramesLoading;
|
||||
String? regexToCancelSubFramesLoading;
|
||||
|
||||
///Set to `true` to enable Flutter's new Hybrid Composition. The default value is `false`.
|
||||
///Hybrid Composition is supported starting with Flutter v1.20+.
|
||||
|
@ -486,11 +497,11 @@ class AndroidInAppWebViewOptions
|
|||
///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 [AndroidOverScrollMode.OVER_SCROLL_IF_CONTENT_SCROLLS].
|
||||
AndroidOverScrollMode overScrollMode;
|
||||
AndroidOverScrollMode? 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.
|
||||
bool networkAvailable;
|
||||
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.
|
||||
|
@ -498,28 +509,28 @@ class AndroidInAppWebViewOptions
|
|||
///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 [AndroidScrollBarStyle.SCROLLBARS_INSIDE_OVERLAY].
|
||||
AndroidScrollBarStyle scrollBarStyle;
|
||||
AndroidScrollBarStyle? scrollBarStyle;
|
||||
|
||||
///Sets the position of the vertical scroll bar.
|
||||
///The default value is [AndroidVerticalScrollbarPosition.SCROLLBAR_POSITION_DEFAULT].
|
||||
AndroidVerticalScrollbarPosition verticalScrollbarPosition;
|
||||
AndroidVerticalScrollbarPosition? verticalScrollbarPosition;
|
||||
|
||||
///Defines the delay in milliseconds that a scrollbar waits before fade out.
|
||||
int scrollBarDefaultDelayBeforeFade;
|
||||
int? scrollBarDefaultDelayBeforeFade;
|
||||
|
||||
///Defines whether scrollbars will fade when the view is not scrolling.
|
||||
///The default value is `true`.
|
||||
bool scrollbarFadingEnabled;
|
||||
|
||||
///Defines the scrollbar fade duration in milliseconds.
|
||||
int scrollBarFadeDuration;
|
||||
int? scrollBarFadeDuration;
|
||||
|
||||
///Sets the renderer priority policy for this WebView.
|
||||
RendererPriorityPolicy rendererPriorityPolicy;
|
||||
RendererPriorityPolicy? rendererPriorityPolicy;
|
||||
|
||||
///Sets whether the default Android error page should be disabled.
|
||||
///The default value is `false`.
|
||||
bool disableDefaultErrorPage;
|
||||
bool? disableDefaultErrorPage;
|
||||
|
||||
AndroidInAppWebViewOptions({
|
||||
this.textZoom = 100,
|
||||
|
@ -533,8 +544,6 @@ class AndroidInAppWebViewOptions
|
|||
this.mixedContentMode,
|
||||
this.allowContentAccess = true,
|
||||
this.allowFileAccess = true,
|
||||
this.allowFileAccessFromFileURLs = false,
|
||||
this.allowUniversalAccessFromFileURLs = false,
|
||||
this.appCachePath,
|
||||
this.blockNetworkImage = false,
|
||||
this.blockNetworkLoads = false,
|
||||
|
@ -592,8 +601,6 @@ class AndroidInAppWebViewOptions
|
|||
"mixedContentMode": mixedContentMode?.toValue(),
|
||||
"allowContentAccess": allowContentAccess,
|
||||
"allowFileAccess": allowFileAccess,
|
||||
"allowFileAccessFromFileURLs": allowFileAccessFromFileURLs,
|
||||
"allowUniversalAccessFromFileURLs": allowUniversalAccessFromFileURLs,
|
||||
"appCachePath": appCachePath,
|
||||
"blockNetworkImage": blockNetworkImage,
|
||||
"blockNetworkLoads": blockNetworkLoads,
|
||||
|
@ -651,9 +658,6 @@ class AndroidInAppWebViewOptions
|
|||
AndroidMixedContentMode.fromValue(map["mixedContentMode"]);
|
||||
options.allowContentAccess = map["allowContentAccess"];
|
||||
options.allowFileAccess = map["allowFileAccess"];
|
||||
options.allowFileAccessFromFileURLs = map["allowFileAccessFromFileURLs"];
|
||||
options.allowUniversalAccessFromFileURLs =
|
||||
map["allowUniversalAccessFromFileURLs"];
|
||||
options.appCachePath = map["appCachePath"];
|
||||
options.blockNetworkImage = map["blockNetworkImage"];
|
||||
options.blockNetworkLoads = map["blockNetworkLoads"];
|
||||
|
@ -899,8 +903,11 @@ class IOSInAppWebViewOptions
|
|||
List<IOSWKDataDetectorTypes> dataDetectorTypes = [];
|
||||
List<String> dataDetectorTypesList =
|
||||
List<String>.from(map["dataDetectorTypes"] ?? []);
|
||||
dataDetectorTypesList.forEach((dataDetectorType) {
|
||||
dataDetectorTypes.add(IOSWKDataDetectorTypes.fromValue(dataDetectorType));
|
||||
dataDetectorTypesList.forEach((dataDetectorTypeValue) {
|
||||
var dataDetectorType = IOSWKDataDetectorTypes.fromValue(dataDetectorTypeValue);
|
||||
if (dataDetectorType != null) {
|
||||
dataDetectorTypes.add(dataDetectorType);
|
||||
}
|
||||
});
|
||||
|
||||
IOSInAppWebViewOptions options = IOSInAppWebViewOptions();
|
||||
|
@ -920,7 +927,7 @@ class IOSInAppWebViewOptions
|
|||
options.isFraudulentWebsiteWarningEnabled =
|
||||
map["isFraudulentWebsiteWarningEnabled"];
|
||||
options.selectionGranularity =
|
||||
IOSWKSelectionGranularity.fromValue(map["selectionGranularity"]);
|
||||
IOSWKSelectionGranularity.fromValue(map["selectionGranularity"])!;
|
||||
options.dataDetectorTypes = dataDetectorTypes;
|
||||
options.sharedCookiesEnabled = map["sharedCookiesEnabled"];
|
||||
options.automaticallyAdjustsScrollIndicatorInsets =
|
||||
|
@ -928,7 +935,7 @@ class IOSInAppWebViewOptions
|
|||
options.accessibilityIgnoresInvertColors =
|
||||
map["accessibilityIgnoresInvertColors"];
|
||||
options.decelerationRate =
|
||||
IOSUIScrollViewDecelerationRate.fromValue(map["decelerationRate"]);
|
||||
IOSUIScrollViewDecelerationRate.fromValue(map["decelerationRate"])!;
|
||||
options.alwaysBounceVertical = map["alwaysBounceVertical"];
|
||||
options.alwaysBounceHorizontal = map["alwaysBounceHorizontal"];
|
||||
options.scrollsToTop = map["scrollsToTop"];
|
||||
|
@ -937,7 +944,7 @@ class IOSInAppWebViewOptions
|
|||
options.minimumZoomScale = map["minimumZoomScale"];
|
||||
options.contentInsetAdjustmentBehavior =
|
||||
IOSUIScrollViewContentInsetAdjustmentBehavior.fromValue(
|
||||
map["contentInsetAdjustmentBehavior"]);
|
||||
map["contentInsetAdjustmentBehavior"])!;
|
||||
return options;
|
||||
}
|
||||
|
||||
|
@ -1127,9 +1134,9 @@ class IOSInAppBrowserOptions implements BrowserOptions, IosOptions {
|
|||
options.closeButtonCaption = map["closeButtonCaption"];
|
||||
options.closeButtonColor = map["closeButtonColor"];
|
||||
options.presentationStyle =
|
||||
IOSUIModalPresentationStyle.fromValue(map["presentationStyle"]);
|
||||
IOSUIModalPresentationStyle.fromValue(map["presentationStyle"])!;
|
||||
options.transitionStyle =
|
||||
IOSUIModalTransitionStyle.fromValue(map["transitionStyle"]);
|
||||
IOSUIModalTransitionStyle.fromValue(map["transitionStyle"])!;
|
||||
options.spinner = map["spinner"];
|
||||
return options;
|
||||
}
|
||||
|
@ -1173,7 +1180,7 @@ class AndroidChromeCustomTabsOptions
|
|||
///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.
|
||||
String packageName;
|
||||
String? packageName;
|
||||
|
||||
///Set to `true` to enable Keep Alive. The default value is `false`.
|
||||
bool keepAliveEnabled;
|
||||
|
@ -1285,13 +1292,13 @@ class IOSSafariOptions implements ChromeSafariBrowserOptions, IosOptions {
|
|||
options.entersReaderIfAvailable = map["entersReaderIfAvailable"];
|
||||
options.barCollapsingEnabled = map["barCollapsingEnabled"];
|
||||
options.dismissButtonStyle =
|
||||
IOSSafariDismissButtonStyle.fromValue(map["dismissButtonStyle"]);
|
||||
IOSSafariDismissButtonStyle.fromValue(map["dismissButtonStyle"])!;
|
||||
options.preferredBarTintColor = map["preferredBarTintColor"];
|
||||
options.preferredControlTintColor = map["preferredControlTintColor"];
|
||||
options.presentationStyle =
|
||||
IOSUIModalPresentationStyle.fromValue(map["presentationStyle"]);
|
||||
IOSUIModalPresentationStyle.fromValue(map["presentationStyle"])!;
|
||||
options.transitionStyle =
|
||||
IOSUIModalTransitionStyle.fromValue(map["transitionStyle"]);
|
||||
IOSUIModalTransitionStyle.fromValue(map["transitionStyle"])!;
|
||||
return options;
|
||||
}
|
||||
|
||||
|
|
|
@ -168,7 +168,6 @@ app.post("/test-ajax-post", (req, res) => {
|
|||
res.send(JSON.stringify({
|
||||
"firstname": req.body.firstname,
|
||||
"lastname": req.body.lastname,
|
||||
"fullname": req.body.firstname + " " + req.body.lastname,
|
||||
}))
|
||||
res.end()
|
||||
})
|
||||
|
|
15
pubspec.yaml
15
pubspec.yaml
|
@ -1,17 +1,22 @@
|
|||
name: flutter_inappwebview
|
||||
description: A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window.
|
||||
version: 5.0.0
|
||||
version: 5.0.0-nullsafety.0
|
||||
homepage: https://github.com/pichillilorenzo/flutter_inappwebview
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
flutter: ">=1.12.13+hotfix.5"
|
||||
sdk: ">=2.12.0-0 <3.0.0"
|
||||
flutter: ">=1.22.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
uuid: ^2.0.0
|
||||
mime: ^0.9.6+2
|
||||
uuid: ^3.0.0-nullsafety.0
|
||||
mime: ^1.0.0-nullsafety.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
pedantic: ^1.10.0-nullsafety.1
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://www.dartlang.org/tools/pub/pubspec
|
||||
|
|
3
test.sh
3
test.sh
|
@ -1,4 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
# on linux/macOS local IP can be found using $(ipconfig getifaddr en0)
|
||||
export NODE_SERVER_IP=$1
|
||||
dart tool/env.dart
|
||||
|
@ -7,5 +8,5 @@ node index.js &
|
|||
flutter clean
|
||||
cd ../example
|
||||
flutter clean
|
||||
flutter driver -t test_driver/app.dart
|
||||
flutter driver --driver=test_driver/integration_test.dart --target=integration_test/webview_flutter_test.dart
|
||||
kill $(jobs -p)
|
|
@ -7,6 +7,6 @@ Future<void> main() async {
|
|||
'NODE_SERVER_IP': Platform.environment['NODE_SERVER_IP'],
|
||||
};
|
||||
|
||||
final filename = 'example/test_driver/.env.dart';
|
||||
final filename = 'example/integration_test/.env.dart';
|
||||
await File(filename).writeAsString('final environment = ${json.encode(config)};');
|
||||
}
|
Loading…
Reference in New Issue