33// found in the LICENSE file.
44
55import 'dart:async' ;
6+ import 'dart:math' ;
67
78import 'package:flutter/foundation.dart' ;
9+ import 'package:flutter/services.dart' ;
810import 'package:flutter/widgets.dart' ;
11+ import 'package:path/path.dart' as path;
912import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart' ;
1013
1114import 'foundation/foundation.dart' ;
@@ -194,6 +197,19 @@ class WebKitWebViewPlatformController extends WebViewPlatformController {
194197 };
195198 }
196199
200+ @override
201+ Future <void > loadHtmlString (String html, {String ? baseUrl}) {
202+ return webView.loadHtmlString (html, baseUrl: baseUrl);
203+ }
204+
205+ @override
206+ Future <void > loadFile (String absoluteFilePath) async {
207+ await webView.loadFileUrl (
208+ absoluteFilePath,
209+ readAccessUrl: path.dirname (absoluteFilePath),
210+ );
211+ }
212+
197213 @override
198214 Future <void > clearCache () {
199215 return webView.configuration.webSiteDataStore.removeDataOfTypes (
@@ -207,6 +223,124 @@ class WebKitWebViewPlatformController extends WebViewPlatformController {
207223 );
208224 }
209225
226+ @override
227+ Future <void > loadFlutterAsset (String key) async {
228+ assert (key.isNotEmpty);
229+ return webView.loadFlutterAsset (key);
230+ }
231+
232+ @override
233+ Future <void > loadUrl (String url, Map <String , String >? headers) async {
234+ final NSUrlRequest request = NSUrlRequest (
235+ url: url,
236+ allHttpHeaderFields: headers ?? < String , String > {},
237+ );
238+ return webView.loadRequest (request);
239+ }
240+
241+ @override
242+ Future <void > loadRequest (WebViewRequest request) async {
243+ if (! request.uri.hasScheme) {
244+ throw ArgumentError ('WebViewRequest#uri is required to have a scheme.' );
245+ }
246+
247+ final NSUrlRequest urlRequest = NSUrlRequest (
248+ url: request.uri.toString (),
249+ allHttpHeaderFields: request.headers,
250+ httpMethod: describeEnum (request.method),
251+ httpBody: request.body,
252+ );
253+
254+ return webView.loadRequest (urlRequest);
255+ }
256+
257+ @override
258+ Future <bool > canGoBack () => webView.canGoBack;
259+
260+ @override
261+ Future <bool > canGoForward () => webView.canGoForward;
262+
263+ @override
264+ Future <void > goBack () => webView.goBack ();
265+
266+ @override
267+ Future <void > goForward () => webView.goForward ();
268+
269+ @override
270+ Future <void > reload () => webView.reload ();
271+
272+ @override
273+ Future <String > evaluateJavascript (String javascript) async {
274+ final Object ? result = await webView.evaluateJavaScript (javascript);
275+ // The legacy implementation of webview_flutter_wkwebview would convert
276+ // objects to strings before returning them to Dart. This method attempts
277+ // to converts Dart objects to Strings the way it is done in Objective-C
278+ // to avoid breaking users expecting the same String format.
279+ return _asObjectiveCString (result);
280+ }
281+
282+ @override
283+ Future <void > runJavascript (String javascript) async {
284+ try {
285+ await webView.evaluateJavaScript (javascript);
286+ } on PlatformException catch (exception) {
287+ // WebKit will throw an error when the type of the evaluated value is
288+ // unsupported. This also goes for `null` and `undefined` on iOS 14+. For
289+ // example, when running a void function. For ease of use, this specific
290+ // error is ignored when no return value is expected.
291+ // TODO(bparrishMines): Ensure the platform code includes the NSError in
292+ // the FlutterError.details.
293+ if (exception.details is ! NSError ||
294+ exception.details.code !=
295+ WKErrorCode .javaScriptResultTypeIsUnsupported) {
296+ rethrow ;
297+ }
298+ }
299+ }
300+
301+ @override
302+ Future <String > runJavascriptReturningResult (String javascript) async {
303+ final Object ? result = await webView.evaluateJavaScript (javascript);
304+ if (result == null ) {
305+ throw ArgumentError (
306+ 'Result of JavaScript execution returned a `null` value. '
307+ 'Use `runJavascript` when expecting a null return value.' ,
308+ );
309+ }
310+ return result.toString ();
311+ }
312+
313+ @override
314+ Future <String ?> getTitle () => webView.title;
315+
316+ @override
317+ Future <void > scrollTo (int x, int y) async {
318+ webView.scrollView.contentOffset = Point <double >(
319+ x.toDouble (),
320+ y.toDouble (),
321+ );
322+ }
323+
324+ @override
325+ Future <void > scrollBy (int x, int y) async {
326+ await webView.scrollView.scrollBy (Point <double >(
327+ x.toDouble (),
328+ y.toDouble (),
329+ ));
330+ }
331+
332+ @override
333+ Future <int > getScrollX () async {
334+ final Point <double > offset = await webView.scrollView.contentOffset;
335+ return offset.x.toInt ();
336+ }
337+
338+ @override
339+ Future <int > getScrollY () async {
340+ final Point <double > offset = await webView.scrollView.contentOffset;
341+ return offset.y.toInt ();
342+ }
343+
210344 @override
211345 Future <void > updateSettings (WebSettings setting) async {
212346 if (setting.hasNavigationDelegate != null ) {
@@ -324,6 +458,35 @@ class WebKitWebViewPlatformController extends WebViewPlatformController {
324458 errorType: errorType,
325459 );
326460 }
461+
462+ String _asObjectiveCString (Object ? value, {bool inContainer = false }) {
463+ if (value == null ) {
464+ // An NSNull inside an NSArray or NSDictionary is represented as a String
465+ // differently than a nil.
466+ if (inContainer) {
467+ return '"<null>"' ;
468+ }
469+ return '(null)' ;
470+ } else if (value is List ) {
471+ final List <String > stringValues = < String > [];
472+ for (final Object ? listValue in value) {
473+ stringValues.add (_asObjectiveCString (listValue, inContainer: true ));
474+ }
475+ return '(${stringValues .join (',' )})' ;
476+ } else if (value is Map ) {
477+ final List <String > stringValues = < String > [];
478+ for (final MapEntry <Object ?, Object ?> entry in value.entries) {
479+ stringValues.add (
480+ '${_asObjectiveCString (entry .key , inContainer : true )} '
481+ '= '
482+ '${_asObjectiveCString (entry .value , inContainer : true )}' ,
483+ );
484+ }
485+ return '{${stringValues .join (';' )}}' ;
486+ }
487+
488+ return value.toString ();
489+ }
327490}
328491
329492/// Handles constructing objects and calling static methods.
0 commit comments