Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[webview_flutter] Expose loadFile and loadHtmlString through app facing package. #4558

Merged
merged 18 commits into from
Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
d124eeb
Added `loadData` and `loadDataWithBaseUrl` to API.
mvanbeusekom Nov 24, 2021
e8c529f
Added `loadData` and `loadDataWithBaseUrl` JAVA implementation.
mvanbeusekom Nov 24, 2021
2977a6e
Merge remote-tracking branch 'upstream/master' into webview_load_file…
mvanbeusekom Nov 25, 2021
801139e
Adds Dart implementation of `loadData` and `loadDataWithBaseUrl`.
mvanbeusekom Nov 25, 2021
6b16597
Adds example usage of `loadFile` and `loadHtmlString` methods.
mvanbeusekom Nov 25, 2021
f47425a
Added missing license information
mvanbeusekom Nov 25, 2021
7b63509
Remove unused import from test
mvanbeusekom Nov 25, 2021
5f43f82
Ignore avoid_relative_file_lib_imports and unnecessary_parenthesis
mvanbeusekom Nov 25, 2021
c55603e
Process feedback on PR
mvanbeusekom Nov 29, 2021
481b063
Merge remote-tracking branch 'upstream/master' into webview_load_file…
mvanbeusekom Nov 29, 2021
9f2edd0
Regenerate mock objects
mvanbeusekom Nov 29, 2021
2c40c34
Merge remote-tracking branch 'upstream/master' into webview_load_file…
mvanbeusekom Nov 30, 2021
f8e9c32
Expose loadFile and loadHtmlString.
mvanbeusekom Nov 30, 2021
67df993
Tests for the loadFile and loadHtmlString methods.
mvanbeusekom Nov 30, 2021
c247686
Add loadHtmlString and loadFile feature to example
mvanbeusekom Nov 30, 2021
15ae840
Update version and CHANGELOG.
mvanbeusekom Nov 30, 2021
8a08a7a
Merge remote-tracking branch 'upstream/master' into webview_load_file…
mvanbeusekom Nov 30, 2021
b4807b5
Apply PR feedback
mvanbeusekom Dec 6, 2021
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
3 changes: 2 additions & 1 deletion packages/webview_flutter/webview_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## NEXT
## 2.4.0

* Adds support for the `loadFile` and `loadHtmlString` methods.
* Updates example app Android compileSdkVersion to 31.
* Integration test fixes.
* Updates code for new analysis options.
Expand Down
59 changes: 59 additions & 0 deletions packages/webview_flutter/webview_flutter/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() => runApp(MaterialApp(home: WebViewExample()));
Expand All @@ -28,6 +29,25 @@ The navigation delegate is set to block navigation to the youtube website.
</html>
''';

const String kLocalExamplePage = '''
<!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 {
@override
_WebViewExampleState createState() => _WebViewExampleState();
Expand Down Expand Up @@ -133,6 +153,8 @@ enum MenuOptions {
listCache,
clearCache,
navigationDelegate,
loadLocalFile,
loadHtmlString,
}

class SampleMenu extends StatelessWidget {
Expand Down Expand Up @@ -171,6 +193,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;
}
},
itemBuilder: (BuildContext context) => <PopupMenuItem<MenuOptions>>[
Expand Down Expand Up @@ -203,6 +231,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'),
),
],
);
},
Expand Down Expand Up @@ -279,6 +315,18 @@ class SampleMenu extends StatelessWidget {
await controller.loadUrl('data:text/html;base64,$contentBase64');
}

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

await controller.loadFile(pathToIndex);
}

Future<void> _onLoadHtmlStringExample(
WebViewController controller, BuildContext context) async {
await controller.loadHtmlString(kLocalExamplePage);
}

Widget _getCookieList(String cookies) {
if (cookies == null || cookies == '""') {
return Container();
Expand All @@ -292,6 +340,17 @@ class SampleMenu extends StatelessWidget {
children: cookieWidgets.toList(),
);
}

static Future<String> _prepareLocalFile() async {
final String tmpDir = (await getTemporaryDirectory()).path;
final File indexFile = File(
<String>{tmpDir, 'www', 'index.html'}.join(Platform.pathSeparator));

await indexFile.create(recursive: true);
await indexFile.writeAsString(kLocalExamplePage);

return indexFile.path;
}
}

class NavigationControls extends StatelessWidget {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ environment:
dependencies:
flutter:
sdk: flutter
path_provider: ^2.0.6
webview_flutter:
# When depending on this package from a real application you should use:
# webview_flutter: ^x.y.z
Expand Down
29 changes: 29 additions & 0 deletions packages/webview_flutter/webview_flutter/lib/src/webview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,35 @@ class WebViewController {

WebView _widget;

/// Loads the file located at 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
4 changes: 2 additions & 2 deletions packages/webview_flutter/webview_flutter/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: webview_flutter
description: A Flutter plugin that provides a WebView widget on Android and iOS.
repository: https://github.com/flutter/plugins/tree/master/packages/webview_flutter/webview_flutter
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
version: 2.3.1
version: 2.4.0

environment:
sdk: ">=2.14.0 <3.0.0"
Expand All @@ -19,7 +19,7 @@ flutter:
dependencies:
flutter:
sdk: flutter
webview_flutter_android: ^2.3.1
webview_flutter_android: ^2.4.0
webview_flutter_platform_interface: ^1.5.2
webview_flutter_wkwebview: ^2.4.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,98 @@ void main() {
expect(disabledparams.webSettings!.javascriptMode, JavascriptMode.disabled);
});

testWidgets('Load file', (WidgetTester tester) async {
WebViewController? controller;
await tester.pumpWidget(
WebView(
onWebViewCreated: (WebViewController webViewController) {
controller = webViewController;
},
),
);

expect(controller, isNotNull);

await controller!.loadFile('/test/path/index.html');

verify(mockWebViewPlatformController.loadFile(
'/test/path/index.html',
));
});

testWidgets('Load file with empty path', (WidgetTester tester) async {
WebViewController? controller;
await tester.pumpWidget(
WebView(
onWebViewCreated: (WebViewController webViewController) {
controller = webViewController;
},
),
);

expect(controller, isNotNull);

expect(() => controller!.loadFile(''), throwsAssertionError);
});

testWidgets('Load HTML string without base URL', (WidgetTester tester) async {
WebViewController? controller;
await tester.pumpWidget(
WebView(
onWebViewCreated: (WebViewController webViewController) {
controller = webViewController;
},
),
);

expect(controller, isNotNull);

await controller!.loadHtmlString('<p>This is a test paragraph.</p>');

verify(mockWebViewPlatformController.loadHtmlString(
'<p>This is a test paragraph.</p>',
));
});

testWidgets('Load HTML string with base URL', (WidgetTester tester) async {
WebViewController? controller;
await tester.pumpWidget(
WebView(
onWebViewCreated: (WebViewController webViewController) {
controller = webViewController;
},
),
);

expect(controller, isNotNull);

await controller!.loadHtmlString(
'<p>This is a test paragraph.</p>',
baseUrl: 'https://flutter.dev',
);

verify(mockWebViewPlatformController.loadHtmlString(
'<p>This is a test paragraph.</p>',
baseUrl: 'https://flutter.dev',
));
});

testWidgets('Load HTML string with empty string',
(WidgetTester tester) async {
WebViewController? controller;
await tester.pumpWidget(
WebView(
onWebViewCreated: (WebViewController webViewController) {
controller = webViewController;
},
),
);

expect(controller, isNotNull);

expect(() => controller!.loadHtmlString(''), throwsAssertionError);
});

testWidgets('Load url', (WidgetTester tester) async {
WebViewController? controller;
await tester.pumpWidget(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Mocks generated by Mockito 5.0.16 from annotations
// in webview_flutter/test/webview_flutter_test.dart.
// Do not manually edit this file.
Expand Down Expand Up @@ -81,12 +77,28 @@ class MockWebViewPlatformController extends _i1.Mock
_i1.throwOnMissingStub(this);
}

@override
_i9.Future<void> loadFile(String? absoluteFilePath) =>
(super.noSuchMethod(Invocation.method(#loadFile, [absoluteFilePath]),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
@override
_i9.Future<void> loadHtmlString(String? html, {String? baseUrl}) =>
(super.noSuchMethod(
Invocation.method(#loadHtmlString, [html], {#baseUrl: baseUrl}),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
@override
_i9.Future<void> loadUrl(String? url, Map<String, String>? headers) =>
(super.noSuchMethod(Invocation.method(#loadUrl, [url, headers]),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
@override
_i9.Future<void> loadRequest(_i4.WebViewRequest? request) =>
(super.noSuchMethod(Invocation.method(#loadRequest, [request]),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
@override
_i9.Future<void> updateSettings(_i4.WebSettings? setting) =>
(super.noSuchMethod(Invocation.method(#updateSettings, [setting]),
returnValue: Future<void>.value(),
Expand Down