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

Commit 131036d

Browse files
authored
[webview_flutter] WKWebView implementation of loadFlutterAsset method. (#4582)
1 parent ab99ed5 commit 131036d

9 files changed

Lines changed: 196 additions & 3 deletions

File tree

packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.7.0
2+
3+
* Adds implementation of the `loadFlutterAsset` method from the platform interface.
4+
15
## 2.6.0
26

37
* Implements new cookie manager for setting cookies and providing initial cookies.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<!DOCTYPE html>
2+
<!-- Copyright 2013 The Flutter Authors. All rights reserved.
3+
Use of this source code is governed by a BSD-style license that can be
4+
found in the LICENSE file. -->
5+
<html lang="en">
6+
<head>
7+
<title>Load file or HTML string example</title>
8+
<link rel="stylesheet" href="styles/style.css" />
9+
</head>
10+
<body>
11+
12+
<h1>Local demo page</h1>
13+
<p>
14+
This is an example page used to demonstrate how to load a local file or HTML
15+
string using the <a href="https://pub.dev/packages/webview_flutter">Flutter
16+
webview</a> plugin.
17+
</p>
18+
19+
</body>
20+
</html>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
h1 {
2+
color: blue;
3+
}

packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,120 @@ - (void)testLoadFileFailsWithInvalidPath {
164164
OCMReject([mockWebView loadFileURL:[OCMArg any] allowingReadAccessToURL:[OCMArg any]]);
165165
}
166166

167-
- (void)testLoadFileSucceedsWithBaseUrl {
167+
- (void)testLoadFlutterAssetSucceeds {
168+
NSBundle *mockBundle = OCMPartialMock([NSBundle mainBundle]);
169+
NSString *filePath = [FlutterDartProject lookupKeyForAsset:@"assets/file.html"];
170+
NSURL *url = [NSURL URLWithString:[@"file:///" stringByAppendingString:filePath]];
171+
[OCMStub([mockBundle URLForResource:[filePath stringByDeletingPathExtension]
172+
withExtension:@"html"]) andReturn:(url)];
173+
174+
XCTestExpectation *resultExpectation =
175+
[self expectationWithDescription:@"Should return successful result over the method channel."];
176+
FLTWebViewController *controller =
177+
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
178+
viewIdentifier:1
179+
arguments:nil
180+
binaryMessenger:self.mockBinaryMessenger];
181+
FLTWKWebView *mockWebView = OCMClassMock(FLTWKWebView.class);
182+
controller.webView = mockWebView;
183+
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadFlutterAsset"
184+
arguments:@"assets/file.html"]
185+
result:^(id _Nullable result) {
186+
XCTAssertNil(result);
187+
[resultExpectation fulfill];
188+
}];
189+
190+
[self waitForExpectations:@[ resultExpectation ] timeout:1.0];
191+
OCMVerify([mockWebView loadFileURL:url
192+
allowingReadAccessToURL:[url URLByDeletingLastPathComponent]]);
193+
}
194+
195+
- (void)testLoadFlutterAssetFailsWithInvalidKey {
196+
NSArray *resultExpectations = @[
197+
[self expectationWithDescription:@"Should return failed result when argument is nil."],
198+
[self expectationWithDescription:
199+
@"Should return failed result when argument is not of type NSString*."],
200+
[self expectationWithDescription:
201+
@"Should return failed result when argument is an empty string."],
202+
];
203+
204+
FLTWebViewController *controller =
205+
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
206+
viewIdentifier:1
207+
arguments:nil
208+
binaryMessenger:self.mockBinaryMessenger];
209+
FLTWKWebView *mockWebView = OCMClassMock(FLTWKWebView.class);
210+
controller.webView = mockWebView;
211+
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadFlutterAsset"
212+
arguments:nil]
213+
result:^(id _Nullable result) {
214+
FlutterError *expected =
215+
[FlutterError errorWithCode:@"loadFlutterAsset_invalidKey"
216+
message:@"Supplied asset key is not valid."
217+
details:@"Argument is nil."];
218+
[FLTWebViewTests assertFlutterError:result withExpected:expected];
219+
[resultExpectations[0] fulfill];
220+
}];
221+
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadFlutterAsset"
222+
arguments:@(10)]
223+
result:^(id _Nullable result) {
224+
FlutterError *expected =
225+
[FlutterError errorWithCode:@"loadFlutterAsset_invalidKey"
226+
message:@"Supplied asset key is not valid."
227+
details:@"Argument is not of type NSString."];
228+
[FLTWebViewTests assertFlutterError:result withExpected:expected];
229+
[resultExpectations[1] fulfill];
230+
}];
231+
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadFlutterAsset"
232+
arguments:@""]
233+
result:^(id _Nullable result) {
234+
FlutterError *expected =
235+
[FlutterError errorWithCode:@"loadFlutterAsset_invalidKey"
236+
message:@"Supplied asset key is not valid."
237+
details:@"Argument contains an empty string."];
238+
[FLTWebViewTests assertFlutterError:result withExpected:expected];
239+
[resultExpectations[2] fulfill];
240+
}];
241+
242+
[self waitForExpectations:resultExpectations timeout:1.0];
243+
OCMReject([mockWebView loadFileURL:[OCMArg any] allowingReadAccessToURL:[OCMArg any]]);
244+
}
245+
246+
- (void)testLoadFlutterAssetFailsWithParsingError {
247+
NSBundle *mockBundle = OCMPartialMock([NSBundle mainBundle]);
248+
NSString *filePath = [FlutterDartProject lookupKeyForAsset:@"assets/file.html"];
249+
[OCMStub([mockBundle URLForResource:[filePath stringByDeletingPathExtension]
250+
withExtension:@"html"]) andReturn:(nil)];
251+
252+
XCTestExpectation *resultExpectation =
253+
[self expectationWithDescription:@"Should return failed result over the method channel."];
254+
FLTWebViewController *controller =
255+
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
256+
viewIdentifier:1
257+
arguments:nil
258+
binaryMessenger:self.mockBinaryMessenger];
259+
FLTWKWebView *mockWebView = OCMClassMock(FLTWKWebView.class);
260+
controller.webView = mockWebView;
261+
[controller
262+
onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"loadFlutterAsset"
263+
arguments:@"assets/file.html"]
264+
result:^(id _Nullable result) {
265+
FlutterError *expected = [FlutterError
266+
errorWithCode:@"loadFlutterAsset_invalidKey"
267+
message:@"Failed parsing file path for supplied key."
268+
details:[NSString
269+
stringWithFormat:
270+
@"Failed to convert path '%@' into NSURL for key '%@'.",
271+
filePath, @"assets/file.html"]];
272+
[FLTWebViewTests assertFlutterError:result withExpected:expected];
273+
[resultExpectation fulfill];
274+
}];
275+
276+
[self waitForExpectations:@[ resultExpectation ] timeout:1.0];
277+
OCMReject([mockWebView loadFileURL:[OCMArg any] allowingReadAccessToURL:[OCMArg any]]);
278+
}
279+
280+
- (void)testLoadHtmlStringSucceedsWithBaseUrl {
168281
NSURL *baseUrl = [NSURL URLWithString:@"https://flutter.dev"];
169282
XCTestExpectation *resultExpectation =
170283
[self expectationWithDescription:@"Should return successful result over the method channel."];
@@ -189,7 +302,7 @@ - (void)testLoadFileSucceedsWithBaseUrl {
189302
OCMVerify([mockWebView loadHTMLString:@"some HTML string" baseURL:baseUrl]);
190303
}
191304

192-
- (void)testLoadFileSucceedsWithoutBaseUrl {
305+
- (void)testLoadHtmlStringSucceedsWithoutBaseUrl {
193306
XCTestExpectation *resultExpectation =
194307
[self expectationWithDescription:@"Should return successful result over the method channel."];
195308
FLTWebViewController *controller =

packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ enum _MenuOptions {
171171
listCache,
172172
clearCache,
173173
navigationDelegate,
174+
loadFlutterAsset,
174175
loadLocalFile,
175176
loadHtmlString,
176177
doPostRequest,
@@ -214,6 +215,9 @@ class _SampleMenu extends StatelessWidget {
214215
case _MenuOptions.navigationDelegate:
215216
_onNavigationDelegateExample(controller.data!, context);
216217
break;
218+
case _MenuOptions.loadFlutterAsset:
219+
_onLoadFlutterAssetExample(controller.data!, context);
220+
break;
217221
case _MenuOptions.loadLocalFile:
218222
_onLoadLocalFileExample(controller.data!, context);
219223
break;
@@ -261,6 +265,10 @@ class _SampleMenu extends StatelessWidget {
261265
value: _MenuOptions.navigationDelegate,
262266
child: Text('Navigation Delegate example'),
263267
),
268+
const PopupMenuItem<_MenuOptions>(
269+
value: _MenuOptions.loadFlutterAsset,
270+
child: Text('Load Flutter Asset'),
271+
),
264272
const PopupMenuItem<_MenuOptions>(
265273
value: _MenuOptions.loadHtmlString,
266274
child: Text('Load HTML string'),
@@ -355,6 +363,11 @@ class _SampleMenu extends StatelessWidget {
355363
await controller.loadUrl('data:text/html;base64,$contentBase64');
356364
}
357365

366+
Future<void> _onLoadFlutterAssetExample(
367+
WebViewController controller, BuildContext context) async {
368+
await controller.loadFlutterAsset('assets/www/index.html');
369+
}
370+
358371
Future<void> _onLoadLocalFileExample(
359372
WebViewController controller, BuildContext context) async {
360373
final String pathToIndex = await _prepareLocalFile();

packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,14 @@ class WebViewController {
319319

320320
WebView _widget;
321321

322+
/// Loads the Flutter asset specified in the pubspec.yaml file.
323+
///
324+
/// Throws an ArgumentError if [key] is not part of the specified assets
325+
/// in the pubspec.yaml file.
326+
Future<void> loadFlutterAsset(String key) {
327+
return _webViewPlatformController.loadFlutterAsset(key);
328+
}
329+
322330
/// Loads the file located on the specified [absoluteFilePath].
323331
///
324332
/// The [absoluteFilePath] parameter should contain the absolute path to the

packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,5 @@ flutter:
3434
assets:
3535
- assets/sample_audio.ogg
3636
- assets/sample_video.mp4
37+
- assets/www/index.html
38+
- assets/www/styles/style.css

packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ - (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
163163
[self onUpdateSettings:call result:result];
164164
} else if ([[call method] isEqualToString:@"loadFile"]) {
165165
[self onLoadFile:call result:result];
166+
} else if ([[call method] isEqualToString:@"loadFlutterAsset"]) {
167+
[self onLoadFlutterAsset:call result:result];
166168
} else if ([[call method] isEqualToString:@"loadHtmlString"]) {
167169
[self onLoadHtmlString:call result:result];
168170
} else if ([[call method] isEqualToString:@"loadUrl"]) {
@@ -244,6 +246,34 @@ - (void)onLoadFile:(FlutterMethodCall*)call result:(FlutterResult)result {
244246
result(nil);
245247
}
246248

249+
- (void)onLoadFlutterAsset:(FlutterMethodCall*)call result:(FlutterResult)result {
250+
NSString* error = nil;
251+
if (![FLTWebViewController isValidStringArgument:[call arguments] withErrorMessage:&error]) {
252+
result([FlutterError errorWithCode:@"loadFlutterAsset_invalidKey"
253+
message:@"Supplied asset key is not valid."
254+
details:error]);
255+
return;
256+
}
257+
258+
NSString* assetKey = [call arguments];
259+
NSString* assetFilePath = [FlutterDartProject lookupKeyForAsset:assetKey];
260+
NSURL* url = [[NSBundle mainBundle] URLForResource:[assetFilePath stringByDeletingPathExtension]
261+
withExtension:assetFilePath.pathExtension];
262+
263+
if (!url) {
264+
result([FlutterError
265+
errorWithCode:@"loadFlutterAsset_invalidKey"
266+
message:@"Failed parsing file path for supplied key."
267+
details:[NSString
268+
stringWithFormat:@"Failed to convert path '%@' into NSURL for key '%@'.",
269+
assetFilePath, assetKey]]);
270+
return;
271+
}
272+
273+
[_webView loadFileURL:url allowingReadAccessToURL:[url URLByDeletingLastPathComponent]];
274+
result(nil);
275+
}
276+
247277
- (void)onLoadHtmlString:(FlutterMethodCall*)call result:(FlutterResult)result {
248278
NSDictionary* arguments = [call arguments];
249279
if (![arguments isKindOfClass:NSDictionary.class]) {

packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: webview_flutter_wkwebview
22
description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control.
33
repository: https://github.com/flutter/plugins/tree/master/packages/webview_flutter/webview_flutter_wkwebview
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
5-
version: 2.6.0
5+
version: 2.7.0
66

77
environment:
88
sdk: ">=2.14.0 <3.0.0"

0 commit comments

Comments
 (0)