Skip to content

Commit d01f4ea

Browse files
[webview_flutter_android] [webview_flutter_wkwebview] Adds support for PlatformNavigationDelegate.onUrlChange (#3653)
[webview_flutter_android] [webview_flutter_wkwebview] Adds support for `PlatformNavigationDelegate.onUrlChange`
1 parent 6bf2ea8 commit d01f4ea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2326
-1216
lines changed

packages/webview_flutter/webview_flutter_android/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
## NEXT
1+
## 3.5.0
22

3+
* Adds support for `PlatformNavigationDelegate.onUrlChange`.
34
* Bumps androidx.webkit:webkit from 1.6.0 to 1.6.1.
45
* Fixes common typos in tests and documentation.
56

packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java

Lines changed: 360 additions & 623 deletions
Large diffs are not rendered by default.

packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientFlutterApiImpl.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import android.webkit.WebResourceRequest;
1111
import android.webkit.WebView;
1212
import android.webkit.WebViewClient;
13+
import androidx.annotation.NonNull;
1314
import androidx.annotation.RequiresApi;
1415
import androidx.webkit.WebResourceErrorCompat;
1516
import io.flutter.plugin.common.BinaryMessenger;
@@ -202,6 +203,21 @@ public void urlLoading(
202203
urlLoading(getIdentifierForClient(webViewClient), webViewIdentifier, urlArg, callback);
203204
}
204205

206+
/** Passes arguments from {@link WebViewClient#doUpdateVisitedHistory} to Dart. */
207+
public void doUpdateVisitedHistory(
208+
@NonNull WebViewClient webViewClient,
209+
@NonNull WebView webView,
210+
@NonNull String url,
211+
boolean isReload,
212+
@NonNull Reply<Void> callback) {
213+
webViewFlutterApi.create(webView, reply -> {});
214+
215+
final Long webViewIdentifier =
216+
Objects.requireNonNull(instanceManager.getIdentifierForStrongReference(webView));
217+
doUpdateVisitedHistory(
218+
getIdentifierForClient(webViewClient), webViewIdentifier, url, isReload, callback);
219+
}
220+
205221
private long getIdentifierForClient(WebViewClient webViewClient) {
206222
final Long identifier = instanceManager.getIdentifierForStrongReference(webViewClient);
207223
if (identifier == null) {

packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) {
8282
return returnValueForShouldOverrideUrlLoading;
8383
}
8484

85+
@Override
86+
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
87+
flutterApi.doUpdateVisitedHistory(this, view, url, isReload, reply -> {});
88+
}
89+
8590
@Override
8691
public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
8792
// Deliberately empty. Occasionally the webview will mark events as having failed to be
@@ -155,7 +160,12 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) {
155160
}
156161

157162
@Override
158-
public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
163+
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
164+
flutterApi.doUpdateVisitedHistory(this, view, url, isReload, reply -> {});
165+
}
166+
167+
@Override
168+
public void onUnhandledKeyEvent(@NonNull WebView view, @NonNull KeyEvent event) {
159169
// Deliberately empty. Occasionally the webview will mark events as having failed to be
160170
// handled even though they were handled. We don't want to propagate those as they're not
161171
// truly lost.
@@ -175,7 +185,8 @@ public static class WebViewClientCreator {
175185
* @param flutterApi handles sending messages to Dart
176186
* @return the created {@link WebViewClient}
177187
*/
178-
public WebViewClient createWebViewClient(WebViewClientFlutterApiImpl flutterApi) {
188+
@NonNull
189+
public WebViewClient createWebViewClient(@NonNull WebViewClientFlutterApiImpl flutterApi) {
179190
// WebViewClientCompat is used to get
180191
// shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
181192
// invoked by the webview on older Android devices, without it pages that use iframes will

packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import android.webkit.WebResourceRequest;
1616
import android.webkit.WebView;
1717
import android.webkit.WebViewClient;
18+
import androidx.annotation.NonNull;
1819
import io.flutter.plugins.webviewflutter.WebViewClientHostApiImpl.WebViewClientCompatImpl;
1920
import io.flutter.plugins.webviewflutter.WebViewClientHostApiImpl.WebViewClientCreator;
2021
import java.util.HashMap;
@@ -111,8 +112,10 @@ public void setReturnValueForShouldOverrideUrlLoading() {
111112
new WebViewClientHostApiImpl(
112113
instanceManager,
113114
new WebViewClientCreator() {
115+
@NonNull
114116
@Override
115-
public WebViewClient createWebViewClient(WebViewClientFlutterApiImpl flutterApi) {
117+
public WebViewClient createWebViewClient(
118+
@NonNull WebViewClientFlutterApiImpl flutterApi) {
116119
return mockWebViewClient;
117120
}
118121
},
@@ -123,4 +126,12 @@ public WebViewClient createWebViewClient(WebViewClientFlutterApiImpl flutterApi)
123126

124127
verify(mockWebViewClient).setReturnValueForShouldOverrideUrlLoading(false);
125128
}
129+
130+
@Test
131+
public void doUpdateVisitedHistory() {
132+
webViewClient.doUpdateVisitedHistory(mockWebView, "https://www.google.com", true);
133+
verify(mockFlutterApi)
134+
.doUpdateVisitedHistory(
135+
eq(webViewClient), eq(mockWebView), eq("https://www.google.com"), eq(true), any());
136+
}
126137
}

packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,81 @@ Future<void> main() async {
942942
final String? currentUrl = await controller.currentUrl();
943943
expect(currentUrl, secondaryUrl);
944944
});
945+
946+
testWidgets('can receive url changes', (WidgetTester tester) async {
947+
final Completer<void> pageLoaded = Completer<void>();
948+
949+
final PlatformNavigationDelegate navigationDelegate =
950+
PlatformNavigationDelegate(
951+
const PlatformNavigationDelegateCreationParams(),
952+
)..setOnPageFinished((_) => pageLoaded.complete());
953+
954+
final PlatformWebViewController controller = PlatformWebViewController(
955+
const PlatformWebViewControllerCreationParams(),
956+
)
957+
..setJavaScriptMode(JavaScriptMode.unrestricted)
958+
..setPlatformNavigationDelegate(navigationDelegate)
959+
..loadRequest(LoadRequestParams(uri: Uri.parse(blankPageEncoded)));
960+
961+
await tester.pumpWidget(Builder(
962+
builder: (BuildContext context) {
963+
return PlatformWebViewWidget(
964+
PlatformWebViewWidgetCreationParams(controller: controller),
965+
).build(context);
966+
},
967+
));
968+
969+
await pageLoaded.future;
970+
await navigationDelegate.setOnPageFinished((_) {});
971+
972+
final Completer<String> urlChangeCompleter = Completer<String>();
973+
await navigationDelegate.setOnUrlChange((UrlChange change) {
974+
urlChangeCompleter.complete(change.url);
975+
});
976+
977+
await controller.runJavaScript('location.href = "$primaryUrl"');
978+
979+
await expectLater(urlChangeCompleter.future, completion(primaryUrl));
980+
});
981+
982+
testWidgets('can receive updates to history state',
983+
(WidgetTester tester) async {
984+
final Completer<void> pageLoaded = Completer<void>();
985+
986+
final PlatformNavigationDelegate navigationDelegate =
987+
PlatformNavigationDelegate(
988+
const PlatformNavigationDelegateCreationParams(),
989+
)..setOnPageFinished((_) => pageLoaded.complete());
990+
991+
final PlatformWebViewController controller = PlatformWebViewController(
992+
const PlatformWebViewControllerCreationParams(),
993+
)
994+
..setJavaScriptMode(JavaScriptMode.unrestricted)
995+
..setPlatformNavigationDelegate(navigationDelegate)
996+
..loadRequest(LoadRequestParams(uri: Uri.parse(primaryUrl)));
997+
998+
await tester.pumpWidget(Builder(
999+
builder: (BuildContext context) {
1000+
return PlatformWebViewWidget(
1001+
PlatformWebViewWidgetCreationParams(controller: controller),
1002+
).build(context);
1003+
},
1004+
));
1005+
1006+
await pageLoaded.future;
1007+
await navigationDelegate.setOnPageFinished((_) {});
1008+
1009+
final Completer<String> urlChangeCompleter = Completer<String>();
1010+
await navigationDelegate.setOnUrlChange((UrlChange change) {
1011+
urlChangeCompleter.complete(change.url);
1012+
});
1013+
1014+
await controller.runJavaScript(
1015+
'window.history.pushState({}, "", "secondary.txt");',
1016+
);
1017+
1018+
await expectLater(urlChangeCompleter.future, completion(secondaryUrl));
1019+
});
9451020
});
9461021

9471022
testWidgets('target _blank opens in same window',

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ Page resource error:
123123
}
124124
debugPrint('allowing navigation to ${request.url}');
125125
return NavigationDecision.navigate;
126+
})
127+
..setOnUrlChange((UrlChange change) {
128+
debugPrint('url change to ${change.url}');
126129
}),
127130
)
128131
..addJavaScriptChannel(JavaScriptChannelParams(

packages/webview_flutter/webview_flutter_android/example/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ dependencies:
1919
# The example app is bundled with the plugin so we use a path dependency on
2020
# the parent directory to use the current plugin's version.
2121
path: ../
22-
webview_flutter_platform_interface: ^2.0.0
22+
webview_flutter_platform_interface: ^2.1.0
2323

2424
dev_dependencies:
2525
espresso: ^0.2.0

packages/webview_flutter/webview_flutter_android/lib/src/android_proxy.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ class AndroidWebViewProxy {
5858
android_webview.WebResourceRequest request,
5959
)? requestLoading,
6060
void Function(android_webview.WebView webView, String url)? urlLoading,
61+
void Function(android_webview.WebView webView, String url, bool isReload)?
62+
doUpdateVisitedHistory,
6163
}) createAndroidWebViewClient;
6264

6365
/// Constructs a [android_webview.FlutterAssetManager].

packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,7 @@ class WebViewClient extends JavaObject {
677677
@Deprecated('Only called on Android version < 23.') this.onReceivedError,
678678
this.requestLoading,
679679
this.urlLoading,
680+
this.doUpdateVisitedHistory,
680681
@visibleForTesting super.binaryMessenger,
681682
@visibleForTesting super.instanceManager,
682683
}) : super.detached() {
@@ -696,6 +697,7 @@ class WebViewClient extends JavaObject {
696697
@Deprecated('Only called on Android version < 23.') this.onReceivedError,
697698
this.requestLoading,
698699
this.urlLoading,
700+
this.doUpdateVisitedHistory,
699701
super.binaryMessenger,
700702
super.instanceManager,
701703
}) : super.detached();
@@ -840,6 +842,10 @@ class WebViewClient extends JavaObject {
840842
/// indicates whether the [WebView] loaded the URL.
841843
final void Function(WebView webView, String url)? urlLoading;
842844

845+
/// Notify the host application to update its visited links database.
846+
final void Function(WebView webView, String url, bool isReload)?
847+
doUpdateVisitedHistory;
848+
843849
/// Sets the required synchronous return value for the Java method,
844850
/// `WebViewClient.shouldOverrideUrlLoading(...)`.
845851
///
@@ -867,6 +873,7 @@ class WebViewClient extends JavaObject {
867873
onReceivedError: onReceivedError,
868874
requestLoading: requestLoading,
869875
urlLoading: urlLoading,
876+
doUpdateVisitedHistory: doUpdateVisitedHistory,
870877
binaryMessenger: _api.binaryMessenger,
871878
instanceManager: _api.instanceManager,
872879
);

0 commit comments

Comments
 (0)