added loadSimulatedRequest iOS webview method

This commit is contained in:
Lorenzo Pichilli 2022-10-08 18:57:29 +02:00
parent 85ff4c1234
commit 386bd2097e
6 changed files with 105 additions and 4 deletions

View File

@ -6,7 +6,7 @@
- Added `PrintJobController` to manage print jobs
- Added `WebAuthenticationSession` for iOS
- Added `FindInteractionController` for Android and iOS
- Added `pauseAllMediaPlayback`, `setAllMediaPlaybackSuspended`, `closeAllMediaPresentations`, `requestMediaPlaybackState`, `isInFullscreen`, `getCameraCaptureState`, `setCameraCaptureState`, `getMicrophoneCaptureState`, `setMicrophoneCaptureState` WebView controller methods
- Added `pauseAllMediaPlayback`, `setAllMediaPlaybackSuspended`, `closeAllMediaPresentations`, `requestMediaPlaybackState`, `isInFullscreen`, `getCameraCaptureState`, `setCameraCaptureState`, `getMicrophoneCaptureState`, `setMicrophoneCaptureState`, `loadSimulatedRequest` WebView controller methods
- Added `underPageBackgroundColor`, `isTextInteractionEnabled`, `isSiteSpecificQuirksModeEnabled`, `upgradeKnownHostsToHTTPS`, `forceDarkStrategy`, `willSuppressErrorPage`, `algorithmicDarkeningAllowed`, `requestedWithHeaderMode`, `enterpriseAuthenticationAppLinkPolicyEnabled`, `isElementFullscreenEnabled`, `isFindInteractionEnabled`, `minimumViewportInset`, `maximumViewportInset` WebView settings
- Added `onCameraCaptureStateChanged`, `onMicrophoneCaptureStateChanged` WebView events
- Added support for `onPermissionRequest` event on iOS 15.0+

View File

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
@ -8,7 +9,7 @@ import 'package:flutter_test/flutter_test.dart';
import '../constants.dart';
void loadUrl() {
final shouldSkip = kIsWeb ? false :
final shouldSkip1 = kIsWeb ? false :
![
TargetPlatform.android,
TargetPlatform.iOS,
@ -49,5 +50,49 @@ void loadUrl() {
await controller.loadUrl(
urlRequest: URLRequest(url: TEST_CROSS_PLATFORM_URL_1));
expect(await loadedUrl.future, TEST_CROSS_PLATFORM_URL_1.toString());
}, skip: shouldSkip);
}, skip: shouldSkip1);
final shouldSkip2 = kIsWeb ? false :
![
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
testWidgets('loadSimulatedRequest', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>();
final Completer<String> firstUrlLoad = Completer<String>();
final Completer<String> loadedUrl = Completer<String>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest:
URLRequest(url: initialUrl),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
onLoadStop: (controller, url) {
if (url.toString() == initialUrl.toString() && !firstUrlLoad.isCompleted) {
firstUrlLoad.complete(url.toString());
} else if (url.toString() == TEST_CROSS_PLATFORM_URL_1.toString() && !loadedUrl.isCompleted) {
loadedUrl.complete(url.toString());
}
},
),
),
);
final InAppWebViewController controller =
await controllerCompleter.future;
expect(await firstUrlLoad.future, initialUrl.toString());
final htmlCode = "<h1>Hello</h1>";
await controller.loadSimulatedRequest(
urlRequest: URLRequest(url: TEST_CROSS_PLATFORM_URL_1),
data: Uint8List.fromList(utf8.encode(htmlCode))
);
expect(await loadedUrl.future, TEST_CROSS_PLATFORM_URL_1.toString());
expect(await controller.evaluateJavascript(source: "document.body").toString().trim(), htmlCode);
}, skip: shouldSkip2);
}

View File

@ -640,6 +640,23 @@ public class WebViewChannelDelegate : ChannelDelegate {
result(false)
}
break
case .loadSimulatedRequest:
if let webView = webView, #available(iOS 15.0, *) {
let request = URLRequest.init(fromPluginMap: arguments!["urlRequest"] as! [String:Any?])
let data = arguments!["data"] as! FlutterStandardTypedData
var response: URLResponse? = nil
if let urlResponse = arguments!["urlResponse"] as? [String:Any?] {
response = URLResponse.init(fromPluginMap: urlResponse)
}
if let response = response {
webView.loadSimulatedRequest(request, response: response, responseData: data.data)
} else {
webView.loadSimulatedRequest(request, responseHTML: String(decoding: data.data, as: UTF8.self))
}
result(true)
} else {
result(false)
}
}
}

View File

@ -86,4 +86,5 @@ public enum WebViewChannelDelegateMethods: String {
case setCameraCaptureState = "setCameraCaptureState"
case getMicrophoneCaptureState = "getMicrophoneCaptureState"
case setMicrophoneCaptureState = "setMicrophoneCaptureState"
case loadSimulatedRequest = "loadSimulatedRequest"
}

View File

@ -8,6 +8,14 @@
import Foundation
extension URLResponse {
public convenience init?(fromPluginMap: [String:Any?]) {
let url = URL(string: fromPluginMap["url"] as? String ?? "about:blank")!
let mimeType = fromPluginMap["mimeType"] as? String
let expectedContentLength = fromPluginMap["expectedContentLength"] as? Int64 ?? 0
let textEncodingName = fromPluginMap["textEncodingName"] as? String
self.init(url: url, mimeType: mimeType, expectedContentLength: Int(expectedContentLength), textEncodingName: textEncodingName)
}
public func toMap () -> [String:Any?] {
let httpResponse: HTTPURLResponse? = self as? HTTPURLResponse
return [

View File

@ -1619,7 +1619,7 @@ class InAppWebViewController {
///Loads the given [url] with [postData] (x-www-form-urlencoded) using `POST` method into this WebView.
///
///Example
///Example:
///```dart
///var postData = Uint8List.fromList(utf8.encode("firstname=Foo&surname=Bar"));
///controller.postUrl(url: Uri.parse("https://www.example.com/"), postData: postData);
@ -3371,6 +3371,36 @@ class InAppWebViewController {
await _channel.invokeMethod('setMicrophoneCaptureState', args);
}
///Loads the web content from the data you provide as if the data were the response to the request.
///If [urlResponse] is `null`, it loads the web content from the data as an utf8 encoded HTML string as the response to the request.
///
///[urlRequest] represents a URL request that specifies the base URL and other loading details the system uses to interpret the data you provide.
///
///[urlResponse] represents a response the system uses to interpret the data you provide.
///
///[data] represents the data or the utf8 encoded HTML string to use as the contents of the webpage.
///
///Example:
///```dart
///controller.loadSimulateloadSimulatedRequestdRequest(urlRequest: URLRequest(
/// url: Uri.parse("https://flutter.dev"),
/// ),
/// data: Uint8List.fromList(utf8.encode("<h1>Hello</h1>"))
///);
///```
///
///**NOTE for iOS**: available on iOS 15.0+.
///
///**Supported Platforms/Implementations**:
///- iOS ([Official API - WKWebView.loadSimulatedRequest(_:response:responseData:)](https://developer.apple.com/documentation/webkit/wkwebview/3763094-loadsimulatedrequest) and [Official API - WKWebView.loadSimulatedRequest(_:responseHTML:)](https://developer.apple.com/documentation/webkit/wkwebview/3763095-loadsimulatedrequest)).
Future<void> loadSimulatedRequest({required URLRequest urlRequest, required Uint8List data, URLResponse? urlResponse}) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('urlRequest', () => urlRequest.toMap());
args.putIfAbsent('data', () => data);
args.putIfAbsent('urlResponse', () => urlResponse?.toMap());
await _channel.invokeMethod('loadSimulatedRequest', args);
}
///Returns the iframe `id` attribute used on the Web platform.
///
///**Supported Platforms/Implementations**: