Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ public void onMethodCall(MethodCall methodCall, Result result) {
case "loadUrl":
loadUrl(methodCall, result);
break;
case "loadData":
loadData(methodCall, result);
break;
case "loadDataBase64":
loadDataBase64(methodCall, result);
break;
case "updateSettings":
updateSettings(methodCall, result);
break;
Expand Down Expand Up @@ -239,6 +245,33 @@ private void loadUrl(MethodCall methodCall, Result result) {
result.success(null);
}

@SuppressWarnings("unchecked")
private void loadData(MethodCall methodCall, Result result) {
Map<String, Object> request = (Map<String, Object>) methodCall.arguments;
String baseUrl = (String) request.get("baseUrl");
String data = (String) request.get("data");
String mimeType = (String) request.get("mimeType");

final String encoding = "UTF-8";
webView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, null);
result.success(null);
}

@SuppressWarnings("unchecked")
private void loadDataBase64(MethodCall methodCall, Result result) {
Map<String, Object> request = (Map<String, Object>) methodCall.arguments;
String data = (String) request.get("data");
String mimeType = (String) request.get("mimeType");

// We do not use baseUrl, because Android has no way to set it in this context.

// Theoretically, we should be able to use WebView#loadDataWithBaseURL here, but
// support for base64 seems to be broken.
final String url = String.format("data:%s;base64,%s", mimeType, data);
webView.loadUrl(url);
result.success(null);
}

private void canGoBack(Result result) {
result.success(webView.canGoBack());
}
Expand Down
110 changes: 110 additions & 0 deletions packages/webview_flutter/ios/Classes/FlutterWebView.m
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ - (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
[self onUpdateSettings:call result:result];
} else if ([[call method] isEqualToString:@"loadUrl"]) {
[self onLoadUrl:call result:result];
} else if ([[call method] isEqualToString:@"loadData"]) {
[self onLoadData:call result:result];
} else if ([[call method] isEqualToString:@"loadDataBase64"]) {
[self onLoadDataBase64:call result:result];
} else if ([[call method] isEqualToString:@"canGoBack"]) {
[self onCanGoBack:call result:result];
} else if ([[call method] isEqualToString:@"canGoForward"]) {
Expand Down Expand Up @@ -183,6 +187,112 @@ - (void)onLoadUrl:(FlutterMethodCall*)call result:(FlutterResult)result {
}
}

- (void)onLoadData:(FlutterMethodCall*)call result:(FlutterResult)result {
NSDictionary<NSString*, id>* arguments = [call arguments];
if (!arguments) {
result([FlutterError errorWithCode:@"loadData_failed"
message:@"No arguments passed to method"
details:nil]);
return;
}

NSString* const encoding = @"UTF-8";
NSString* mimeType = arguments[@"mimeType"];
NSString* baseUrl = arguments[@"baseUrl"];
NSString* dataStr = arguments[@"data"];

if (![mimeType isKindOfClass:[NSString class]]) {
result([FlutterError errorWithCode:@"loadData_failed"
message:@"Argument type of mimeType is not string"
details:nil]);
return;
}

if (![baseUrl isKindOfClass:[NSString class]]) {
result([FlutterError errorWithCode:@"loadData_failed"
message:@"Argument type of baseUrl is not string"
details:nil]);
return;
}

NSURL* nsUrl = [NSURL URLWithString:baseUrl];
if (!nsUrl) {
result([FlutterError errorWithCode:@"loadData_failed"
message:@"Argument type of baseUrl is not a valid URL"
details:[NSString stringWithFormat:@"URL was: '%@'", baseUrl]]);
return;
}

if (![dataStr isKindOfClass:[NSString class]]) {
result([FlutterError errorWithCode:@"loadData_failed"
message:@"Argument type of data is not string"
details:nil]);
return;
}

NSData* data = [dataStr dataUsingEncoding:NSUTF8StringEncoding];
if (@available(iOS 9.0, *)) {
[_webView loadData:data MIMEType:mimeType characterEncodingName:encoding baseURL:nsUrl];
} else {
NSLog(@"Setting data is not supported for Flutter WebViews prior to iOS 9.");
}

result(nil);
}

- (void)onLoadDataBase64:(FlutterMethodCall*)call result:(FlutterResult)result {
NSDictionary<NSString*, id>* arguments = [call arguments];
if (!arguments) {
result([FlutterError errorWithCode:@"loadDataBase64_failed"
message:@"No arguments passed to method"
details:nil]);
return;
}

NSString* const encoding = @"UTF-8";
NSString* mimeType = arguments[@"mimeType"];
NSString* dataStr = arguments[@"data"];
NSString* baseUrl = arguments[@"baseUrl"];

if (![mimeType isKindOfClass:[NSString class]]) {
result([FlutterError errorWithCode:@"loadDataBase64_failed"
message:@"Argument type of mimeType is not string"
details:nil]);
return;
}

if (![dataStr isKindOfClass:[NSString class]]) {
result([FlutterError errorWithCode:@"loadDataBase64_failed"
message:@"Argument type of data is not string"
details:nil]);
return;
}

if (![baseUrl isKindOfClass:[NSString class]]) {
result([FlutterError errorWithCode:@"loadDataBase64_failed"
message:@"Argument type of baseUrl is not string"
details:nil]);
return;
}

NSURL* nsUrl = [NSURL URLWithString:baseUrl];
if (!nsUrl) {
result([FlutterError errorWithCode:@"loadData_failed"
message:@"Argument type of baseUrl is not a valid URL"
details:[NSString stringWithFormat:@"URL was: '%@'", baseUrl]]);
return;
}

NSData* data = [[NSData alloc] initWithBase64EncodedString:dataStr options:0];
if (@available(iOS 9.0, *)) {
[_webView loadData:data MIMEType:mimeType characterEncodingName:encoding baseURL:nsUrl];
} else {
NSLog(@"Setting data is not supported for Flutter WebViews prior to iOS 9.");
}

result(nil);
}

- (void)onCanGoBack:(FlutterMethodCall*)call result:(FlutterResult)result {
BOOL canGoBack = [_webView canGoBack];
result([NSNumber numberWithBool:canGoBack]);
Expand Down
35 changes: 35 additions & 0 deletions packages/webview_flutter/lib/platform_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,41 @@ abstract class WebViewPlatformController {
"WebView loadUrl is not implemented on the current platform");
}

/// Loads the specified content data into the WebView.
///
/// The string `data` will be interpreted as a UTF-8 string.
///
/// `baseUrl` is the apparent URL which the page was loaded at, used to resolve
/// relative paths.
///
/// Throws an ArgumentError if `baseUrl` is not a valid URL string.
Future<void> loadData(
String data,
String baseUrl,
String mimeType,
) {
throw UnimplementedError(
"WebView loadData is not implemented on the current platform");
}

/// Loads the specified content data into the WebView.
///
/// The string `data` will be interpreted as a Base64 encoded string. Note
/// that any trailing padding = or == characters MUST be present for full device
/// compatibility.
///
/// The `baseUrl` argument is required but has no effect on Android.
///
/// Throws an ArgumentError if `baseUrl` is not a valid URL string.
Future<void> loadDataBase64(
String data,
String mimeType,
String baseUrl,
) {
throw UnimplementedError(
"WebView loadDataBase64 is not implemented on the current platform");
}

/// Updates the webview settings.
///
/// Any non null field in `settings` will be set as the new setting value.
Expand Down
32 changes: 32 additions & 0 deletions packages/webview_flutter/lib/src/webview_method_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,38 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController {
});
}

@override
Future<void> loadData(
String data,
String baseUrl,
String mimeType,
) async {
assert(data != null);
assert(baseUrl != null);
assert(mimeType != null);
return _channel.invokeMethod<void>('loadData', <String, dynamic>{
'data': data,
'baseUrl': baseUrl,
'mimeType': mimeType,
});
}

@override
Future<void> loadDataBase64(
String data,
String mimeType,
String baseUrl,
) async {
assert(data != null);
assert(mimeType != null);
assert(baseUrl != null);
return _channel.invokeMethod<void>('loadDataBase64', <String, dynamic>{
'data': data,
'mimeType': mimeType,
'baseUrl': baseUrl,
});
}

@override
Future<String> currentUrl() => _channel.invokeMethod<String>('currentUrl');

Expand Down
39 changes: 39 additions & 0 deletions packages/webview_flutter/lib/webview_flutter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,45 @@ class WebViewController {
return _webViewPlatformController.loadUrl(url, headers);
}

/// Loads the specified content data into the WebView.
///
/// The string `data` will be interpreted as a UTF-8 string.
///
/// `baseUrl` is the apparent URL which the page was loaded at, used to resolve
/// relative paths.
///
/// Throws an ArgumentError if `baseUrl` is not a valid URL string.
Future<void> loadData(
String data, {
@required String baseUrl,
@required String mimeType,
}) async {
assert(data != null);
assert(baseUrl != null);
assert(mimeType != null);
_validateUrlString(baseUrl);
return _webViewPlatformController.loadData(data, baseUrl, mimeType);
}

/// Loads the specified content data into the WebView.
///
/// The string `data` will be interpreted as a Base64 encoded string. Note
/// that any trailing padding = or == characters MUST be present for full device
/// compatibility.
///
/// The `baseUrl` argument is required but has no effect on Android.
///
/// Throws an ArgumentError if `baseUrl` is not a valid URL string.
Future<void> loadDataBase64(
String data, {
@required String mimeType,
@required String baseUrl,
}) async {
assert(data != null);
assert(mimeType != null);
return _webViewPlatformController.loadDataBase64(data, mimeType, baseUrl);
}

/// Accessor to the current URL that the WebView is displaying.
///
/// If [WebView.initialUrl] was never specified, returns `null`.
Expand Down