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

Commit eaab52e

Browse files
committed
Fixes bug when onNavigationRequestCallback returns false
1 parent 0b29924 commit eaab52e

File tree

5 files changed

+231
-5
lines changed

5 files changed

+231
-5
lines changed

packages/webview_flutter/webview_flutter_android/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.8.13
2+
3+
* Fixes a bug which causes an exception when the `onNavigationRequestCallback` return `false`.
4+
15
## 2.8.12
26

37
* Bumps mockito-inline from 3.11.1 to 4.6.1.

packages/webview_flutter/webview_flutter_android/lib/webview_android_widget.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -652,8 +652,8 @@ class WebViewAndroidWebViewClient extends android_webview.WebViewClient {
652652

653653
if (returnValue is bool && returnValue) {
654654
loadUrl!(url, <String, String>{});
655-
} else {
656-
(returnValue as Future<bool>).then((bool shouldLoadUrl) {
655+
} else if (returnValue is Future<bool>) {
656+
returnValue.then((bool shouldLoadUrl) {
657657
if (shouldLoadUrl) {
658658
loadUrl!(url, <String, String>{});
659659
}
@@ -677,8 +677,8 @@ class WebViewAndroidWebViewClient extends android_webview.WebViewClient {
677677

678678
if (returnValue is bool && returnValue) {
679679
loadUrl!(request.url, <String, String>{});
680-
} else {
681-
(returnValue as Future<bool>).then((bool shouldLoadUrl) {
680+
} else if (returnValue is Future<bool>) {
681+
returnValue.then((bool shouldLoadUrl) {
682682
if (shouldLoadUrl) {
683683
loadUrl!(request.url, <String, String>{});
684684
}

packages/webview_flutter/webview_flutter_android/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: webview_flutter_android
22
description: A Flutter plugin that provides a WebView widget on Android.
33
repository: https://github.com/flutter/plugins/tree/main/packages/webview_flutter/webview_flutter_android
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
5-
version: 2.8.12
5+
version: 2.8.13
66

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

packages/webview_flutter/webview_flutter_android/test/webview_android_widget_test.dart

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'dart:async';
56
import 'dart:typed_data';
67

78
import 'package:flutter/widgets.dart';
@@ -24,6 +25,7 @@ import 'webview_android_widget_test.mocks.dart';
2425
android_webview.WebSettings,
2526
android_webview.WebStorage,
2627
android_webview.WebView,
28+
android_webview.WebResourceRequest,
2729
WebViewAndroidDownloadListener,
2830
WebViewAndroidJavaScriptChannel,
2931
WebViewAndroidWebChromeClient,
@@ -843,4 +845,194 @@ void main() {
843845
verify(mockPlatformHostApi.setWebContentsDebuggingEnabled(false));
844846
});
845847
});
848+
849+
group('WebViewAndroidWebViewClient', () {
850+
test(
851+
'urlLoading should call loadUrl when onNavigationRequestCallback returns true',
852+
() {
853+
final Completer<void> completer = Completer<void>();
854+
final WebViewAndroidWebViewClient webViewClient =
855+
WebViewAndroidWebViewClient.handlesNavigation(
856+
onPageStartedCallback: (_) {},
857+
onPageFinishedCallback: (_) {},
858+
onWebResourceErrorCallback: (_) {},
859+
onNavigationRequestCallback: ({
860+
required bool isForMainFrame,
861+
required String url,
862+
}) =>
863+
true,
864+
loadUrl: (String url, Map<String, String>? headers) async {
865+
completer.complete();
866+
});
867+
868+
webViewClient.urlLoading(MockWebView(), 'https://flutter.dev');
869+
expect(completer.isCompleted, isTrue);
870+
});
871+
872+
test(
873+
'urlLoading should call loadUrl when onNavigationRequestCallback returns a Future true',
874+
() async {
875+
final Completer<void> completer = Completer<void>();
876+
final WebViewAndroidWebViewClient webViewClient =
877+
WebViewAndroidWebViewClient.handlesNavigation(
878+
onPageStartedCallback: (_) {},
879+
onPageFinishedCallback: (_) {},
880+
onWebResourceErrorCallback: (_) {},
881+
onNavigationRequestCallback: ({
882+
required bool isForMainFrame,
883+
required String url,
884+
}) =>
885+
Future<bool>.value(true),
886+
loadUrl: (String url, Map<String, String>? headers) async {
887+
completer.complete();
888+
});
889+
890+
webViewClient.urlLoading(MockWebView(), 'https://flutter.dev');
891+
await completer.future;
892+
expect(completer.isCompleted, isTrue);
893+
});
894+
895+
test(
896+
'urlLoading should not call laodUrl when onNavigationRequestCallback returns false',
897+
() async {
898+
final WebViewAndroidWebViewClient webViewClient =
899+
WebViewAndroidWebViewClient.handlesNavigation(
900+
onPageStartedCallback: (_) {},
901+
onPageFinishedCallback: (_) {},
902+
onWebResourceErrorCallback: (_) {},
903+
onNavigationRequestCallback: ({
904+
required bool isForMainFrame,
905+
required String url,
906+
}) =>
907+
false,
908+
loadUrl: (String url, Map<String, String>? headers) async {
909+
fail(
910+
'loadUrl should not be called if onNavigationRequestCallback returns false.');
911+
});
912+
913+
webViewClient.urlLoading(MockWebView(), 'https://flutter.dev');
914+
});
915+
916+
test(
917+
'urlLoading should not call loadUrl when onNavigationRequestCallback returns a Future false',
918+
() {
919+
final WebViewAndroidWebViewClient webViewClient =
920+
WebViewAndroidWebViewClient.handlesNavigation(
921+
onPageStartedCallback: (_) {},
922+
onPageFinishedCallback: (_) {},
923+
onWebResourceErrorCallback: (_) {},
924+
onNavigationRequestCallback: ({
925+
required bool isForMainFrame,
926+
required String url,
927+
}) =>
928+
Future<bool>.value(false),
929+
loadUrl: (String url, Map<String, String>? headers) async {
930+
fail(
931+
'loadUrl should not be called if onNavigationRequestCallback returns false.');
932+
});
933+
934+
webViewClient.urlLoading(MockWebView(), 'https://flutter.dev');
935+
});
936+
937+
test(
938+
'requestLoading should call loadUrl when onNavigationRequestCallback returns true',
939+
() {
940+
final Completer<void> completer = Completer<void>();
941+
final MockWebResourceRequest mockRequest = MockWebResourceRequest();
942+
when(mockRequest.isForMainFrame).thenReturn(true);
943+
when(mockRequest.url).thenReturn('https://flutter.dev');
944+
final WebViewAndroidWebViewClient webViewClient =
945+
WebViewAndroidWebViewClient.handlesNavigation(
946+
onPageStartedCallback: (_) {},
947+
onPageFinishedCallback: (_) {},
948+
onWebResourceErrorCallback: (_) {},
949+
onNavigationRequestCallback: ({
950+
required bool isForMainFrame,
951+
required String url,
952+
}) =>
953+
true,
954+
loadUrl: (String url, Map<String, String>? headers) async {
955+
expect(url, 'https://flutter.dev');
956+
completer.complete();
957+
});
958+
959+
webViewClient.requestLoading(MockWebView(), mockRequest);
960+
expect(completer.isCompleted, isTrue);
961+
});
962+
963+
test(
964+
'requestLoading should call loadUrl when onNavigationRequestCallback returns a Future true',
965+
() async {
966+
final Completer<void> completer = Completer<void>();
967+
final MockWebResourceRequest mockRequest = MockWebResourceRequest();
968+
when(mockRequest.isForMainFrame).thenReturn(true);
969+
when(mockRequest.url).thenReturn('https://flutter.dev');
970+
final WebViewAndroidWebViewClient webViewClient =
971+
WebViewAndroidWebViewClient.handlesNavigation(
972+
onPageStartedCallback: (_) {},
973+
onPageFinishedCallback: (_) {},
974+
onWebResourceErrorCallback: (_) {},
975+
onNavigationRequestCallback: ({
976+
required bool isForMainFrame,
977+
required String url,
978+
}) =>
979+
Future<bool>.value(true),
980+
loadUrl: (String url, Map<String, String>? headers) async {
981+
expect(url, 'https://flutter.dev');
982+
completer.complete();
983+
});
984+
985+
webViewClient.requestLoading(MockWebView(), mockRequest);
986+
await completer.future;
987+
expect(completer.isCompleted, isTrue);
988+
});
989+
990+
test(
991+
'requestLoading should not call onLoadUrlCallback when onNavigationRequestCallback returns false',
992+
() {
993+
final MockWebResourceRequest mockRequest = MockWebResourceRequest();
994+
when(mockRequest.isForMainFrame).thenReturn(true);
995+
when(mockRequest.url).thenReturn('https://flutter.dev');
996+
final WebViewAndroidWebViewClient webViewClient =
997+
WebViewAndroidWebViewClient.handlesNavigation(
998+
onPageStartedCallback: (_) {},
999+
onPageFinishedCallback: (_) {},
1000+
onWebResourceErrorCallback: (_) {},
1001+
onNavigationRequestCallback: ({
1002+
required bool isForMainFrame,
1003+
required String url,
1004+
}) =>
1005+
false,
1006+
loadUrl: (String url, Map<String, String>? headers) {
1007+
fail(
1008+
'loadUrl should not be called if onNavigationRequestCallback returns false.');
1009+
});
1010+
1011+
webViewClient.requestLoading(MockWebView(), mockRequest);
1012+
});
1013+
1014+
test(
1015+
'requestLoading should not call onLoadUrlCallback when onNavigationRequestCallback returns a Future false',
1016+
() {
1017+
final MockWebResourceRequest mockRequest = MockWebResourceRequest();
1018+
when(mockRequest.isForMainFrame).thenReturn(true);
1019+
when(mockRequest.url).thenReturn('https://flutter.dev');
1020+
final WebViewAndroidWebViewClient webViewClient =
1021+
WebViewAndroidWebViewClient.handlesNavigation(
1022+
onPageStartedCallback: (_) {},
1023+
onPageFinishedCallback: (_) {},
1024+
onWebResourceErrorCallback: (_) {},
1025+
onNavigationRequestCallback: ({
1026+
required bool isForMainFrame,
1027+
required String url,
1028+
}) =>
1029+
Future<bool>.value(false),
1030+
loadUrl: (String url, Map<String, String>? headers) {
1031+
fail(
1032+
'loadUrl should not be called if onNavigationRequestCallback returns false.');
1033+
});
1034+
1035+
webViewClient.requestLoading(MockWebView(), mockRequest);
1036+
});
1037+
});
8461038
}

packages/webview_flutter/webview_flutter_android/test/webview_android_widget_test.mocks.dart

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,36 @@ class MockWebView extends _i1.Mock implements _i2.WebView {
286286
returnValueForMissingStub: Future<void>.value()) as _i4.Future<void>);
287287
}
288288

289+
/// A class which mocks [WebResourceRequest].
290+
///
291+
/// See the documentation for Mockito's code generation for more information.
292+
class MockWebResourceRequest extends _i1.Mock
293+
implements _i2.WebResourceRequest {
294+
MockWebResourceRequest() {
295+
_i1.throwOnMissingStub(this);
296+
}
297+
298+
@override
299+
String get url =>
300+
(super.noSuchMethod(Invocation.getter(#url), returnValue: '') as String);
301+
@override
302+
bool get isForMainFrame => (super
303+
.noSuchMethod(Invocation.getter(#isForMainFrame), returnValue: false)
304+
as bool);
305+
@override
306+
bool get hasGesture =>
307+
(super.noSuchMethod(Invocation.getter(#hasGesture), returnValue: false)
308+
as bool);
309+
@override
310+
String get method =>
311+
(super.noSuchMethod(Invocation.getter(#method), returnValue: '')
312+
as String);
313+
@override
314+
Map<String, String> get requestHeaders =>
315+
(super.noSuchMethod(Invocation.getter(#requestHeaders),
316+
returnValue: <String, String>{}) as Map<String, String>);
317+
}
318+
289319
/// A class which mocks [WebViewAndroidDownloadListener].
290320
///
291321
/// See the documentation for Mockito's code generation for more information.

0 commit comments

Comments
 (0)