updated README.md, Added verticalScrollbarThumbColor, verticalScrollbarTrackColor, horizontalScrollbarThumbColor, horizontalScrollbarTrackColor Android-specific WebView options, Fixed some null types and wrong casting

This commit is contained in:
Lorenzo Pichilli 2021-02-25 00:00:46 +01:00
parent 35cea5b01a
commit 1e63238eb8
21 changed files with 476 additions and 218 deletions

View File

@ -1,3 +1,8 @@
## 5.0.1-nullsafety.1
- Added `verticalScrollbarThumbColor`, `verticalScrollbarTrackColor`, `horizontalScrollbarThumbColor`, `horizontalScrollbarTrackColor` Android-specific WebView options
- Fixed some null types and wrong casting
## 5.0.0-nullsafety.0 ## 5.0.0-nullsafety.0
- Added support for Dart null-safety feature - Added support for Dart null-safety feature

170
README.md
View File

@ -217,14 +217,33 @@ First, add `flutter_inappwebview` as a [dependency in your pubspec.yaml file](ht
Classes: Classes:
- [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. - [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.
- [methods](#inappwebviewcontroller-methods)
- [options](#inappwebview-options)
- [events](#inappwebview-events)
- [ContextMenu](#contextmenu-class): This class represents the WebView context menu. - [ContextMenu](#contextmenu-class): This class represents the WebView context menu.
- [options](#contextmenu-options)
- [events](#contextmenu-events)
- [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. - [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.
- [methods](#inappwebviewcontroller-methods)
- [options](#inappwebview-options)
- [events](#inappwebview-events)
- [InAppBrowser](#inappbrowser-class): In-App Browser using native WebView. - [InAppBrowser](#inappbrowser-class): In-App Browser using native WebView.
- [methods](#inappbrowser-methods)
- [options](#inappbrowser-options)
- [events](#inappbrowser-events)
- [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.
- [methods](#chromesafaribrowser-methods)
- [options](#chromesafaribrowser-options)
- [events](#chromesafaribrowser-events)
- [InAppLocalhostServer](#inapplocalhostserver-class): This class allows you to create a simple server on `http://localhost:[port]/`. The default `port` value is `8080`. - [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. **LIMITED SUPPORT for iOS below 11.0**. - [CookieManager](#cookiemanager-class): This class implements a singleton object (shared instance) which manages the cookies used by WebView instances. **LIMITED SUPPORT for iOS below 11.0**.
- [methods](#cookiemanager-methods)
- [HttpAuthCredentialDatabase](#httpauthcredentialdatabase-class): This class implements a singleton object (shared instance) which manages the shared HTTP auth credentials cache. - [HttpAuthCredentialDatabase](#httpauthcredentialdatabase-class): This class implements a singleton object (shared instance) which manages the shared HTTP auth credentials cache.
- [methods](#httpauthcredentialdatabase-methods)
- [WebStorageManager](#webstoragemanager-class): This class implements a singleton object (shared instance) which manages the web storage used by WebView instances. - [WebStorageManager](#webstoragemanager-class): This class implements a singleton object (shared instance) which manages the web storage used by WebView instances.
- [methods](#webstoragemanager-methods)
- [WebRTC](#webrtc)
- [Service Worker API](#service-worker-api)
### Load a file inside `assets` folder ### Load a file inside `assets` folder
@ -613,6 +632,8 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
* `forceDark`: Set the force dark mode for this WebView. The default value is `AndroidInAppWebViewForceDark.FORCE_DARK_OFF`. * `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`. * `geolocationEnabled`: Sets whether Geolocation API is enabled. The default value is `true`.
* `hardwareAcceleration`: Boolean value to enable Hardware Acceleration in the WebView. * `hardwareAcceleration`: Boolean value to enable Hardware Acceleration in the WebView.
* `horizontalScrollbarThumbColor`: Sets the horizontal scrollbar thumb color.
* `horizontalScrollbarTrackColor`: Sets the horizontal scrollbar track color.
* `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`. * `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. * `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. * `loadWithOverviewMode`: Sets whether the WebView loads pages in overview mode, that is, zooms out the content to fit on screen by width.
@ -642,6 +663,8 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
* `useShouldInterceptRequest`: Set to `true` to be able to listen at the `androidShouldInterceptRequest` 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. * `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`. * `verticalScrollbarPosition`: Set the position of the vertical scroll bar. The default value is `AndroidVerticalScrollbarPosition.SCROLLBAR_POSITION_DEFAULT`.
* `verticalScrollbarThumbColor`: Sets the vertical scrollbar thumb color.
* `verticalScrollbarTrackColor`: Sets the vertical scrollbar track color.
##### `InAppWebView` iOS-specific options ##### `InAppWebView` iOS-specific options
@ -1148,7 +1171,7 @@ class _MyAppState extends State<MyApp> {
Screenshots: Screenshots:
- iOS: - iOS:
![ios](https://user-images.githubusercontent.com/5956938/45934084-2a935400-bf99-11e8-9d71-9e1758b5b8c6.gif) ![ios](https://user-images.githubusercontent.com/5956938/109074100-92fd3700-76f7-11eb-8e75-34ce7377e35f.gif)
- Android: - Android:
@ -1509,3 +1532,148 @@ iOS-specific methods can be called using the `WebStorageManager.instance().ios`
* `fetchDataRecords({required Set<IOSWKWebsiteDataType> dataTypes})`: Fetches data records containing the given website data types. * `fetchDataRecords({required Set<IOSWKWebsiteDataType> dataTypes})`: Fetches data records containing the given website data types.
* `removeDataFor({required Set<IOSWKWebsiteDataType> dataTypes, required List<IOSWKWebsiteDataRecord> dataRecords})`: Removes website data of the given types for the given data records. * `removeDataFor({required Set<IOSWKWebsiteDataType> dataTypes, required List<IOSWKWebsiteDataRecord> dataRecords})`: Removes website data of the given types for the given data records.
* `removeDataModifiedSince({required Set<IOSWKWebsiteDataType> dataTypes, required DateTime date})`: Removes all website data of the given types that has been modified since the given date. * `removeDataModifiedSince({required Set<IOSWKWebsiteDataType> dataTypes, required DateTime date})`: Removes all website data of the given types that has been modified since the given date.
### WebRTC
To work with WebRTC, you need to request `camera` and `microphone` permissions, for example using the `permission_handler` flutter package:
```dart
import 'package:permission_handler/permission_handler.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Permission.camera.request();
await Permission.microphone.request();
runApp(MyApp());
}
```
Also, you need to set the cross-platform option `mediaPlaybackRequiresUserGesture` to `false` in order to autoplay HTML5 audio and video.
After that, follow the instructions below for each platform where you want to use it.
To test WebRTC, you can try to visit https://appr.tc/.
#### WebRTC on Android
On Android, you need to implement the `androidOnPermissionRequest` event, that is an event fired when the WebView is requesting permission to access a specific resource.
This event is used to grant permissions for the WebRTC API, for example:
```dart
androidOnPermissionRequest: (controller, origin, resources) async {
return PermissionRequestResponse(resources: resources, action: PermissionRequestResponseAction.GRANT);
}
```
Also, you need to add these permissions in your `AndroidManifest.xml` file:
```xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.VIDEO_CAPTURE" />
<uses-permission android:name="android.permission.AUDIO_CAPTURE" />
```
#### WebRTC on iOS
On iOS, WebRTC is supported starting from 14.3+.
You need to set the iOS-specific option `allowsInlineMediaPlayback` to `true`, for example:
```dart
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
mediaPlaybackRequiresUserGesture: false,
),
android: AndroidInAppWebViewOptions(
useHybridComposition: true
),
ios: IOSInAppWebViewOptions(
allowsInlineMediaPlayback: true,
)
),
```
Note that on iOS, to be able to play video inline, the `video` HTML element must have the `playsinline` attribute, for example:
```html
<video autoplay playsinline src="..."></video>
```
In your `Info.plist` file, you need to add also the following properties:
```xml
<key>NSMicrophoneUsageDescription</key>
<string>Flutter requires access to microphone.</string>
<key>NSCameraUsageDescription</key>
<string>Flutter requires access to camera.</string>
```
If you open this file In Xcode, the `NSMicrophoneUsageDescription` property is represented by `Privacy - Microphone Usage Description` and
`NSCameraUsageDescription` is represented by `Privacy - Camera Usage Description`.
### Service Worker API
Check https://caniuse.com/serviceworkers for JavaScript Service Worker API availability.
#### Service Worker API on Android
On Android, the `AndroidServiceWorkerController` and `AndroidServiceWorkerClient` classes can be used to intercept requests.
Before using these classes or its methods, you should check if the service worker features you want to use are supported or not, for example:
```dart
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isAndroid) {
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
var swAvailable = await AndroidWebViewFeature.isFeatureSupported(AndroidWebViewFeature.SERVICE_WORKER_BASIC_USAGE);
var swInterceptAvailable = await AndroidWebViewFeature.isFeatureSupported(AndroidWebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST);
if (swAvailable && swInterceptAvailable) {
AndroidServiceWorkerController serviceWorkerController = AndroidServiceWorkerController.instance();
serviceWorkerController.serviceWorkerClient = AndroidServiceWorkerClient(
shouldInterceptRequest: (request) async {
print(request);
return null;
},
);
}
}
runApp(MyApp());
}
```
#### Service Worker API on iOS
The JavaScript Service Worker API are available starting from iOS 14.0+.
To enable this JavaScript API on iOS there are only 2 ways:
- using `App-Bound Domains`
- your App proposes itself as a possible Default Browser such as iOS Safari or Google Chrome
##### iOS App-Bound Domains
Read the [WebKit - App-Bound Domains](https://webkit.org/blog/10882/app-bound-domains/) article for details.
You can specify up to 10 "app-bound" domains using a new Info.plist key `WKAppBoundDomains`, for example:
```xml
<dict>
<key>WKAppBoundDomains</key>
<array>
<string>flutter.dev</string>
<string>github.com</string>
</array>
</dict>
```
After that, you need to set to `true` the `limitsNavigationsToAppBoundDomains` iOS-specific WebView option, for example:
```dart
InAppWebViewGroupOptions(
ios: IOSInAppWebViewOptions(
limitsNavigationsToAppBoundDomains: true // adds Service Worker API on iOS 14.0+
)
)
```
##### iOS Default Browser
Read the [Preparing Your App to be the Default Browser or Email Client](https://developer.apple.com/documentation/xcode/allowing_apps_and_websites_to_link_to_your_content/preparing_your_app_to_be_the_default_browser_or_email_client) article for details.

View File

@ -8,6 +8,8 @@ import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@ -78,6 +80,8 @@ import org.json.JSONObject;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@ -184,6 +188,25 @@ final public class InAppWebView extends InputAwareWebView {
WebViewCompat.setWebViewRenderProcessClient(this, inAppWebViewRenderProcessClient); WebViewCompat.setWebViewRenderProcessClient(this, inAppWebViewRenderProcessClient);
} }
userContentController.addPluginScript(PromisePolyfillJS.PROMISE_POLYFILL_JS_PLUGIN_SCRIPT);
userContentController.addPluginScript(JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_JS_PLUGIN_SCRIPT);
userContentController.addPluginScript(ConsoleLogJS.CONSOLE_LOG_JS_PLUGIN_SCRIPT);
userContentController.addPluginScript(PrintJS.PRINT_JS_PLUGIN_SCRIPT);
userContentController.addPluginScript(OnWindowBlurEventJS.ON_WINDOW_BLUR_EVENT_JS_PLUGIN_SCRIPT);
userContentController.addPluginScript(OnWindowFocusEventJS.ON_WINDOW_FOCUS_EVENT_JS_PLUGIN_SCRIPT);
if (options.useShouldInterceptAjaxRequest) {
userContentController.addPluginScript(InterceptAjaxRequestJS.INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT);
}
if (options.useShouldInterceptFetchRequest) {
userContentController.addPluginScript(InterceptFetchRequestJS.INTERCEPT_FETCH_REQUEST_JS_PLUGIN_SCRIPT);
}
if (options.useOnLoadResource) {
userContentController.addPluginScript(OnLoadResourceJS.ON_LOAD_RESOURCE_JS_PLUGIN_SCRIPT);
}
if (!options.useHybridComposition) {
userContentController.addPluginScript(PluginScriptsUtil.CHECK_GLOBAL_KEY_DOWN_EVENT_TO_HIDE_CONTEXT_MENU_JS_PLUGIN_SCRIPT);
}
if (options.useOnDownloadStart) if (options.useOnDownloadStart)
setDownloadListener(new DownloadStartListener()); setDownloadListener(new DownloadStartListener());
@ -304,6 +327,18 @@ final public class InAppWebView extends InputAwareWebView {
options.scrollBarFadeDuration = getScrollBarFadeDuration(); options.scrollBarFadeDuration = getScrollBarFadeDuration();
} }
setVerticalScrollbarPosition(options.verticalScrollbarPosition); setVerticalScrollbarPosition(options.verticalScrollbarPosition);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (options.verticalScrollbarThumbColor != null)
setVerticalScrollbarThumbDrawable(new ColorDrawable(Color.parseColor(options.verticalScrollbarThumbColor)));
if (options.verticalScrollbarTrackColor != null)
setVerticalScrollbarTrackDrawable(new ColorDrawable(Color.parseColor(options.verticalScrollbarTrackColor)));
if (options.horizontalScrollbarThumbColor != null)
setHorizontalScrollbarThumbDrawable(new ColorDrawable(Color.parseColor(options.horizontalScrollbarThumbColor)));
if (options.horizontalScrollbarTrackColor != null)
setHorizontalScrollbarTrackDrawable(new ColorDrawable(Color.parseColor(options.horizontalScrollbarTrackColor)));
}
setOverScrollMode(options.overScrollMode); setOverScrollMode(options.overScrollMode);
if (options.networkAvailable != null) { if (options.networkAvailable != null) {
setNetworkAvailable(options.networkAvailable); setNetworkAvailable(options.networkAvailable);
@ -436,25 +471,6 @@ final public class InAppWebView extends InputAwareWebView {
return false; return false;
} }
}); });
userContentController.addPluginScript(PromisePolyfillJS.PROMISE_POLYFILL_JS_PLUGIN_SCRIPT);
userContentController.addPluginScript(JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_JS_PLUGIN_SCRIPT);
userContentController.addPluginScript(ConsoleLogJS.CONSOLE_LOG_JS_PLUGIN_SCRIPT);
userContentController.addPluginScript(PrintJS.PRINT_JS_PLUGIN_SCRIPT);
userContentController.addPluginScript(OnWindowBlurEventJS.ON_WINDOW_BLUR_EVENT_JS_PLUGIN_SCRIPT);
userContentController.addPluginScript(OnWindowFocusEventJS.ON_WINDOW_FOCUS_EVENT_JS_PLUGIN_SCRIPT);
if (options.useShouldInterceptAjaxRequest) {
userContentController.addPluginScript(InterceptAjaxRequestJS.INTERCEPT_AJAX_REQUEST_JS_PLUGIN_SCRIPT);
}
if (options.useShouldInterceptFetchRequest) {
userContentController.addPluginScript(InterceptFetchRequestJS.INTERCEPT_FETCH_REQUEST_JS_PLUGIN_SCRIPT);
}
if (options.useOnLoadResource) {
userContentController.addPluginScript(OnLoadResourceJS.ON_LOAD_RESOURCE_JS_PLUGIN_SCRIPT);
}
if (!options.useHybridComposition) {
userContentController.addPluginScript(PluginScriptsUtil.CHECK_GLOBAL_KEY_DOWN_EVENT_TO_HIDE_CONTEXT_MENU_JS_PLUGIN_SCRIPT);
}
} }
public void setIncognito(boolean enabled) { public void setIncognito(boolean enabled) {

View File

@ -4,6 +4,8 @@ import android.os.Build;
import android.view.View; import android.view.View;
import android.webkit.WebSettings; import android.webkit.WebSettings;
import androidx.annotation.Nullable;
import com.pichillilorenzo.flutter_inappwebview.Options; import com.pichillilorenzo.flutter_inappwebview.Options;
import com.pichillilorenzo.flutter_inappwebview.types.PreferredContentModeOptionType; import com.pichillilorenzo.flutter_inappwebview.types.PreferredContentModeOptionType;
@ -97,6 +99,14 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
public Boolean useOnRenderProcessGone = false; public Boolean useOnRenderProcessGone = false;
public Boolean disableDefaultErrorPage = false; public Boolean disableDefaultErrorPage = false;
public Boolean useHybridComposition = false; public Boolean useHybridComposition = false;
@Nullable
public String verticalScrollbarThumbColor;
@Nullable
public String verticalScrollbarTrackColor;
@Nullable
public String horizontalScrollbarThumbColor;
@Nullable
public String horizontalScrollbarTrackColor;
@Override @Override
public InAppWebViewOptions parse(Map<String, Object> options) { public InAppWebViewOptions parse(Map<String, Object> options) {
@ -339,6 +349,18 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
case "useHybridComposition": case "useHybridComposition":
useHybridComposition = (Boolean) value; useHybridComposition = (Boolean) value;
break; break;
case "verticalScrollbarThumbColor":
verticalScrollbarThumbColor = (String) value;
break;
case "verticalScrollbarTrackColor":
verticalScrollbarTrackColor = (String) value;
break;
case "horizontalScrollbarThumbColor":
horizontalScrollbarThumbColor = (String) value;
break;
case "horizontalScrollbarTrackColor":
horizontalScrollbarTrackColor = (String) value;
break;
} }
} }
@ -425,6 +447,10 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
options.put("useOnRenderProcessGone", useOnRenderProcessGone); options.put("useOnRenderProcessGone", useOnRenderProcessGone);
options.put("disableDefaultErrorPage", disableDefaultErrorPage); options.put("disableDefaultErrorPage", disableDefaultErrorPage);
options.put("useHybridComposition", useHybridComposition); options.put("useHybridComposition", useHybridComposition);
options.put("verticalScrollbarThumbColor", verticalScrollbarThumbColor);
options.put("verticalScrollbarTrackColor", verticalScrollbarTrackColor);
options.put("horizontalScrollbarThumbColor", horizontalScrollbarThumbColor);
options.put("horizontalScrollbarTrackColor", horizontalScrollbarTrackColor);
return options; return options;
} }

View File

@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"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":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"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":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/","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.2.0-nullsafety/","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.1.0-nullsafety.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":"device_info","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":["device_info"]},{"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-02-22 23:54:51.255907","version":"1.27.0-5.0.pre.90"} {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"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":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"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":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/","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.2.0-nullsafety/","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.1.0-nullsafety.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":"device_info","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":["device_info"]},{"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-02-24 23:50:11.899671","version":"1.27.0-4.0.pre"}

View File

@ -44,6 +44,7 @@ android {
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
} }
buildTypes { buildTypes {
@ -63,4 +64,6 @@ dependencies {
testImplementation 'junit:junit:4.13' testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test:runner:1.3.0' androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'com.android.support:multidex:1.0.3'
} }

View File

@ -1,8 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> <!-- Theme applied to the Android Window while the process is starting -->
<style name="LaunchTheme" parent="Theme.MaterialComponents.NoActionBar">
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame --> Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
</style> </style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="Theme.MaterialComponents.NoActionBar">
<item name="android:windowBackground">@android:color/white</item>
</style>
</resources> </resources>

View File

@ -459,7 +459,7 @@ void main() {
final ConsoleMessage consoleMessage = await consoleMessageCompleter.future; final ConsoleMessage consoleMessage = await consoleMessageCompleter.future;
expect(consoleMessage.messageLevel, ConsoleMessageLevel.LOG); expect(consoleMessage.messageLevel, ConsoleMessageLevel.LOG);
expect(consoleMessage.message, 'message'); expect(consoleMessage.message, 'message');
}); }, skip: !Platform.isIOS);
testWidgets('loadUrl with file:// scheme and iosAllowingReadAccessTo argument', (WidgetTester tester) async { testWidgets('loadUrl with file:// scheme and iosAllowingReadAccessTo argument', (WidgetTester tester) async {
final Completer<ConsoleMessage?> consoleMessageShouldNotComplete = Completer<ConsoleMessage?>(); final Completer<ConsoleMessage?> consoleMessageShouldNotComplete = Completer<ConsoleMessage?>();
@ -503,7 +503,7 @@ void main() {
final ConsoleMessage consoleMessage = await consoleMessageCompleter.future; final ConsoleMessage consoleMessage = await consoleMessageCompleter.future;
expect(consoleMessage.messageLevel, ConsoleMessageLevel.LOG); expect(consoleMessage.messageLevel, ConsoleMessageLevel.LOG);
expect(consoleMessage.message, 'message'); expect(consoleMessage.message, 'message');
}); }, skip: !Platform.isIOS);
}, skip: !Platform.isIOS); }, skip: !Platform.isIOS);
testWidgets('JavaScript Handler', (WidgetTester tester) async { testWidgets('JavaScript Handler', (WidgetTester tester) async {
@ -2971,7 +2971,7 @@ setTimeout(function() {
await pageLoaded.future; await pageLoaded.future;
final String url = await onNavigationResponseCompleter.future; final String url = await onNavigationResponseCompleter.future;
expect(url, 'https://flutter.dev/'); expect(url, 'https://flutter.dev/');
}); }, skip: !Platform.isIOS);
testWidgets('cancel navigation', (WidgetTester tester) async { testWidgets('cancel navigation', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>(); final Completer controllerCompleter = Completer<InAppWebViewController>();
@ -3008,7 +3008,7 @@ setTimeout(function() {
final String url = await onNavigationResponseCompleter.future; final String url = await onNavigationResponseCompleter.future;
expect(url, 'https://flutter.dev/'); expect(url, 'https://flutter.dev/');
expect(pageLoaded.future, doesNotComplete); expect(pageLoaded.future, doesNotComplete);
}); }, skip: !Platform.isIOS);
}, skip: !Platform.isIOS); }, skip: !Platform.isIOS);
testWidgets('initialUserScripts', (WidgetTester tester) async { testWidgets('initialUserScripts', (WidgetTester tester) async {
@ -4292,7 +4292,7 @@ setTimeout(function() {
final InAppWebViewController controller = await controllerCompleter.future; final InAppWebViewController controller = await controllerCompleter.future;
await pageLoaded.future; await pageLoaded.future;
await expectLater(controller.android.clearSslPreferences(), completes); await expectLater(controller.android.clearSslPreferences(), completes);
}); }, skip: !Platform.isAndroid);
testWidgets('pause/resume', (WidgetTester tester) async { testWidgets('pause/resume', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>(); final Completer controllerCompleter = Completer<InAppWebViewController>();
@ -4321,7 +4321,7 @@ setTimeout(function() {
await expectLater(controller.android.pause(), completes); await expectLater(controller.android.pause(), completes);
await Future.delayed(Duration(seconds: 1)); await Future.delayed(Duration(seconds: 1));
await expectLater(controller.android.resume(), completes); await expectLater(controller.android.resume(), completes);
}); }, skip: !Platform.isAndroid);
testWidgets('getOriginalUrl', (WidgetTester tester) async { testWidgets('getOriginalUrl', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>(); final Completer controllerCompleter = Completer<InAppWebViewController>();
@ -4349,7 +4349,7 @@ setTimeout(function() {
await pageLoaded.future; await pageLoaded.future;
var originUrl = (await controller.android.getOriginalUrl())?.toString(); var originUrl = (await controller.android.getOriginalUrl())?.toString();
expect(originUrl, 'https://flutter.dev/'); expect(originUrl, 'https://flutter.dev/');
}); }, skip: !Platform.isAndroid);
testWidgets('pageDown/pageUp', (WidgetTester tester) async { testWidgets('pageDown/pageUp', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>(); final Completer controllerCompleter = Completer<InAppWebViewController>();
@ -4378,7 +4378,7 @@ setTimeout(function() {
expect(await controller.android.pageDown(bottom: false), true); expect(await controller.android.pageDown(bottom: false), true);
await Future.delayed(Duration(seconds: 1)); await Future.delayed(Duration(seconds: 1));
expect(await controller.android.pageUp(top: false), true); expect(await controller.android.pageUp(top: false), true);
}); }, skip: !Platform.isAndroid);
testWidgets('zoomIn/zoomOut', (WidgetTester tester) async { testWidgets('zoomIn/zoomOut', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>(); final Completer controllerCompleter = Completer<InAppWebViewController>();
@ -4407,7 +4407,7 @@ setTimeout(function() {
expect(await controller.android.zoomIn(), true); expect(await controller.android.zoomIn(), true);
await Future.delayed(Duration(seconds: 1)); await Future.delayed(Duration(seconds: 1));
expect(await controller.android.zoomOut(), true); expect(await controller.android.zoomOut(), true);
}); }, skip: !Platform.isAndroid);
testWidgets('clearHistory', (WidgetTester tester) async { testWidgets('clearHistory', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>(); final Completer controllerCompleter = Completer<InAppWebViewController>();
@ -4443,121 +4443,121 @@ setTimeout(function() {
webHistory = await controller.getCopyBackForwardList(); webHistory = await controller.getCopyBackForwardList();
expect(webHistory!.list!.length, 1); expect(webHistory!.list!.length, 1);
}); }, skip: !Platform.isAndroid);
test('clearClientCertPreferences', () async { test('clearClientCertPreferences', () async {
await expectLater(AndroidInAppWebViewController.clearClientCertPreferences(), completes); await expectLater(AndroidInAppWebViewController.clearClientCertPreferences(), completes);
}); }, skip: !Platform.isAndroid);
test('getSafeBrowsingPrivacyPolicyUrl', () async { test('getSafeBrowsingPrivacyPolicyUrl', () async {
expect(await AndroidInAppWebViewController.getSafeBrowsingPrivacyPolicyUrl(), isNotNull); expect(await AndroidInAppWebViewController.getSafeBrowsingPrivacyPolicyUrl(), isNotNull);
}); }, skip: !Platform.isAndroid);
test('setSafeBrowsingWhitelist', () async { test('setSafeBrowsingWhitelist', () async {
expect(await AndroidInAppWebViewController.setSafeBrowsingWhitelist(hosts: ["flutter.dev", "github.com"]), true); expect(await AndroidInAppWebViewController.setSafeBrowsingWhitelist(hosts: ["flutter.dev", "github.com"]), true);
}); }, skip: !Platform.isAndroid);
test('getCurrentWebViewPackage', () async { test('getCurrentWebViewPackage', () async {
expect(await AndroidInAppWebViewController.getCurrentWebViewPackage(), isNotNull); expect(await AndroidInAppWebViewController.getCurrentWebViewPackage(), isNotNull);
}); }, skip: !Platform.isAndroid);
}, skip: !Platform.isAndroid); }, skip: !Platform.isAndroid);
group('ios methods', () { group('ios methods', () {
testWidgets('reloadFromOrigin', (WidgetTester tester) async { testWidgets('reloadFromOrigin', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>(); final Completer controllerCompleter = Completer<InAppWebViewController>();
final Completer<void> pageLoaded = Completer<void>(); final Completer<void> pageLoaded = Completer<void>();
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: InAppWebView( child: InAppWebView(
key: GlobalKey(), key: GlobalKey(),
initialUrlRequest: URLRequest( initialUrlRequest: URLRequest(
url: Uri.parse('https://flutter.dev') url: Uri.parse('https://flutter.dev')
),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
onLoadStop: (controller, url) {
pageLoaded.complete();
},
), ),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
onLoadStop: (controller, url) {
pageLoaded.complete();
},
), ),
); ),
);
final InAppWebViewController controller = await controllerCompleter.future; final InAppWebViewController controller = await controllerCompleter.future;
await pageLoaded.future; await pageLoaded.future;
await expectLater(controller.ios.reloadFromOrigin(), completes); await expectLater(controller.ios.reloadFromOrigin(), completes);
});
testWidgets('createPdf', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>();
final Completer<void> pageLoaded = Completer<void>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(
url: Uri.parse('https://flutter.dev')
),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
onLoadStop: (controller, url) {
pageLoaded.complete();
},
),
),
);
final InAppWebViewController controller = await controllerCompleter.future;
await pageLoaded.future;
var iosWKPdfConfiguration = IOSWKPDFConfiguration(rect: InAppWebViewRect(
width: 100,
height: 100,
x: 50,
y: 50
));
var pdf = await controller.ios.createPdf(iosWKPdfConfiguration: iosWKPdfConfiguration);
expect(pdf, isNotNull);
});
testWidgets('createWebArchiveData', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>();
final Completer<void> pageLoaded = Completer<void>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(
url: Uri.parse('https://flutter.dev')
),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
onLoadStop: (controller, url) {
pageLoaded.complete();
},
),
),
);
final InAppWebViewController controller = await controllerCompleter.future;
await pageLoaded.future;
expect(await controller.ios.createWebArchiveData(), isNotNull);
});
test('handlesURLScheme', () async {
expect(await IOSInAppWebViewController.handlesURLScheme("http"), true);
expect(await IOSInAppWebViewController.handlesURLScheme("https"), true);
});
}, skip: !Platform.isIOS); }, skip: !Platform.isIOS);
testWidgets('createPdf', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>();
final Completer<void> pageLoaded = Completer<void>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(
url: Uri.parse('https://flutter.dev')
),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
onLoadStop: (controller, url) {
pageLoaded.complete();
},
),
),
);
final InAppWebViewController controller = await controllerCompleter.future;
await pageLoaded.future;
var iosWKPdfConfiguration = IOSWKPDFConfiguration(rect: InAppWebViewRect(
width: 100,
height: 100,
x: 50,
y: 50
));
var pdf = await controller.ios.createPdf(iosWKPdfConfiguration: iosWKPdfConfiguration);
expect(pdf, isNotNull);
}, skip: !Platform.isIOS);
testWidgets('createWebArchiveData', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>();
final Completer<void> pageLoaded = Completer<void>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(
url: Uri.parse('https://flutter.dev')
),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
onLoadStop: (controller, url) {
pageLoaded.complete();
},
),
),
);
final InAppWebViewController controller = await controllerCompleter.future;
await pageLoaded.future;
expect(await controller.ios.createWebArchiveData(), isNotNull);
}, skip: !Platform.isIOS);
test('handlesURLScheme', () async {
expect(await IOSInAppWebViewController.handlesURLScheme("http"), true);
expect(await IOSInAppWebViewController.handlesURLScheme("https"), true);
}, skip: !Platform.isIOS);
}, skip: !Platform.isIOS);
}); });
group('Cookie Manager', () { group('Cookie Manager', () {

View File

@ -1,18 +0,0 @@
#
# NOTE: This podspec is NOT to be published. It is only used as a local source!
# This is a generated file; do not edit or check into version control.
#
Pod::Spec.new do |s|
s.name = 'Flutter'
s.version = '1.0.0'
s.summary = 'High-performance, high-fidelity mobile apps.'
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'
# Framework linking is handled by Flutter tooling, not CocoaPods.
# Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs.
s.vendored_frameworks = 'path/to/nothing'
end

View File

@ -2,13 +2,12 @@
# This is a generated file; do not edit or check into version control. # This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter" export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example" 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 "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build/ios" export "SYMROOT=${SOURCE_ROOT}/../build/ios"
export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1" export "FLUTTER_BUILD_NUMBER=1"
export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ=="
export "DART_OBFUSCATION=false" export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true" export "TRACK_WIDGET_CREATION=false"
export "TREE_SHAKE_ICONS=false" export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/.dart_tool/package_config.json" export "PACKAGE_CONFIG=.packages"

View File

@ -1,7 +1,7 @@
import 'dart:collection'; import 'dart:collection';
import 'dart:convert'; // import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; // import 'dart:typed_data';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart';
@ -23,7 +23,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
late ContextMenu contextMenu; late ContextMenu contextMenu;
String url = ""; String url = "";
double progress = 0; double progress = 0;
CookieManager _cookieManager = CookieManager.instance(); // CookieManager _cookieManager = CookieManager.instance();
@override @override
void initState() { void initState() {
@ -70,7 +70,6 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
), ),
ios: IOSInAppWebViewOptions( ios: IOSInAppWebViewOptions(
allowsInlineMediaPlayback: true, allowsInlineMediaPlayback: true,
// limitsNavigationsToAppBoundDomains: true // adds Service Worker API on iOS 14.0+
) )
); );
@ -146,9 +145,6 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
this.url = url.toString(); this.url = url.toString();
}); });
webView = controller; webView = controller;
// RenderObject renderBox = webViewKey.currentContext!.findRenderObject()!;
// print(renderBox.paintBounds.size);
}, },
onProgressChanged: (controller, progress) { onProgressChanged: (controller, progress) {
setState(() { setState(() {
@ -162,7 +158,6 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
}); });
}, },
onConsoleMessage: (controller, consoleMessage) { onConsoleMessage: (controller, consoleMessage) {
print("CONSOLE MESSAGE FROM MAIN WEBVIEW!");
print(consoleMessage); print(consoleMessage);
}, },
), ),

View File

@ -8,22 +8,26 @@ import 'package:flutter_inappwebview_example/chrome_safari_browser_example.scree
import 'package:flutter_inappwebview_example/headless_in_app_webview.screen.dart'; import 'package:flutter_inappwebview_example/headless_in_app_webview.screen.dart';
import 'package:flutter_inappwebview_example/in_app_webiew_example.screen.dart'; import 'package:flutter_inappwebview_example/in_app_webiew_example.screen.dart';
import 'package:flutter_inappwebview_example/in_app_browser_example.screen.dart'; import 'package:flutter_inappwebview_example/in_app_browser_example.screen.dart';
import 'package:path_provider/path_provider.dart'; // import 'package:path_provider/path_provider.dart';
// import 'package:permission_handler/permission_handler.dart'; // import 'package:permission_handler/permission_handler.dart';
// InAppLocalhostServer localhostServer = new InAppLocalhostServer(); // InAppLocalhostServer localhostServer = new InAppLocalhostServer();
AndroidServiceWorkerController serviceWorkerController = AndroidServiceWorkerController.instance();
Future main() async { Future main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
// await Permission.camera.request(); // await Permission.camera.request();
// await Permission.microphone.request(); // await Permission.microphone.request();
// await Permission.storage.request(); //await Permission.storage.request();
if (Platform.isAndroid) { if (Platform.isAndroid) {
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true); await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
if (await AndroidWebViewFeature.isFeatureSupported(AndroidWebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST)) { var swAvailable = await AndroidWebViewFeature.isFeatureSupported(AndroidWebViewFeature.SERVICE_WORKER_BASIC_USAGE);
var swInterceptAvailable = await AndroidWebViewFeature.isFeatureSupported(AndroidWebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST);
if (swAvailable && swInterceptAvailable) {
AndroidServiceWorkerController serviceWorkerController = AndroidServiceWorkerController.instance();
serviceWorkerController.serviceWorkerClient = AndroidServiceWorkerClient( serviceWorkerController.serviceWorkerClient = AndroidServiceWorkerClient(
shouldInterceptRequest: (request) async { shouldInterceptRequest: (request) async {
print(request); print(request);

View File

@ -1012,6 +1012,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
if newOptionsMap["javaScriptEnabled"] != nil && options?.javaScriptEnabled != newOptions.javaScriptEnabled { if newOptionsMap["javaScriptEnabled"] != nil && options?.javaScriptEnabled != newOptions.javaScriptEnabled {
configuration.preferences.javaScriptEnabled = newOptions.javaScriptEnabled configuration.preferences.javaScriptEnabled = newOptions.javaScriptEnabled
} }
if #available(iOS 14.0, *) { if #available(iOS 14.0, *) {
if options?.mediaType != newOptions.mediaType { if options?.mediaType != newOptions.mediaType {
mediaType = newOptions.mediaType mediaType = newOptions.mediaType
@ -1479,7 +1480,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
if let useOnDownloadStart = options?.useOnDownloadStart, useOnDownloadStart { if let useOnDownloadStart = options?.useOnDownloadStart, useOnDownloadStart {
let mimeType = navigationResponse.response.mimeType let mimeType = navigationResponse.response.mimeType
if let url = navigationResponse.response.url, navigationResponse.isForMainFrame { if let url = navigationResponse.response.url, navigationResponse.isForMainFrame {
if mimeType != nil && !mimeType!.starts(with: "text/") { if url.scheme != "file", mimeType != nil, !mimeType!.starts(with: "text/") {
onDownloadStart(url: url.absoluteString) onDownloadStart(url: url.absoluteString)
if useOnNavigationResponse == nil || !useOnNavigationResponse! { if useOnNavigationResponse == nil || !useOnNavigationResponse! {
decisionHandler(.cancel) decisionHandler(.cancel)

View File

@ -1,3 +1,4 @@
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
// ignore: non_constant_identifier_names
final UUID_GENERATOR = Uuid(); final UUID_GENERATOR = Uuid();

View File

@ -6,8 +6,6 @@ class AndroidWebViewFeature {
static const MethodChannel _channel = const MethodChannel( static const MethodChannel _channel = const MethodChannel(
'com.pichillilorenzo/flutter_inappwebview_android_webviewfeature'); 'com.pichillilorenzo/flutter_inappwebview_android_webviewfeature');
static Future<dynamic> _handleMethod(MethodCall call) async {}
final String _value; final String _value;
const AndroidWebViewFeature._internal(this._value); const AndroidWebViewFeature._internal(this._value);

View File

@ -1,3 +1,7 @@
import 'dart:ui';
import 'package:flutter_inappwebview/src/util.dart';
import '../../types.dart'; import '../../types.dart';
import '../../in_app_browser/in_app_browser_options.dart'; import '../../in_app_browser/in_app_browser_options.dart';
@ -213,7 +217,27 @@ class AndroidInAppWebViewOptions
///Sets whether the default Android error page should be disabled. ///Sets whether the default Android error page should be disabled.
///The default value is `false`. ///The default value is `false`.
bool? disableDefaultErrorPage; bool disableDefaultErrorPage;
///Sets the vertical scrollbar thumb color.
///
///**NOTE**: available on Android 29+.
Color? verticalScrollbarThumbColor;
///Sets the vertical scrollbar track color.
///
///**NOTE**: available on Android 29+.
Color? verticalScrollbarTrackColor;
///Sets the horizontal scrollbar thumb color.
///
///**NOTE**: available on Android 29+.
Color? horizontalScrollbarThumbColor;
///Sets the horizontal scrollbar track color.
///
///**NOTE**: available on Android 29+.
Color? horizontalScrollbarTrackColor;
AndroidInAppWebViewOptions({ AndroidInAppWebViewOptions({
this.textZoom = 100, this.textZoom = 100,
@ -267,7 +291,11 @@ class AndroidInAppWebViewOptions
this.scrollbarFadingEnabled = true, this.scrollbarFadingEnabled = true,
this.scrollBarFadeDuration, this.scrollBarFadeDuration,
this.rendererPriorityPolicy, this.rendererPriorityPolicy,
this.disableDefaultErrorPage, this.disableDefaultErrorPage = false,
this.verticalScrollbarThumbColor,
this.verticalScrollbarTrackColor,
this.horizontalScrollbarThumbColor,
this.horizontalScrollbarTrackColor,
}); });
@override @override
@ -323,7 +351,11 @@ class AndroidInAppWebViewOptions
"scrollbarFadingEnabled": scrollbarFadingEnabled, "scrollbarFadingEnabled": scrollbarFadingEnabled,
"scrollBarFadeDuration": scrollBarFadeDuration, "scrollBarFadeDuration": scrollBarFadeDuration,
"rendererPriorityPolicy": rendererPriorityPolicy?.toMap(), "rendererPriorityPolicy": rendererPriorityPolicy?.toMap(),
"disableDefaultErrorPage": disableDefaultErrorPage "disableDefaultErrorPage": disableDefaultErrorPage,
"verticalScrollbarThumbColor": verticalScrollbarThumbColor?.toHex(),
"verticalScrollbarTrackColor": verticalScrollbarTrackColor?.toHex(),
"horizontalScrollbarThumbColor": horizontalScrollbarThumbColor?.toHex(),
"horizontalScrollbarTrackColor": horizontalScrollbarTrackColor?.toHex(),
}; };
} }
@ -390,6 +422,14 @@ class AndroidInAppWebViewOptions
options.rendererPriorityPolicy = RendererPriorityPolicy.fromMap( options.rendererPriorityPolicy = RendererPriorityPolicy.fromMap(
map["rendererPriorityPolicy"]?.cast<String, dynamic>()); map["rendererPriorityPolicy"]?.cast<String, dynamic>());
options.disableDefaultErrorPage = map["disableDefaultErrorPage"]; options.disableDefaultErrorPage = map["disableDefaultErrorPage"];
options.verticalScrollbarThumbColor =
UtilColor.fromHex(map["verticalScrollbarThumbColor"]);
options.verticalScrollbarTrackColor =
UtilColor.fromHex(map["verticalScrollbarTrackColor"]);
options.horizontalScrollbarThumbColor =
UtilColor.fromHex(map["horizontalScrollbarThumbColor"]);
options.horizontalScrollbarTrackColor =
UtilColor.fromHex(map["horizontalScrollbarTrackColor"]);
return options; return options;
} }

View File

@ -1871,7 +1871,7 @@ class Favicon {
} }
} }
///Class that represents an Android-specific class used to override the way the cache is used. ///An Android-specific class used to override the way the cache is used.
class AndroidCacheMode { class AndroidCacheMode {
final int _value; final int _value;
@ -1932,7 +1932,7 @@ class AndroidCacheMode {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents an Android-specific class used to disable the action mode menu items. ///An Android-specific class used to disable the action mode menu items.
/// ///
///**NOTE**: available on Android 24+. ///**NOTE**: available on Android 24+.
class AndroidActionModeMenuItem { class AndroidActionModeMenuItem {
@ -1996,7 +1996,7 @@ class AndroidActionModeMenuItem {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents an Android-specific class used to indicate the force dark mode. ///An Android-specific class used to indicate the force dark mode.
/// ///
///**NOTE**: available on Android 29+. ///**NOTE**: available on Android 29+.
class AndroidForceDark { class AndroidForceDark {
@ -2053,7 +2053,7 @@ class AndroidForceDark {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents an Android-specific class used to set the underlying layout algorithm. ///An Android-specific class used to set the underlying layout algorithm.
class AndroidLayoutAlgorithm { class AndroidLayoutAlgorithm {
final String _value; final String _value;
@ -2102,7 +2102,7 @@ class AndroidLayoutAlgorithm {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents an Android-specific class used to configure the WebView's behavior when a secure origin attempts to load a resource from an insecure origin. ///An Android-specific class used to configure the WebView's behavior when a secure origin attempts to load a resource from an insecure origin.
/// ///
///**NOTE**: available on Android 21+. ///**NOTE**: available on Android 21+.
class AndroidMixedContentMode { class AndroidMixedContentMode {
@ -2167,7 +2167,7 @@ class AndroidMixedContentMode {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents an iOS-specific class used to set the level of granularity with which the user can interactively select content in the web view. ///An iOS-specific class used to set the level of granularity with which the user can interactively select content in the web view.
class IOSWKSelectionGranularity { class IOSWKSelectionGranularity {
final int _value; final int _value;
@ -2215,7 +2215,7 @@ class IOSWKSelectionGranularity {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents an iOS-specific class used to specify a `dataDetectoryTypes` value that adds interactivity to web content that matches the value. ///An iOS-specific class used to specify a `dataDetectoryTypes` value that adds interactivity to web content that matches the value.
/// ///
///**NOTE**: available on iOS 10.0+. ///**NOTE**: available on iOS 10.0+.
class IOSWKDataDetectorTypes { class IOSWKDataDetectorTypes {
@ -2390,7 +2390,7 @@ class UserPreferredContentMode {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents an iOS-specific class used to specify the modal presentation style when presenting a view controller. ///An iOS-specific class used to specify the modal presentation style when presenting a view controller.
class IOSUIModalPresentationStyle { class IOSUIModalPresentationStyle {
final int _value; final int _value;
@ -2490,7 +2490,7 @@ class IOSUIModalPresentationStyle {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents an iOS-specific class used to specify the transition style when presenting a view controller. ///An iOS-specific class used to specify the transition style when presenting a view controller.
class IOSUIModalTransitionStyle { class IOSUIModalTransitionStyle {
final int _value; final int _value;
@ -2556,7 +2556,7 @@ class IOSUIModalTransitionStyle {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents an iOS-specific class used to set the custom style for the dismiss button. ///An iOS-specific class used to set the custom style for the dismiss button.
/// ///
///**NOTE**: available on iOS 11.0+. ///**NOTE**: available on iOS 11.0+.
class IOSSafariDismissButtonStyle { class IOSSafariDismissButtonStyle {
@ -4618,7 +4618,7 @@ class FormResubmissionAction {
} }
} }
///Class that represents an Android-specific class used to configure the WebView's over-scroll mode. ///An Android-specific class used to configure 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. ///Setting the over-scroll mode of a WebView will have an effect only if the WebView is capable of scrolling.
class AndroidOverScrollMode { class AndroidOverScrollMode {
final int _value; final int _value;
@ -4674,7 +4674,7 @@ class AndroidOverScrollMode {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents an Android-specific class used to configure the style of the scrollbars. ///An Android-specific class used to configure the style of the scrollbars.
///The scrollbars can be overlaid or inset. ///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. ///When inset, they add to the padding of the view. And the scrollbars can be drawn inside the padding area or on the edge of the view.
///For example, if a view has a background drawable and you want to draw the scrollbars inside the padding specified by the drawable, ///For example, if a view has a background drawable and you want to draw the scrollbars inside the padding specified by the drawable,
@ -4748,7 +4748,7 @@ class AndroidScrollBarStyle {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents an Android-specific class used to configure the position of the vertical scroll bar. ///An Android-specific class used to configure the position of the vertical scroll bar.
class AndroidVerticalScrollbarPosition { class AndroidVerticalScrollbarPosition {
final int _value; final int _value;
@ -5181,7 +5181,7 @@ class IOSSslError {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents an iOS-specific class used to configure how safe area insets are added to the adjusted content inset. ///An iOS-specific class used to configure how safe area insets are added to the adjusted content inset.
/// ///
///**NOTE**: available on iOS 11.0+. ///**NOTE**: available on iOS 11.0+.
class IOSUIScrollViewContentInsetAdjustmentBehavior { class IOSUIScrollViewContentInsetAdjustmentBehavior {
@ -5576,6 +5576,7 @@ class ContentWorld {
} }
///The default world for clients. ///The default world for clients.
// ignore: non_constant_identifier_names
static final ContentWorld DEFAULT_CLIENT = static final ContentWorld DEFAULT_CLIENT =
ContentWorld.world(name: "defaultClient"); ContentWorld.world(name: "defaultClient");
@ -5583,6 +5584,7 @@ class ContentWorld {
///This property contains the content world for scripts that the current webpage executes. ///This property contains the content world for scripts that the current webpage executes.
///Be careful when manipulating variables in this content world. ///Be careful when manipulating variables in this content world.
///If you modify a variable with the same name as one the webpage uses, you may unintentionally disrupt the normal operation of that page. ///If you modify a variable with the same name as one the webpage uses, you may unintentionally disrupt the normal operation of that page.
// ignore: non_constant_identifier_names
static final ContentWorld PAGE = ContentWorld.world(name: "page"); static final ContentWorld PAGE = ContentWorld.world(name: "page");
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {

View File

@ -98,9 +98,8 @@ class ASN1Object {
} }
String? get asString { String? get asString {
var string = value as String?; if (value is String) {
if (string != null) { return value;
return string;
} }
if (sub != null && sub!.length > 0) { if (sub != null && sub!.length > 0) {

View File

@ -114,8 +114,8 @@ class X509Certificate {
///Gets the version (version number) value from the certificate. ///Gets the version (version number) value from the certificate.
int? get version { int? get version {
if (block1 != null) { if (block1 != null) {
var v = firstLeafValue(block: block1!) as List<int>?; var v = firstLeafValue(block: block1!);
if (v != null) { if (v is List<int>) {
var index = toIntValue(v); var index = toIntValue(v);
if (index != null) { if (index != null) {
return index.toInt() + 1; return index.toInt() + 1;
@ -126,8 +126,10 @@ class X509Certificate {
} }
///Gets the serialNumber value from the certificate. ///Gets the serialNumber value from the certificate.
List<int> get serialNumber => List<int>? get serialNumber {
block1?.atIndex(X509BlockPosition.serialNumber)?.value as List<int>; var data = block1?.atIndex(X509BlockPosition.serialNumber)?.value;
return data is List<int> ? data : null;
}
///Returns the issuer (issuer distinguished name) value from the certificate as a String. ///Returns the issuer (issuer distinguished name) value from the certificate as a String.
String? get issuerDistinguishedName { String? get issuerDistinguishedName {
@ -143,8 +145,8 @@ class X509Certificate {
var issuerBlock = block1?.atIndex(X509BlockPosition.issuer); var issuerBlock = block1?.atIndex(X509BlockPosition.issuer);
if (issuerBlock != null) { if (issuerBlock != null) {
for (var sub in (issuerBlock.sub ?? <ASN1Object>[])) { for (var sub in (issuerBlock.sub ?? <ASN1Object>[])) {
var value = firstLeafValue(block: sub) as String?; var value = firstLeafValue(block: sub);
if (value != null) { if (value is String) {
result.add(value); result.add(value);
} }
} }
@ -162,8 +164,8 @@ class X509Certificate {
var oidBlock = issuerBlock.findOid(oidValue: oid); var oidBlock = issuerBlock.findOid(oidValue: oid);
if (oidBlock != null) { if (oidBlock != null) {
var sub = oidBlock.parent?.sub; var sub = oidBlock.parent?.sub;
if (sub != null && sub.length > 0) { if (sub != null && sub.length > 0 && sub.last.value is String) {
return sub.last.value as String; return sub.last.value;
} else { } else {
return null; return null;
} }
@ -187,8 +189,8 @@ class X509Certificate {
var subjectBlock = block1?.atIndex(X509BlockPosition.subject); var subjectBlock = block1?.atIndex(X509BlockPosition.subject);
if (subjectBlock != null) { if (subjectBlock != null) {
for (var sub in (subjectBlock.sub ?? <ASN1Object>[])) { for (var sub in (subjectBlock.sub ?? <ASN1Object>[])) {
var value = firstLeafValue(block: sub) as String?; var value = firstLeafValue(block: sub);
if (value != null) { if (value is String) {
result.add(value); result.add(value);
} }
} }
@ -206,8 +208,8 @@ class X509Certificate {
var oidBlock = subjectBlock.findOid(oidValue: oid); var oidBlock = subjectBlock.findOid(oidValue: oid);
if (oidBlock != null) { if (oidBlock != null) {
var sub = oidBlock.parent?.sub; var sub = oidBlock.parent?.sub;
if (sub != null && sub.length > 0) { if (sub != null && sub.length > 0 && sub.last.value is String) {
return sub.last.value as String; return sub.last.value;
} else { } else {
return null; return null;
} }
@ -218,28 +220,33 @@ class X509Certificate {
} }
///Gets the notBefore date from the validity period of the certificate. ///Gets the notBefore date from the validity period of the certificate.
DateTime? get notBefore => DateTime? get notBefore {
block1?.atIndex(X509BlockPosition.dateValidity)?.subAtIndex(0)?.value var data =
as DateTime?; block1?.atIndex(X509BlockPosition.dateValidity)?.subAtIndex(0)?.value;
return data is DateTime ? data : null;
}
///Gets the notAfter date from the validity period of the certificate. ///Gets the notAfter date from the validity period of the certificate.
DateTime? get notAfter { DateTime? get notAfter {
var value = block1 var data =
?.atIndex(X509BlockPosition.dateValidity) block1?.atIndex(X509BlockPosition.dateValidity)?.subAtIndex(1)?.value;
?.subAtIndex(1) return data is DateTime ? data : null;
?.value as DateTime?;
return value;
} }
///Gets the signature value (the raw signature bits) from the certificate. ///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 {
var data = asn1?[0].subAtIndex(2)?.value;
return data is List<int> ? data : null;
}
///Gets the signature algorithm name for the certificate signature algorithm. ///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. ///Gets the signature algorithm OID string from the certificate.
String? get sigAlgOID => String? get sigAlgOID {
block1?.subAtIndex(2)?.subAtIndex(0)?.value as String?; var data = block1?.subAtIndex(2)?.subAtIndex(0)?.value;
return data is String ? data : null;
}
///Gets the DER-encoded signature algorithm parameters from this certificate's signature algorithm. ///Gets the DER-encoded signature algorithm parameters from this certificate's signature algorithm.
List<int>? get sigAlgParams => null; List<int>? get sigAlgParams => null;
@ -264,8 +271,8 @@ class X509Certificate {
if (oidBlock != null) { if (oidBlock != null) {
var sub = oidBlock.parent?.sub; var sub = oidBlock.parent?.sub;
if (sub != null && sub.length > 0) { if (sub != null && sub.length > 0) {
var data = sub.last.subAtIndex(0)?.value as List<int>?; var data = sub.last.subAtIndex(0)?.value;
int bits = (data != null && data.length > 0) ? data.first : 0; int bits = (data is List<int> && data.length > 0) ? data.first : 0;
for (var index = 0; index < 8; index++) { for (var index = 0; index < 8; index++) {
var value = bits & (1 << index).toUnsigned(8) != 0; var value = bits & (1 << index).toUnsigned(8) != 0;
result.insert(0, value); result.insert(0, value);

View File

@ -108,18 +108,18 @@ class X509Extension {
case 1: case 1:
case 2: case 2:
case 6: case 6:
String? name = item.value as String?; var name = item.value is String ? item.value : null;
return name; return name;
case 4: case 4:
return ASN1DistinguishedNames.string(block: item); return ASN1DistinguishedNames.string(block: item);
case 7: case 7:
var ip = item.value as List<int>?; var ip = item.value is List<int> ? item.value : null;
if (ip != null) { if (ip != null) {
return ip.map((e) => e.toString()).join("."); return ip.map((e) => e.toString()).join(".");
} }
break; break;
case 8: case 8:
var value = item.value as String?; var value = item.value is String ? item.value : null;
if (value != null) { if (value != null) {
try { try {
var data = utf8.encode(value); var data = utf8.encode(value);
@ -139,12 +139,14 @@ class X509Extension {
class BasicConstraintExtension extends X509Extension { class BasicConstraintExtension extends X509Extension {
BasicConstraintExtension({required block}) : super(block: block); BasicConstraintExtension({required block}) : super(block: block);
bool get isCA => bool get isCA {
valueAsBlock?.subAtIndex(0)?.subAtIndex(0)?.value as bool? ?? false; var data = valueAsBlock?.subAtIndex(0)?.subAtIndex(0)?.value;
return data is bool ? data : false;
}
int? get pathLenConstraint { int? get pathLenConstraint {
var data = valueAsBlock?.subAtIndex(0)?.subAtIndex(0)?.value as List<int>?; var data = valueAsBlock?.subAtIndex(0)?.subAtIndex(0)?.value;
if (data != null) { if (data is List<int>) {
return data.length; return data.length;
} }
return null; return null;

View File

@ -1,6 +1,6 @@
name: flutter_inappwebview 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. 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-nullsafety.0 version: 5.0.1-nullsafety.1
homepage: https://github.com/pichillilorenzo/flutter_inappwebview homepage: https://github.com/pichillilorenzo/flutter_inappwebview
environment: environment: