added createWebArchiveData iOS-specific WebView method, Moved saveWebArchive WebView method from Android-specific to cross-platform

This commit is contained in:
Lorenzo Pichilli 2021-02-09 01:39:35 +01:00
parent b15ae759d5
commit 88bfe9036f
12 changed files with 220 additions and 79 deletions

View File

@ -10,7 +10,7 @@
- Added `addUserScript`, `addUserScripts`, `removeUserScript`, `removeUserScripts`, `removeAllUserScripts`, `callAsyncJavaScript` WebView methods
- Added `contentWorld` argument to `evaluateJavascript` WebView method
- Added `isDirectionalLockEnabled`, `mediaType`, `pageZoom`, `limitsNavigationsToAppBoundDomains` iOS-specific WebView options
- Added `handlesURLScheme`, `createPdf` iOS-specific WebView methods
- Added `handlesURLScheme`, `createPdf`, `createWebArchiveData` iOS-specific WebView methods
- Added `iosAnimated` optional argument to `zoomBy` WebView method
- Added `screenshotConfiguration` optional argument to `takeScreenshot` WebView method
- Updated integration tests
@ -44,6 +44,7 @@
- `allowUniversalAccessFromFileURLs` and `allowFileAccessFromFileURLs` WebView options moved from Android-specific options to cross-platform options
- Added `callAsyncJavaScript` name to the list of javaScriptHandlerForbiddenNames
- Changed `zoomBy` WebView method signature
- Moved `saveWebArchive` WebView method from Android-specific to cross-platform
## 4.0.0+4

View File

@ -494,6 +494,7 @@ Android-specific methods can be called using the `InAppWebViewController.android
iOS-specific methods can be called using the `InAppWebViewController.ios` attribute. Static methods can be called using the `IOSInAppWebViewController` class directly.
* `createPdf({IOSWKPDFConfiguration? iosWKPdfConfiguration})`: Generates PDF data from the web views contents asynchronously.
* `createWebArchiveData`: Creates a web archive of the web views current contents asynchronously.
* `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.
* `static handlesURLScheme(String urlScheme)`: Returns a Boolean value that indicates whether WebKit natively supports resources with the specified URL scheme.

View File

@ -338,9 +338,9 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
break;
case "saveWebArchive":
if (webView != null) {
String basename = (String) call.argument("basename");
String filePath = (String) call.argument("filePath");
boolean autoname = (boolean) call.argument("autoname");
webView.saveWebArchive(basename, autoname, new ValueCallback<String>() {
webView.saveWebArchive(filePath, autoname, new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
result.success(value);

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/.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":"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/.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":"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-08 18:26:05.315620","version":"1.26.0-18.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/.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":"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/.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":"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-09 01:23:18.308862","version":"1.26.0-18.0.pre.90"}

View File

@ -262,7 +262,6 @@
"${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}/pdf_viewer_plugin/pdf_viewer_plugin.framework",
"${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework",
);
name = "[CP] Embed Pods Frameworks";
@ -272,7 +271,6 @@
"${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}/pdf_viewer_plugin.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework",
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -2,8 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSDocumentsFolderUsageDescription</key>
<string>InAppWebView requires access to documents folder</string>
<key>NSMicrophoneUsageDescription</key>
<string>InAppWebView requires acess to mic.</string>
<string>InAppWebView requires access to mic.</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
@ -64,7 +66,7 @@
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>NSCameraUsageDescription</key>
<string>InAppWebView requires acess to cam.</string>
<string>InAppWebView requires access to cam.</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Allow Flutter tools on your computer to connect and debug your application.</string>
</dict>

View File

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
// import 'package:path_provider/path_provider.dart';
import 'package:url_launcher/url_launcher.dart';
import 'main.dart';

View File

@ -18,6 +18,7 @@ Future main() async {
WidgetsFlutterBinding.ensureInitialized();
// await Permission.camera.request();
// await Permission.microphone.request();
// await Permission.storage.request();
if (Platform.isAndroid) {
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);

View File

@ -1700,70 +1700,117 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
: currentIndex + steps >= 0
}
@available(iOS 11.0, *)
public func takeScreenshot (with: [String: Any?]?, completionHandler: @escaping (_ screenshot: Data?) -> Void) {
if #available(iOS 11.0, *) {
var snapshotConfiguration: WKSnapshotConfiguration? = nil
if let with = with {
snapshotConfiguration = WKSnapshotConfiguration()
if let rect = with["rect"] as? [String: Double] {
snapshotConfiguration!.rect = CGRect(x: rect["x"]!, y: rect["y"]!, width: rect["width"]!, height: rect["height"]!)
}
if let snapshotWidth = with["snapshotWidth"] as? Double {
snapshotConfiguration!.snapshotWidth = NSNumber(value: snapshotWidth)
}
if #available(iOS 13.0, *), let afterScreenUpdates = with["iosAfterScreenUpdates"] as? Bool {
snapshotConfiguration!.afterScreenUpdates = afterScreenUpdates
}
var snapshotConfiguration: WKSnapshotConfiguration? = nil
if let with = with {
snapshotConfiguration = WKSnapshotConfiguration()
if let rect = with["rect"] as? [String: Double] {
snapshotConfiguration!.rect = CGRect(x: rect["x"]!, y: rect["y"]!, width: rect["width"]!, height: rect["height"]!)
}
takeSnapshot(with: snapshotConfiguration, completionHandler: {(image, error) -> Void in
var imageData: Data? = nil
if let screenshot = image {
if let with = with {
switch with["compressFormat"] as! String {
case "JPEG":
let quality = Float(with["quality"] as! Int) / 100
imageData = screenshot.jpegData(compressionQuality: CGFloat(quality))!
break
case "PNG":
imageData = screenshot.pngData()!
break
default:
imageData = screenshot.pngData()!
}
}
else {
if let snapshotWidth = with["snapshotWidth"] as? Double {
snapshotConfiguration!.snapshotWidth = NSNumber(value: snapshotWidth)
}
if #available(iOS 13.0, *), let afterScreenUpdates = with["iosAfterScreenUpdates"] as? Bool {
snapshotConfiguration!.afterScreenUpdates = afterScreenUpdates
}
}
takeSnapshot(with: snapshotConfiguration, completionHandler: {(image, error) -> Void in
var imageData: Data? = nil
if let screenshot = image {
if let with = with {
switch with["compressFormat"] as! String {
case "JPEG":
let quality = Float(with["quality"] as! Int) / 100
imageData = screenshot.jpegData(compressionQuality: CGFloat(quality))!
break
case "PNG":
imageData = screenshot.pngData()!
break
default:
imageData = screenshot.pngData()!
}
}
completionHandler(imageData)
})
} else {
completionHandler(nil)
else {
imageData = screenshot.pngData()!
}
}
completionHandler(imageData)
})
}
@available(iOS 14.0, *)
public func createPdf (configuration: [String: Any?]?, completionHandler: @escaping (_ pdf: Data?) -> Void) {
let pdfConfiguration: WKPDFConfiguration = .init()
if let configuration = configuration {
if let rect = configuration["rect"] as? [String: Double] {
pdfConfiguration.rect = CGRect(x: rect["x"]!, y: rect["y"]!, width: rect["width"]!, height: rect["height"]!)
}
}
createPDF(configuration: pdfConfiguration) { (result) in
switch (result) {
case .success(let data):
completionHandler(data)
return
case .failure(let error):
print(error.localizedDescription)
completionHandler(nil)
return
}
}
}
public func createPdf (configuration: [String: Any?]?, completionHandler: @escaping (_ pdf: Data?) -> Void) {
if #available(iOS 14.0, *) {
let pdfConfiguration: WKPDFConfiguration = .init()
if let configuration = configuration {
if let rect = configuration["rect"] as? [String: Double] {
pdfConfiguration.rect = CGRect(x: rect["x"]!, y: rect["y"]!, width: rect["width"]!, height: rect["height"]!)
}
@available(iOS 14.0, *)
public func createWebArchiveData (dataCompletionHandler: @escaping (_ webArchiveData: Data?) -> Void) {
createWebArchiveData(completionHandler: { (result) in
switch (result) {
case .success(let data):
dataCompletionHandler(data)
return
case .failure(let error):
print(error.localizedDescription)
dataCompletionHandler(nil)
return
}
createPDF(configuration: pdfConfiguration) { (result) in
switch (result) {
case .success(let data):
completionHandler(data)
return
case .failure(let error):
})
}
@available(iOS 14.0, *)
public func saveWebArchive (filePath: String, autoname: Bool, completionHandler: @escaping (_ path: String?) -> Void) {
createWebArchiveData(dataCompletionHandler: { (webArchiveData) in
if let webArchiveData = webArchiveData {
var localUrl = URL(fileURLWithPath: filePath)
if autoname {
if let url = self.url {
// tries to mimic Android saveWebArchive method
let invalidCharacters = CharacterSet(charactersIn: "\\/:*?\"<>|")
.union(.newlines)
.union(.illegalCharacters)
.union(.controlCharacters)
let currentPageUrlFileName = url.path
.components(separatedBy: invalidCharacters)
.joined(separator: "")
let fullPath = filePath + "/" + currentPageUrlFileName + ".webarchive"
localUrl = URL(fileURLWithPath: fullPath)
} else {
completionHandler(nil)
return
}
}
do {
try webArchiveData.write(to: localUrl)
completionHandler(localUrl.path)
} catch {
// Catch any errors
print(error.localizedDescription)
completionHandler(nil)
return
}
} else {
completionHandler(nil)
}
} else {
completionHandler(nil)
}
})
}
public func loadUrl(url: URL, headers: [String: String]?) {

View File

@ -128,7 +128,7 @@ class InAppWebViewMethodHandler: FlutterMethodCallDelegate {
result(webView?.isLoading ?? false)
break
case "takeScreenshot":
if webView != nil {
if webView != nil, #available(iOS 11.0, *) {
let screenshotConfiguration = arguments!["screenshotConfiguration"] as? [String: Any?]
webView!.takeScreenshot(with: screenshotConfiguration, completionHandler: { (screenshot) -> Void in
result(screenshot)
@ -403,7 +403,7 @@ class InAppWebViewMethodHandler: FlutterMethodCallDelegate {
}
break
case "createPdf":
if webView != nil {
if webView != nil, #available(iOS 14.0, *) {
let configuration = arguments!["iosWKPdfConfiguration"] as? [String: Any?]
webView!.createPdf(configuration: configuration, completionHandler: { (pdf) -> Void in
result(pdf)
@ -413,6 +413,28 @@ class InAppWebViewMethodHandler: FlutterMethodCallDelegate {
result(nil)
}
break
case "createWebArchiveData":
if webView != nil, #available(iOS 14.0, *) {
webView!.createWebArchiveData(dataCompletionHandler: { (webArchiveData) -> Void in
result(webArchiveData)
})
}
else {
result(nil)
}
break
case "saveWebArchive":
if webView != nil, #available(iOS 14.0, *) {
let filePath = arguments!["filePath"] as! String
let autoname = arguments!["autoname"] as! Bool
webView!.saveWebArchive(filePath: filePath, autoname: autoname, completionHandler: { (path) -> Void in
result(path)
})
}
else {
result(nil)
}
break
default:
result(FlutterMethodNotImplemented)
break

View File

@ -1508,7 +1508,7 @@ class InAppWebViewController {
///
///[screenshotConfiguration] represents the configuration data to use when generating an image from a web views contents.
///
///**NOTE for iOS**: available from iOS 11.0+.
///**NOTE for iOS**: available on iOS 11.0+.
///
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/2873260-takesnapshot
Future<Uint8List?> takeScreenshot({ScreenshotConfiguration? screenshotConfiguration}) async {
@ -2088,6 +2088,35 @@ class InAppWebViewController {
return CallAsyncJavaScriptResult(value: data["value"], error: data["error"]);
}
///Saves the current WebView as a web archive.
///Returns the file path under which the web archive file was saved, or `null` if saving the file failed.
///
///[filePath] represents the file path where the archive should be placed. This value cannot be `null`.
///
///[autoname] if `false`, takes [filePath] to be a file.
///If `true`, [filePath] is assumed to be a directory in which a filename will be chosen according to the URL of the current page.
///
///**NOTE for iOS**: Available on iOS 14.0+. If [autoname] is `false`, the [filePath] must ends with the [WebArchiveFormat.WEBARCHIVE] file extension.
///
///**NOTE for Android**: if [autoname] is `false`, the [filePath] must ends with the [WebArchiveFormat.MHT] file extension.
///
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#saveWebArchive(java.lang.String,%20boolean,%20android.webkit.ValueCallback%3Cjava.lang.String%3E)
Future<String?> saveWebArchive(
{required String filePath, bool autoname = false}) async {
if (!autoname) {
if (Platform.isAndroid) {
assert(filePath.endsWith("." + WebArchiveFormat.MHT.toValue()));
} else if (Platform.isIOS) {
assert(filePath.endsWith("." + WebArchiveFormat.WEBARCHIVE.toValue()));
}
}
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("filePath", () => filePath);
args.putIfAbsent("autoname", () => autoname);
return await _channel.invokeMethod('saveWebArchive', args);
}
///Gets the default user agent.
///
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebSettings#getDefaultUserAgent(android.content.Context)
@ -2180,23 +2209,6 @@ class AndroidInAppWebViewController {
return await _controller._channel.invokeMethod('pageUp', args);
}
///Saves the current WebView as a web archive.
///Returns the filename under which the file was saved, or `null` if saving the file failed.
///
///[basename] the filename where the archive should be placed. This value cannot be `null`.
///
///[autoname] if `false`, takes basename to be a file.
///If `true`, [basename] is assumed to be a directory in which a filename will be chosen according to the URL of the current page.
///
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#saveWebArchive(java.lang.String,%20boolean,%20android.webkit.ValueCallback%3Cjava.lang.String%3E)
Future<String?> saveWebArchive(
{required String basename, required bool autoname}) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("basename", () => basename);
args.putIfAbsent("autoname", () => autoname);
return await _controller._channel.invokeMethod('saveWebArchive', args);
}
///Performs zoom in in this WebView.
///Returns `true` if zoom in succeeds, `false` if no zoom changes.
///
@ -2337,14 +2349,30 @@ class IOSInAppWebViewController {
}
///Generates PDF data from the web views contents asynchronously.
///Returns `null` if a problem occurred.
///
///[iosWKPdfConfiguration] represents the object that specifies the portion of the web view to capture as PDF data.
///
///**NOTE**: available only on iOS 14.0+.
///
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/3650490-createpdf
Future<Uint8List?> createPdf({IOSWKPDFConfiguration? iosWKPdfConfiguration}) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('iosWKPdfConfiguration', () => iosWKPdfConfiguration?.toMap());
return await _controller._channel.invokeMethod('createPdf', args);
}
///Creates a web archive of the web views current contents asynchronously.
///Returns `null` if a problem occurred.
///
///**NOTE**: available only on iOS 14.0+.
///
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/3650491-createwebarchivedata
Future<Uint8List?> createWebArchiveData() async {
Map<String, dynamic> args = <String, dynamic>{};
return await _controller._channel.invokeMethod('createWebArchiveData', args);
}
///Returns a Boolean value that indicates whether WebKit natively supports resources with the specified URL scheme.
///
///[urlScheme] represents the URL scheme associated with the resource.

View File

@ -4873,4 +4873,44 @@ class IOSWKPDFConfiguration {
String toString() {
return toMap().toString();
}
}
///Class that represents the known Web Archive formats used when saving a web page.
class WebArchiveFormat {
final String _value;
const WebArchiveFormat._internal(this._value);
static final Set<WebArchiveFormat> values = [
WebArchiveFormat.MHT,
WebArchiveFormat.WEBARCHIVE
].toSet();
static WebArchiveFormat? fromValue(String? value) {
if (value != null) {
try {
return WebArchiveFormat.values.firstWhere(
(element) => element.toValue() == value);
} catch (e) {
return null;
}
}
return null;
}
String toValue() => _value;
@override
String toString() => _value;
///Web Archive format used only by Android.
static const MHT = const WebArchiveFormat._internal("mht");
///Web Archive format used only by iOS.
static const WEBARCHIVE = const WebArchiveFormat._internal("webarchive");
bool operator ==(value) => value == _value;
@override
int get hashCode => _value.hashCode;
}