Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
4 changes: 4 additions & 0 deletions packages/webview_flutter/webview_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 4.1.0

* Adds support to track URL changes. See `NavigationDelegate(onUrlChange)`.

## 4.0.5

* Updates links for the merge of flutter/plugins into flutter/packages.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,32 @@ Future<void> main() async {
final String? currentUrl = await controller.currentUrl();
expect(currentUrl, secondaryUrl);
});

testWidgets('can receive url changes', (WidgetTester tester) async {
final Completer<void> pageLoaded = Completer<void>();

final WebViewController controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(NavigationDelegate(
onPageFinished: (_) => pageLoaded.complete(),
))
..loadRequest(Uri.parse(blankPageEncoded));

await tester.pumpWidget(WebViewWidget(controller: controller));

await pageLoaded.future;

final Completer<String> urlChangeCompleter = Completer<String>();
await controller.setNavigationDelegate(NavigationDelegate(
onUrlChange: (UrlChange change) {
urlChangeCompleter.complete(change.url);
},
));

await controller.runJavaScript('location.href = "$primaryUrl"');

await expectLater(urlChangeCompleter.future, completion(primaryUrl));
});
});

testWidgets('target _blank opens in same window',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ Page resource error:
debugPrint('allowing navigation to ${request.url}');
return NavigationDecision.navigate;
},
onUrlChange: (UrlChange change) {
debugPrint('url change to ${change.url}');
},
),
)
..addJavaScriptChannel(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,12 @@ flutter:
- assets/sample_video.mp4
- assets/www/index.html
- assets/www/styles/style.css

# FOR TESTING ONLY. DO NOT MERGE.
dependency_overrides:
webview_flutter_android:
path: ../../../webview_flutter/webview_flutter_android
webview_flutter_platform_interface:
path: ../../../webview_flutter/webview_flutter_platform_interface
webview_flutter_wkwebview:
path: ../../../webview_flutter/webview_flutter_wkwebview
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,7 @@ class FakeNavigationDelegate extends PlatformNavigationDelegate {
Future<void> setOnWebResourceError(
WebResourceErrorCallback onWebResourceError,
) async {}

@override
Future<void> setOnUrlChange(UrlChangeCallback onUrlChange) async {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,18 @@ import 'webview_controller.dart';
/// ```
class NavigationDelegate {
/// Constructs a [NavigationDelegate].
///
/// {@template webview_fluttter.navigation_delegate}
/// `onUrlChange`: invoked when the underlying web view changes to a new url.
/// {@endtemplate}
NavigationDelegate({
FutureOr<NavigationDecision> Function(NavigationRequest request)?
onNavigationRequest,
void Function(String url)? onPageStarted,
void Function(String url)? onPageFinished,
void Function(int progress)? onProgress,
void Function(WebResourceError error)? onWebResourceError,
void Function(UrlChange change)? onUrlChange,
}) : this.fromPlatformCreationParams(
const PlatformNavigationDelegateCreationParams(),
onNavigationRequest: onNavigationRequest,
Expand Down Expand Up @@ -81,6 +86,8 @@ class NavigationDelegate {
/// );
/// ```
/// {@endtemplate}
///
/// {@macro webview_fluttter.navigation_delegate}
NavigationDelegate.fromPlatformCreationParams(
PlatformNavigationDelegateCreationParams params, {
FutureOr<NavigationDecision> Function(NavigationRequest request)?
Expand All @@ -89,23 +96,28 @@ class NavigationDelegate {
void Function(String url)? onPageFinished,
void Function(int progress)? onProgress,
void Function(WebResourceError error)? onWebResourceError,
void Function(UrlChange change)? onUrlChange,
}) : this.fromPlatform(
PlatformNavigationDelegate(params),
onNavigationRequest: onNavigationRequest,
onPageStarted: onPageStarted,
onPageFinished: onPageFinished,
onProgress: onProgress,
onWebResourceError: onWebResourceError,
onUrlChange: onUrlChange,
);

/// Constructs a [NavigationDelegate] from a specific platform implementation.
///
/// {@macro webview_fluttter.navigation_delegate}
NavigationDelegate.fromPlatform(
this.platform, {
this.onNavigationRequest,
this.onPageStarted,
this.onPageFinished,
this.onProgress,
this.onWebResourceError,
void Function(UrlChange change)? onUrlChange,
}) {
if (onNavigationRequest != null) {
platform.setOnNavigationRequest(onNavigationRequest!);
Expand All @@ -122,6 +134,9 @@ class NavigationDelegate {
if (onWebResourceError != null) {
platform.setOnWebResourceError(onWebResourceError!);
}
if (onUrlChange != null) {
platform.setOnUrlChange(onUrlChange);
}
}

/// Implementation of [PlatformNavigationDelegate] for the current platform.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export 'package:webview_flutter_platform_interface/webview_flutter_platform_inte
PlatformWebViewCookieManagerCreationParams,
PlatformWebViewWidgetCreationParams,
ProgressCallback,
UrlChange,
WebResourceError,
WebResourceErrorCallback,
WebResourceErrorType,
Expand Down
11 changes: 10 additions & 1 deletion 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/packages/tree/main/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: 4.0.5
version: 4.1.0

environment:
sdk: ">=2.17.0 <3.0.0"
Expand Down Expand Up @@ -31,3 +31,12 @@ dev_dependencies:
sdk: flutter
mockito: ^5.3.2
plugin_platform_interface: ^2.1.3

# FOR TESTING ONLY. DO NOT MERGE.
dependency_overrides:
webview_flutter_android:
path: ../../webview_flutter/webview_flutter_android
webview_flutter_platform_interface:
path: ../../webview_flutter/webview_flutter_platform_interface
webview_flutter_wkwebview:
path: ../../webview_flutter/webview_flutter_wkwebview
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@ void main() {

verify(delegate.platform.setOnWebResourceError(onWebResourceError));
});

test('onUrlChange', () async {
WebViewPlatform.instance = TestWebViewPlatform();

void onUrlChange(UrlChange change) {}

final NavigationDelegate delegate = NavigationDelegate(
onUrlChange: onUrlChange,
);

verify(delegate.platform.setOnUrlChange(onUrlChange));
});
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,4 +228,14 @@ class MockPlatformNavigationDelegate extends _i1.Mock
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),
) as _i8.Future<void>);
@override
_i8.Future<void> setOnUrlChange(_i3.UrlChangeCallback? onUrlChange) =>
(super.noSuchMethod(
Invocation.method(
#setOnUrlChange,
[onUrlChange],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),
) as _i8.Future<void>);
}
Original file line number Diff line number Diff line change
Expand Up @@ -414,4 +414,14 @@ class MockPlatformNavigationDelegate extends _i1.Mock
returnValue: _i5.Future<void>.value(),
returnValueForMissingStub: _i5.Future<void>.value(),
) as _i5.Future<void>);
@override
_i5.Future<void> setOnUrlChange(_i6.UrlChangeCallback? onUrlChange) =>
(super.noSuchMethod(
Invocation.method(
#setOnUrlChange,
[onUrlChange],
),
returnValue: _i5.Future<void>.value(),
returnValueForMissingStub: _i5.Future<void>.value(),
) as _i5.Future<void>);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ void main() {
main_file.WebViewCookie;
// ignore: unnecessary_statements
main_file.WebResourceErrorType;
// ignore: unnecessary_statements
main_file.UrlChange;
});
});
}
4 changes: 4 additions & 0 deletions packages/webview_flutter/webview_flutter_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.4.0

* Adds support for `PlatformNavigationDelegate.onUrlChange`.

## 3.3.1

* Updates links for the merge of flutter/plugins into flutter/packages.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2352,6 +2352,25 @@ public void urlLoading(
callback.reply(null);
});
}

public void doUpdateVisitedHistory(
@NonNull Long instanceIdArg,
@NonNull Long webViewInstanceIdArg,
@NonNull String urlArg,
@NonNull Boolean isReloadArg,
Reply<Void> callback) {
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.WebViewClientFlutterApi.doUpdateVisitedHistory",
getCodec());
channel.send(
new ArrayList<Object>(
Arrays.asList(instanceIdArg, webViewInstanceIdArg, urlArg, isReloadArg)),
channelReply -> {
callback.reply(null);
});
}
}
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
public interface DownloadListenerHostApi {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) {
return returnValueForShouldOverrideUrlLoading;
}

@Override
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
flutterApi.doUpdateVisitedHistory(this, view, url, isReload, reply -> {});
}

@Override
public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
// Deliberately empty. Occasionally the webview will mark events as having failed to be
Expand Down Expand Up @@ -146,6 +151,11 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) {
return returnValueForShouldOverrideUrlLoading;
}

@Override
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
flutterApi.doUpdateVisitedHistory(this, view, url, isReload, reply -> {});
}

@Override
public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
// Deliberately empty. Occasionally the webview will mark events as having failed to be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,12 @@ public WebViewClient createWebViewClient(WebViewClientFlutterApiImpl flutterApi)

verify(mockWebViewClient).setReturnValueForShouldOverrideUrlLoading(false);
}

@Test
public void doUpdateVisitedHistory() {
webViewClient.doUpdateVisitedHistory(mockWebView, "https://www.google.com", true);
verify(mockFlutterApi)
.doUpdateVisitedHistory(
eq(webViewClient), eq(mockWebView), eq("https://www.google.com"), eq(true), any());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,42 @@ Future<void> main() async {
final String? currentUrl = await controller.currentUrl();
expect(currentUrl, secondaryUrl);
});

testWidgets('can receive url changes', (WidgetTester tester) async {
final Completer<void> pageLoaded = Completer<void>();

final PlatformNavigationDelegate navigationDelegate =
PlatformNavigationDelegate(
const PlatformNavigationDelegateCreationParams(),
)..setOnPageFinished((_) => pageLoaded.complete());

final PlatformWebViewController controller = PlatformWebViewController(
const PlatformWebViewControllerCreationParams(),
)
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setPlatformNavigationDelegate(navigationDelegate)
..loadRequest(LoadRequestParams(uri: Uri.parse(blankPageEncoded)));

await tester.pumpWidget(Builder(
builder: (BuildContext context) {
return PlatformWebViewWidget(
PlatformWebViewWidgetCreationParams(controller: controller),
).build(context);
},
));

await pageLoaded.future;
await navigationDelegate.setOnPageFinished((_) {});

final Completer<String> urlChangeCompleter = Completer<String>();
await navigationDelegate.setOnUrlChange((UrlChange change) {
urlChangeCompleter.complete(change.url);
});

await controller.runJavaScript('location.href = "$primaryUrl"');

await expectLater(urlChangeCompleter.future, completion(primaryUrl));
});
});

testWidgets('target _blank opens in same window',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ Page resource error:
}
debugPrint('allowing navigation to ${request.url}');
return NavigationDecision.navigate;
})
..setOnUrlChange((UrlChange change) {
debugPrint('url change to ${change.url}');
}),
)
..addJavaScriptChannel(JavaScriptChannelParams(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,11 @@ flutter:
- assets/sample_video.mp4
- assets/www/index.html
- assets/www/styles/style.css


# FOR TESTING ONLY. DO NOT MERGE.
dependency_overrides:
webview_flutter_android:
path: ../../../webview_flutter/webview_flutter_android
webview_flutter_platform_interface:
path: ../../../webview_flutter/webview_flutter_platform_interface
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class AndroidWebViewProxy {
)?
requestLoading,
void Function(android_webview.WebView webView, String url)? urlLoading,
void Function(android_webview.WebView webView, String url, bool isReload)?
doUpdateVisitedHistory,
}) createAndroidWebViewClient;

/// Constructs a [android_webview.FlutterAssetManager].
Expand Down
Loading