Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
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
@@ -1,3 +1,7 @@
## 2.4.0

* Implemented new `loadFile` and `loadHtmlString` methods from the platform interface.

## 2.3.0

* Implemented new `loadRequest` method from platform interface.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objectVersion = 50;
objects = {

/* Begin PBXBuildFile section */
Expand Down Expand Up @@ -273,7 +273,7 @@
isa = PBXProject;
attributes = {
DefaultBuildSystemTypeForWorkspace = Original;
LastUpgradeCheck = 1030;
LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "The Flutter Authors";
TargetAttributes = {
68BDCAE823C3F7CB00D9C032 = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1030"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,201 @@ - (void)testContentInsetsSumAlwaysZeroAfterSetFrame {
}
}

- (void)testLoadFileSucceeds {
NSString *testFilePath = @"/assets/file.html";
NSURL *url = [NSURL fileURLWithPath:testFilePath isDirectory:NO];
XCTestExpectation *resultExpectation =
[self expectationWithDescription:@"Should return successful result over the method channel."];
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
FLTWKWebView *mockWebView = OCMClassMock(FLTWKWebView.class);
controller.webView = mockWebView;
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadFile"
arguments:testFilePath]
result:^(id _Nullable result) {
XCTAssertNil(result);
[resultExpectation fulfill];
}];

[self waitForExpectations:@[ resultExpectation ] timeout:30.0];
OCMVerify([mockWebView loadFileURL:url
allowingReadAccessToURL:[url URLByDeletingLastPathComponent]]);
}

- (void)testLoadFileFailsWithInvalidPath {
NSArray *resultExpectations = @[
[self expectationWithDescription:@"Should return failed result when argument is nil."],
[self expectationWithDescription:
@"Should return failed result when argument is not of type NSString*."],
[self expectationWithDescription:
@"Should return failed result when argument is an empty string."],
];

FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
FLTWKWebView *mockWebView = OCMClassMock(FLTWKWebView.class);
controller.webView = mockWebView;
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadFile" arguments:nil]
result:^(id _Nullable result) {
FlutterError *expected =
[FlutterError errorWithCode:@"loadFile_failed"
message:@"Failed parsing file path."
details:@"Argument is nil."];
[FLTWebViewTests assertFlutterError:result withExpected:expected];
[resultExpectations[0] fulfill];
}];
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadFile" arguments:@(10)]
result:^(id _Nullable result) {
FlutterError *expected =
[FlutterError errorWithCode:@"loadFile_failed"
message:@"Failed parsing file path."
details:@"Argument is not of type NSString."];
[FLTWebViewTests assertFlutterError:result withExpected:expected];
[resultExpectations[1] fulfill];
}];
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadFile" arguments:@""]
result:^(id _Nullable result) {
FlutterError *expected =
[FlutterError errorWithCode:@"loadFile_failed"
message:@"Failed parsing file path."
details:@"Argument contains an empty string."];
[FLTWebViewTests assertFlutterError:result withExpected:expected];
[resultExpectations[2] fulfill];
}];

[self waitForExpectations:resultExpectations timeout:1.0];
OCMReject([mockWebView loadFileURL:[OCMArg any] allowingReadAccessToURL:[OCMArg any]]);
}

- (void)testLoadFileSucceedsWithBaseUrl {
NSURL *baseUrl = [NSURL URLWithString:@"https://flutter.dev"];
XCTestExpectation *resultExpectation =
[self expectationWithDescription:@"Should return successful result over the method channel."];
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
FLTWKWebView *mockWebView = OCMClassMock(FLTWKWebView.class);
controller.webView = mockWebView;
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadHtmlString"
arguments:@{
@"html" : @"some HTML string",
@"baseUrl" : @"https://flutter.dev"
}]
result:^(id _Nullable result) {
XCTAssertNil(result);
[resultExpectation fulfill];
}];

[self waitForExpectations:@[ resultExpectation ] timeout:30.0];
OCMVerify([mockWebView loadHTMLString:@"some HTML string" baseURL:baseUrl]);
}

- (void)testLoadFileSucceedsWithoutBaseUrl {
XCTestExpectation *resultExpectation =
[self expectationWithDescription:@"Should return successful result over the method channel."];
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
FLTWKWebView *mockWebView = OCMClassMock(FLTWKWebView.class);
controller.webView = mockWebView;
[controller
onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadHtmlString"
arguments:@{@"html" : @"some HTML string"}]
result:^(id _Nullable result) {
XCTAssertNil(result);
[resultExpectation fulfill];
}];

[self waitForExpectations:@[ resultExpectation ] timeout:30.0];
OCMVerify([mockWebView loadHTMLString:@"some HTML string" baseURL:nil]);
}

- (void)testLoadHtmlStringFailsWithInvalidArgument {
NSArray *resultExpectations = @[
[self expectationWithDescription:@"Should return failed result when argument is nil."],
[self expectationWithDescription:
@"Should return failed result when argument is not of type NSDictionary*."],
[self expectationWithDescription:@"Should return failed result when HTML argument is nil."],
[self expectationWithDescription:
@"Should return failed result when HTML argument is not of type NSString*."],
[self expectationWithDescription:
@"Should return failed result when HTML argument is an empty string."],
];

FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
FLTWKWebView *mockWebView = OCMClassMock(FLTWKWebView.class);
controller.webView = mockWebView;
FlutterError *expected = [FlutterError
errorWithCode:@"loadHtmlString_failed"
message:@"Failed parsing arguments."
details:@"Arguments should be a dictionary containing at least a 'html' element and "
@"optionally a 'baseUrl' argument. For example: `@{ @\"html\": @\"some html "
@"code\", @\"baseUrl\": @\"https://flutter.dev\" }`"];
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadHtmlString"
arguments:nil]
result:^(id _Nullable result) {
[FLTWebViewTests assertFlutterError:result withExpected:expected];
[resultExpectations[0] fulfill];
}];
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadHtmlString"
arguments:@""]
result:^(id _Nullable result) {
[FLTWebViewTests assertFlutterError:result withExpected:expected];
[resultExpectations[1] fulfill];
}];
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadHtmlString"
arguments:@{}]
result:^(id _Nullable result) {
FlutterError *expected =
[FlutterError errorWithCode:@"loadHtmlString_failed"
message:@"Failed parsing HTML string argument."
details:@"Argument is nil."];
[FLTWebViewTests assertFlutterError:result withExpected:expected];
[resultExpectations[2] fulfill];
}];
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadHtmlString"
arguments:@{
@"html" : @(42),
}]
result:^(id _Nullable result) {
FlutterError *expected =
[FlutterError errorWithCode:@"loadHtmlString_failed"
message:@"Failed parsing HTML string argument."
details:@"Argument is not of type NSString."];
[FLTWebViewTests assertFlutterError:result withExpected:expected];
[resultExpectations[3] fulfill];
}];
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadHtmlString"
arguments:@{
@"html" : @"",
}]
result:^(id _Nullable result) {
FlutterError *expected =
[FlutterError errorWithCode:@"loadHtmlString_failed"
message:@"Failed parsing HTML string argument."
details:@"Argument contains an empty string."];
[FLTWebViewTests assertFlutterError:result withExpected:expected];
[resultExpectations[4] fulfill];
}];

[self waitForExpectations:resultExpectations timeout:1.0];
OCMReject([mockWebView loadHTMLString:[OCMArg any] baseURL:[OCMArg any]]);
}

- (void)testRunJavascriptFailsForNullString {
// Setup
FLTWebViewController *controller =
Expand Down Expand Up @@ -302,6 +497,14 @@ - (void)testRunJavascriptReturningResultReturnsErrorResultForWKError {
[self waitForExpectationsWithTimeout:30.0 handler:nil];
}

+ (void)assertFlutterError:(id)actual withExpected:(FlutterError *)expected {
XCTAssertTrue([actual class] == [FlutterError class]);
FlutterError *errorResult = actual;
XCTAssertEqualObjects(errorResult.code, expected.code);
XCTAssertEqualObjects(errorResult.message, expected.message);
XCTAssertEqualObjects(errorResult.details, expected.details);
}

- (void)testBuildNSURLRequestReturnsNilForNonDictionaryValue {
// Setup
FLTWebViewController *controller =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';

import 'navigation_decision.dart';
Expand All @@ -34,6 +37,25 @@ The navigation delegate is set to block navigation to the youtube website.
</html>
''';

const String kLocalFileExamplePage = '''
<!DOCTYPE html>
<html lang="en">
<head>
<title>Load file or HTML string example</title>
</head>
<body>

<h1>Local demo page</h1>
<p>
This is an example page used to demonstrate how to load a local file or HTML
string using the <a href="https://pub.dev/packages/webview_flutter">Flutter
webview</a> plugin.
</p>

</body>
</html>
''';

class _WebViewExample extends StatefulWidget {
const _WebViewExample({Key? key}) : super(key: key);

Expand Down Expand Up @@ -121,6 +143,8 @@ enum _MenuOptions {
listCache,
clearCache,
navigationDelegate,
loadLocalFile,
loadHtmlString,
doPostRequest,
}

Expand Down Expand Up @@ -159,6 +183,12 @@ class _SampleMenu extends StatelessWidget {
case _MenuOptions.navigationDelegate:
_onNavigationDelegateExample(controller.data!, context);
break;
case _MenuOptions.loadLocalFile:
_onLoadLocalFileExample(controller.data!, context);
break;
case _MenuOptions.loadHtmlString:
_onLoadHtmlStringExample(controller.data!, context);
break;
case _MenuOptions.doPostRequest:
_onDoPostRequest(controller.data!, context);
break;
Expand Down Expand Up @@ -194,6 +224,14 @@ class _SampleMenu extends StatelessWidget {
value: _MenuOptions.navigationDelegate,
child: Text('Navigation Delegate example'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.loadHtmlString,
child: Text('Load HTML string'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.loadLocalFile,
child: Text('Load local file'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.doPostRequest,
child: Text('Post Request'),
Expand Down Expand Up @@ -268,6 +306,18 @@ class _SampleMenu extends StatelessWidget {
await controller.loadUrl('data:text/html;base64,$contentBase64');
}

void _onLoadLocalFileExample(
WebViewController controller, BuildContext context) async {
String pathToIndex = await _prepareLocalFile();

await controller.loadFile(pathToIndex);
}

void _onLoadHtmlStringExample(
WebViewController controller, BuildContext context) async {
await controller.loadHtmlString(kLocalFileExamplePage);
}

void _onDoPostRequest(
WebViewController controller, BuildContext context) async {
WebViewRequest request = WebViewRequest(
Expand All @@ -292,6 +342,16 @@ class _SampleMenu extends StatelessWidget {
children: cookieWidgets.toList(),
);
}

static Future<String> _prepareLocalFile() async {
final String tmpDir = (await getTemporaryDirectory()).path;
File indexFile = File('$tmpDir/www/index.html');

await Directory('$tmpDir/www').create(recursive: true);
await indexFile.writeAsString(kLocalFileExamplePage);

return indexFile.path;
}
}

class _NavigationControls extends StatelessWidget {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,35 @@ class WebViewController {

WebView _widget;

/// Loads the file located on the specified [absoluteFilePath].
///
/// The [absoluteFilePath] parameter should contain the absolute path to the
/// file as it is stored on the device. For example:
/// `/Users/username/Documents/www/index.html`.
///
/// Throws an ArgumentError if the [absoluteFilePath] does not exist.
Future<void> loadFile(
String absoluteFilePath,
) {
assert(absoluteFilePath.isNotEmpty);
return _webViewPlatformController.loadFile(absoluteFilePath);
}

/// Loads the supplied HTML string.
///
/// The [baseUrl] parameter is used when resolving relative URLs within the
/// HTML string.
Future<void> loadHtmlString(
String html, {
String? baseUrl,
}) {
assert(html.isNotEmpty);
return _webViewPlatformController.loadHtmlString(
html,
baseUrl: baseUrl,
);
}

/// Loads the specified URL.
///
/// If `headers` is not null and the URL is an HTTP URL, the key value paris in `headers` will
Expand Down
Loading