Sitelet https://github.com/flutter/packages/pull/12312
Skip to content

[webview_flutter] Adds NavigationDelegate.onCreateWindow for target=_blank / window.open - #12312

Draft
mateusz-ramp wants to merge 4 commits into
flutter:mainfrom
mateusz-ramp:webview-target-blank
Draft

mateusz-ramp wants to merge 4 commits into
flutter:mainfrom
mateusz-ramp:webview-target-blank

Conversation

@mateusz-ramp

@mateusz-ramp mateusz-ramp commented Jul 29, 2026 •

Copy link
Copy Markdown

Adds an optional NavigationDelegate.onCreateWindow callback so hosts can
handle target=_blank / window.open (e.g. open in an external browser)
instead of only loading in the same WebView.

Behavior

  • If onCreateWindow is set: Android (WebChromeClient.onCreateWindow →
    pigeon) and iOS/macOS (WKUIDelegate.createWebViewWith) invoke the callback
    with the requested URL.
  • If unset: preserves existing same-WebView load behavior.

Packages (federated review PR)

  • webview_flutter_platform_interface 2.16.0
  • webview_flutter_android 4.14.0
  • webview_flutter_wkwebview 3.27.0
  • webview_flutter 4.15.0

Path dependency_overrides are present for combined review only
(make-deps-path-based). This PR is not intended to land as-is; after
approval we will land/publish in the usual federated order (platform
interface → implementations → app-facing).

Related issues

Related to:

Background (prior same-window _blank handling):

Pre-Review Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools.
  • I read the [Tree Hygiene] page, which explains my responsibilities.
  • I read and followed the [relevant style guides] and ran [the auto-formatter].
  • I signed the [CLA].
  • The title of the PR starts with the name of the package surrounded by square brackets, e.g. [shared_preferences]
  • I [linked to at least one issue that this PR fixes] in the description above.
  • I followed [the version and CHANGELOG instructions], using [semantic versioning] and the [repository CHANGELOG style], or I have commented below to indicate which documented exception this PR falls under1.
  • I updated/added any relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or I have commented below to indicate which [test exemption] this PR falls under1.
  • All existing and new tests are passing.

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2

@google-cla

google-cla Bot commented Jul 29, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds the NavigationDelegate.onCreateWindow callback to the webview_flutter packages to support handling new-window requests, such as target=_blank and window.open, on Android and iOS. The implementation spans the platform interface, Android, and iOS implementations, alongside corresponding tests and version bumps. Feedback on the iOS implementation recommends avoiding an asynchronous IPC call to retrieve the URL when onCreateWindow is not set, and ensuring that empty or null URLs fall back to the default loading behavior instead of being silently dropped.

@mateusz-ramp

mateusz-ramp commented Aug 10, 2026 •

Copy link
Copy Markdown
Author

@bparrishMines hello, this is my first contribution to Flutter Packages repo, I'm not sure how things work here. Seems like cicd label needs to be added for the PR to move forward, and I can't do that myself. Could you help me with that?

@mateusz-ramp
mateusz-ramp force-pushed the webview-target-blank branch 4 times, most recently from a0e3e1d to 05fd8ad Compare August 26, 2026 14:14
@mateusz-ramp
mateusz-ramp force-pushed the webview-target-blank branch 2 times, most recently from 9c33f76 to c5ff038 Compare September 2, 2026 12:36

@bparrishMines bparrishMines left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution!

As mentioned in #12236 (comment), I think the workarounds to deal with the synchronous callbacks is not something we want to add while we plan to transition to bringing ffi/jni support to pigeon. They add a nontrivial amount of complexity to the plugin that we would have to maintain.

Feel free to set this to draft and we can revisit adding this feature once flutter/flutter#190148 has been finished.

if (webViewClient instanceof WebViewClientProxyApi.WebViewClientImpl) {
((WebViewClientProxyApi.WebViewClientImpl) webViewClient).notifyCreateWindow(url);
} else if (!webViewClient.shouldOverrideUrlLoading(view, request)) {
view.loadurl(/sitelet?url=https%3A%2F%2Fgithub.com%2Fflutter%2Fpackages%2Fpull%2Furl);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm concerned that this would be a breaking change for users. It looks like for the iOS implementation, if the setOnCreateWindow is not set, then the plugin will continue to do what is does now. This changes Android to call notifyCreateWindow by default. This potentially needs a check that notifyCreateWindow was even set to ensure this behavior is opt in. The WebViewClient would probably need another setter that set whether notifyCreateWindow should be handled.

// Only pay the pigeon IPC cost for getUrl when the host opted in.
final String? url = await navigationAction.request.geturl();
if (url != null && url.isNotEmpty) {
onCreateWindow(url);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WKUIDelegate.onCreateWebView requires returning a synchronous WebView because WebKit loads the request in the returned web view. according to the documentation. This seems like a workaround where the url is passed to the user. Does this behave properly when tested?

@mateusz-ramp
mateusz-ramp marked this pull request as draft September 8, 2026 06:59
…ateWindow.

# Conflicts:
#	packages/webview_flutter/webview_flutter_android/CHANGELOG.md

# Conflicts:
#	packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md
#	packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants