Skip to content

feat(windows): add DevTools, accelerator key and download settings - #44

Merged
moluopro merged 17 commits into
abandoft:mainfrom
Spoki4:feat/windows-kiosk-settings
Sep 25, 2026
Merged

moluopro merged 17 commits into
abandoft:mainfrom
Spoki4:feat/windows-kiosk-settings

Conversation

@Spoki4

@Spoki4 Spoki4 commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Problem

WebView2 turns on DevTools, browser accelerator keys and downloads by default, and WindowsWebViewController has no way to turn any of them off:

  • F12 and Ctrl+Shift+I always open DevTools, whatever the app wants.
  • F5, Ctrl+P, Ctrl+F and the other browser shortcuts always go to WebView2, not to the app.
  • A page can always save files to the user's Downloads folder. DownloadStarting is marked handled and the download goes ahead, with no way to refuse it from Dart.

That is fine for a general-purpose browser view, but it blocks apps that show content they do not fully control: kiosks, embedded help, previews of user-supplied HTML. On iOS/macOS the same need is already covered by WebKitWebViewController.setInspectable.

Fix

Three methods on WindowsWebViewController, each backed by a WebView2 setting:

API WebView2
setInspectable(bool) ICoreWebView2Settings::put_AreDevToolsEnabled — named after WebKitWebViewController.setInspectable
setBrowserAcceleratorKeysEnabled(bool) ICoreWebView2Settings3::put_AreBrowserAcceleratorKeysEnabled
setDownloadsEnabled(bool) DownloadStarting → put_Cancel(TRUE) before a download operation exists, so nothing is written and no download event is sent
final windows = controller.platform as WindowsWebViewController;
await windows.setInspectable(false);
await windows.setBrowserAcceleratorKeysEnabled(false);
await windows.setDownloadsEnabled(false);

Defaults are unchanged. Each method goes through the existing Pigeon host API (setZoomControlEnabled served as the template), and the channels are normalized with tool/normalize_pigeon_namespaces.py.

The controller keeps the requested values and applies them again when a failed initialization is retried (the widget's Refresh), because the new WebView2 starts from the WebView2 defaults. A small private _WebView2Setting also records what the current native WebView already has, so a value is sent once even when the setter and the initialization race.

setBrowserAcceleratorKeysEnabled needs ICoreWebView2Settings3. On a runtime without it the call throws a PlatformException (not_supported) rather than failing silently.

Tests

  • webview_all_windows: unit tests for all three settings forwarding to the host API, and for their re-application after a failed-then-refreshed initialization.
  • examples/platform: an integration test with a real WebView2. It starts one download with downloads allowed, as a control, then the same download with downloads disabled, and checks the user's Downloads folder. Without the control, a page that never started a download would pass too. The test removes both files.
  • The integration test catches the bug. With SetDownloadsEnabled patched to ignore its argument, it fails with "A download started while downloads were disabled."

Verification

Windows 11 Pro 25H2 (26200), WebView2 Runtime 153.0, Flutter 3.47.0, VS 2022 Build Tools 17.14:

  • flutter build windows --debug in examples/platform builds with no warnings.
  • flutter test integration_test/webview_flutter_test.dart -d windows: All tests passed! (29 passed, 3 skipped), new test included.
  • flutter test in webview_all_windows: 53 tests pass.
  • flutter analyze --fatal-infos in webview_all_windows and examples/platform: No issues found!
  • dart format --set-exit-if-changed on the changed files is clean, and tool/normalize_pigeon_namespaces.py --check all passes.

Docs: platforms/windows.md (EN/ZH) controller API table and the Windows section of guides/debugging.md. I did not touch CHANGELOG.md, since release notes come with the release.

Spoki4 and others added 17 commits September 25, 2026 15:32
WebView2 enables DevTools, browser accelerator keys and downloads by
default, and WindowsWebViewController had no way to turn any of them off:
F12 always opened DevTools and a page could always save files to the
user's Downloads folder.

Add three controller methods, each backed by a WebView2 setting:

- setInspectable(bool): ICoreWebView2Settings::AreDevToolsEnabled; named
  after WebKitWebViewController.setInspectable.
- setBrowserAcceleratorKeysEnabled(bool):
  ICoreWebView2Settings3::AreBrowserAcceleratorKeysEnabled.
- setDownloadsEnabled(bool): cancels DownloadStarting before a download
  operation exists, so nothing is written and no download event is sent.

Defaults are unchanged. The requested values are kept by the controller
and re-applied when a failed initialization is retried, because the
retried WebView2 starts from the WebView2 defaults again.
Start one download with downloads allowed as a control, then the same
download with downloads disabled, and check the user's Downloads folder.
Without the control, a page that never started a download would pass too.
@moluopro

Copy link
Copy Markdown
Collaborator

Thanks!

@moluopro
moluopro merged commit a6af5c9 into abandoft:main Sep 25, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants