Skip to content

feat: preload script URL filters (#54903) - #55182

Merged
jkleinsc merged 2 commits into
44-x-yfrom
manual-bp/44-x-y/54903
Oct 22, 2026
Merged

jkleinsc merged 2 commits into
44-x-yfrom
manual-bp/44-x-y/54903

Conversation

@samuelmaddock

Copy link
Copy Markdown
Member

Backport of #54903

See that PR for details.

Manual backport notes:

  • Resolved include and declaration conflicts in electron_api_web_contents.{h,cc} (and renderer_startup_data.cc on 44-x-y).
  • WebContents::GetPreloadScript() still exists on this branch (removed on main in chore: remove dead code, unused chromium_src sources and orphaned files #54229) and brace-initialized PreloadScript, which is no longer an aggregate. It now default-constructs and assigns the fields.

Notes: Added filtering options to session.registerPreloadScript - matches, excludeMatches, includeGlobs, excludeGlobs, matchOriginAsFallback.

* feat: preload script URL filters

* feat: reject an empty preload script matches array

An explicit `matches: []` meant "every URL", the same ambiguity webRequest
filters dropped in favor of `<all_urls>`. Registering one now throws and
points at `<all_urls>`; omitting `matches` still matches every URL, so
existing registrations are unaffected.

Also adds coverage that `<all_urls>` matches both an http page and
about:blank.

* docs: link preload URL filters to MDN match patterns

Matches the webRequest filter docs, which already link to MDN.

* test: extension protocol

* feat: add matchOriginAsFallback to preload script URL filters

A document whose URL has no origin of its own (about:, blob:, data:,
filesystem:) was only matched by its literal URL, so an about:blank popup
escaped its opener's excludeMatches and excludeGlobs.

With matchOriginAsFallback, frame preloads match such documents by the
origin they inherited from their creator, like match_origin_as_fallback
for content scripts.

* fix: reject an empty preload script includeGlobs array

An explicitly empty includeGlobs array converted to the same state as an
omitted one, so the preload ran for every URL instead of none. Reject it
at registration, as an empty matches array already is.

* test: use vitest assertions in preload URL filter specs

main dropped chai in #54439, so the chai-style assertions these specs
added no longer match the rest of the suite, and the dirty-chai call
forms (to.be.empty(), to.be.false()) are no longer available.

* fix: address review feedback on preload script URL filters

- Match a data: URL loaded with baseURLForDataURL by its base URL, which
  is the URL the document commits at.
- Never match when URL patterns were not parsed, instead of matching
  every URL.
- Explain a scheme separator mismatch in the invalid pattern error.
- Document custom scheme requirements, error page matching and opaque
  origins with matchOriginAsFallback.
- Add specs for baseURLForDataURL, subframes and redirects.

* docs: list preload script URL filter conditions

Break the URL filter description for ses.registerPreloadScript into
bullet lists, and note that in-page navigations do not rerun the
preload script.

Co-Authored-By: Claude <[email protected]>
@trop trop Bot added 44-x-y backport This is a backport PR backport/requested 🗳 semver/minor backwards-compatible functionality labels Oct 21, 2026
@trop trop Bot mentioned this pull request Oct 21, 2026
7 tasks done

@jkleinsc jkleinsc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One small nit on documentation (same as #55181). Whatever followup is done here should also be added to main via a followup PR.

other filters. Must not be empty.
* `excludeMatches` string[] (optional) - Match patterns for URLs the script will not run in.
* `includeGlobs` string[] (optional) - Glob patterns applied after `matches`. A URL must
also match one of these globs. `*` matches any sequence of characters and `?` matches

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same comment as #55181:
? globs match zero characters despite the documented single-character contract — preload_script.cc:69

The new API documentation says ? matches exactly one character, but base::MatchPattern matches zero or one characters. Chromium explicitly tests the empty-string case in pattern_unittest.cc:22.

For example, includeGlobs: ['https://example.com/item?'] also admits https://example.com/item, unexpectedly running the preload outside the documented filter. The same discrepancy affects exclusions.

Align the implementation and documentation, and add coverage for zero-, one-, and two-character matches. If retaining Chromium’s existing glob semantics is intentional, document the optional-character behavior explicitly.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thank you for pointing this out @jkleinsc! I would like to match the base::MatchPattern behavior so I've updated the docs to reflect that, while adding a new test to verify.

I've added a commit here and opened #55209 for targeting main.

The URL filter docs said `?` matches any single character, but globs are
matched with base::MatchPattern, where `?` is optional. Correct the docs
and add a spec for the behavior.

Co-Authored-By: Claude <[email protected]>

@claude claude 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.

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Additional findings (outside the current diff — GitHub can't attach inline comments there):

  • 🟡 docs/api/session.md — nit: Readers of the API history for ses.registerPreloadScript will not see that it gained the matches, excludeMatches, includeGlobs, excludeGlobs and matchOriginAsFallback options. The diff adds these options but adds no YAML API history block under the #### ses.registerPreloadScript(script) header. Fix: add a history block right after that header with a changes entry whose pr-url is the main-branch PR (#54903) and whose quoted description names the new URL filter options.

    Why this was flagged

    The diff gives ses.registerPreloadScript(script) five new optional fields: matches, excludeMatches, includeGlobs, excludeGlobs and matchOriginAsFallback (docs/api/session.md:1528-1568, preload-script-registration.md:7-24). It adds no YAML history block under that header, although other entries in the same file have changes blocks (docs/api/session.md:95-98, 164-167, 241-244). The repository's REVIEW.md and docs/CLAUDE.md both ask for a changes history entry, with a quoted description and the main-branch PR URL, whenever an API changes. As a result, the generated API history shows no record that these options were added or when.

    Verification: The diff adds matches, excludeMatches, includeGlobs, excludeGlobs and matchOriginAsFallback, with new description text in docs/api/session.md:1534-1567. But the header at docs/api/session.md:1528 is still followed directly by the parameter line at 1530, with no YAML history block. The diff does not add one. The generated API history will not show the new options.

Comment on lines +124 to +135
// An origin has no path, so a pattern with one could never match a document
// by its origin. Same rule as content scripts.
if (match_origin_as_fallback) {
for (const URLPattern& pattern : match_patterns_) {
if (pattern.path() != "/*") {
*error = "Invalid URL pattern '" + pattern.GetAsString() +
"': the path must be '/*' when matchOriginAsFallback is set";
return false;
}
}
}
return true;

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.

🟡 nit (optional): A service-worker preload is rejected when matchOriginAsFallback is set and a matches path is not /*. The docs say the option only applies to frame contexts. The /* check in ParseUrlPatterns() runs for every script type, but MatchesURL() ignores the flag for workers. Fix: apply the path rule only when script_type == kWebFrame, or document that service-worker registrations reject the flag too.

Why this was flagged

Trigger: ses.registerPreloadScript({ type: 'service-worker', filePath, matches: ['https://example.com/app/*'], matchOriginAsFallback: true }). This reaches Session::RegisterPreloadScript (electron_api_session.cc:1144), which calls ParseUrlPatterns(). At preload_script.cc:124-135 match_origin_as_fallback is checked without looking at script_type, so the call throws "the path must be '/*' when matchOriginAsFallback is set". For workers the flag does nothing: service-worker scopes are matched through MatchesURL() (session_preferences.cc:39, renderer_startup_data.cc:134), and only MatchesDocument() reads the flag. preload-script-registration.md and preload-script.md both say the option "Only applies to frame contexts". A reader expects it to be ignored for workers. Instead, a valid path-scoped worker filter is refused.

Verification: In shell/browser/preload_script.cc:126-133, ParseUrlPatterns() rejects any matches path other than /* when match_origin_as_fallback is set, without looking at script_type. Session::RegisterPreloadScript calls it unconditionally and throws the error. For workers the flag changes nothing about matching. The fallback only happens in MatchesDocument (preload_script.cc:154-157).

@jkleinsc
jkleinsc merged commit 231723d into 44-x-y Oct 22, 2026
68 checks passed
@jkleinsc
jkleinsc deleted the manual-bp/44-x-y/54903 branch October 22, 2026 21:18
@release-clerk

release-clerk Bot commented Oct 22, 2026

Copy link
Copy Markdown

Release Notes Persisted

Added filtering options to session.registerPreloadScript - matches, excludeMatches, includeGlobs, excludeGlobs, matchOriginAsFallback.

renovate Bot added a commit to cigaleapp/cigale that referenced this pull request Nov 8, 2026
##### [v44.10.1](https://github.com/electron/electron/releases/tag/v44.10.1)

### Release Notes for v44.10.1

#### Fixes

- Fixed DevTools "Save" prompting for a location every time instead of reusing the previously chosen file. [#55484](electron/electron#55484)
  - Fixed DevTools "Save As" using the old file and Linux cancels treated as saved.
- Fixed `webContents.adjustSelection()` ignoring the `end` option. [#55461](electron/electron#55461) <sup>(Also in [45](electron/electron#55462), [46](https://github.com/electron/electron/pull/55463))</sup>

#### Performance Improvements

- Improved performance of `net.fetch()` requests without a body. [#55445](electron/electron#55445) <sup>(Also in [43](electron/electron#55447), [45](electron/electron#55446), [46](https://github.com/electron/electron/pull/55444))</sup>
- Improved performance of repeated `net.fetch()` calls for `file:` URLs. [#55458](electron/electron#55458) <sup>(Also in [45](electron/electron#55459), [46](https://github.com/electron/electron/pull/55457))</sup>

#### Other Changes

- Backported fixes from upstream Chromium, Dawn, Skia and V8. [#55492](electron/electron#55492)
##### [v44.10.0](https://github.com/electron/electron/releases/tag/v44.10.0)

### Release Notes for v44.10.0

#### Features

- Added filtering options to `session.registerPreloadScript` - `matches`, `excludeMatches`, `includeGlobs`, `excludeGlobs`, `matchOriginAsFallback`. [#55182](electron/electron#55182) <sup>(Also in [45](https://github.com/electron/electron/pull/55181))</sup>

#### Fixes

- Fixed a crash on Linux when a D-Bus method call was made on a disconnected bus. [#55290](electron/electron#55290) <sup>(Also in [45](electron/electron#55292), [46](https://github.com/electron/electron/pull/55289))</sup>
- Fixed a main process crash when `onSendHeaders` observed Blob uploads. [#55168](electron/electron#55168) <sup>(Also in [45](https://github.com/electron/electron/pull/55169))</sup>
- Fixed `app.getLoginItemSettings()` not finding login items on Windows when the executable path contains spaces. [#55207](electron/electron#55207) <sup>(Also in [45](https://github.com/electron/electron/pull/54419))</sup>
- Fixed Europe/London and Europe/Dublin time zone names showing as "GMT+00:00" in winter by updating ICU to tzdata 2026e. [#55335](electron/electron#55335)
- Fixed File System Access blocklist gaps for `.git/hooks` writes and hypervisor UNC shares. [#55330](electron/electron#55330)
- Fixed handling of malformed asar archives whose size fields do not match the file length. [#55176](electron/electron#55176) <sup>(Also in [43](electron/electron#55179), [45](https://github.com/electron/electron/pull/55175))</sup>
- Fixed inconsistent handling of asar archive paths between the main process and child processes. [#55183](electron/electron#55183) <sup>(Also in [43](electron/electron#55185), [45](https://github.com/electron/electron/pull/55184))</sup>
- Fixed `Menu.popup()` on macOS sometimes not showing a menu after another closed. [#55325](electron/electron#55325) <sup>(Also in [45](electron/electron#55326), [46](https://github.com/electron/electron/pull/55324))</sup>
- Fixed MV3 extension events not arriving to background service workers. [#55152](electron/electron#55152) <sup>(Also in [43](electron/electron#55153), [45](https://github.com/electron/electron/pull/55154))</sup>
- Fixed paste hanging indefinitely on Linux X11 until the app was restarted. [#55327](electron/electron#55327)
- Fixed `protocol.registerSource` schemes not applying the same fetch rules as `protocol.handle` schemes. [#55177](electron/electron#55177) <sup>(Also in [45](https://github.com/electron/electron/pull/55178))</sup>
- Fixed `utilityProcess` not emitting an `exit` event when the app quit while the process was still launching. [#55273](electron/electron#55273) <sup>(Also in [43](electron/electron#55272), [45](electron/electron#55274), [46](https://github.com/electron/electron/pull/55264))</sup>

#### Other Changes

- Updated Chromium to 152.0.7977.169. [#55033](electron/electron#55033)
- Updated Node.js to v24.22.1. [#55162](electron/electron#55162)
##### [v44.9.3](https://github.com/electron/electron/releases/tag/v44.9.3)

### Release Notes for v44.9.3

#### Other Changes

- Backported fixes from upstream ANGLE, Chromium, PDFium, Skia and V8. [#55149](electron/electron#55149)
##### [v44.9.2](https://github.com/electron/electron/releases/tag/v44.9.2)

### Release Notes for v44.9.2
##### [v44.9.1](https://github.com/electron/electron/releases/tag/v44.9.1)

### Release Notes for v44.9.1

> \[!NOTE]
> This release contains the fix for <GHSA-jr5w-w6x2-84p9>, the mitigation for compromised eMudhra intermediate certificates
##### [v44.9.0](https://github.com/electron/electron/releases/tag/v44.9.0)

### Release Notes for v44.9.0

#### Features

- Added app shims on macOS to show windows under another app's Dock icon. [#55073](electron/electron#55073) <sup>(Also in [45](https://github.com/electron/electron/pull/55072))</sup>

#### Fixes

- Fixed link-opened windows not using the opener's session and `webPreferences`. [#55048](electron/electron#55048) <sup>(Also in [42](electron/electron#55050), [43](electron/electron#55049), [45](https://github.com/electron/electron/pull/55051))</sup>
- Fixed `setCertificateVerifyProc` occasionally not being applied to a request issued concurrently with the first request to a host. [#55046](electron/electron#55046) <sup>(Also in [42](electron/electron#55054), [43](electron/electron#55047), [45](https://github.com/electron/electron/pull/55045))</sup>
##### [v44.8.0](https://github.com/electron/electron/releases/tag/v44.8.0)

### Release Notes for v44.8.0

#### Features

- Added support for `Notification` action buttons on Linux. [#54890](electron/electron#54890) <sup>(Also in [45](https://github.com/electron/electron/pull/54889))</sup>

#### Fixes

- Fixed mouse cursor missing over native dialogs in certain scenarios on Windows. [#54987](electron/electron#54987)
- Fixed `net.fetch` and `session.fetch` failing permanently with `net::ERR_FAILED` after the Network Service process restarts. [#54909](electron/electron#54909) <sup>(Also in [42](electron/electron#54925), [43](electron/electron#54908), [45](https://github.com/electron/electron/pull/54910))</sup>
- Fixed `utilityProcess` dropping messages posted with `process.parentPort.postMessage()` right before the process exits. [#54960](electron/electron#54960) <sup>(Also in [42](electron/electron#55000), [43](electron/electron#54962), [45](https://github.com/electron/electron/pull/54956))</sup>
- Fixed `win.isFullScreen()` being stale in fullscreen events on Windows. [#55009](electron/electron#55009) <sup>(Also in [45](https://github.com/electron/electron/pull/55008))</sup>

#### Other Changes

- Backported fixes from upstream Chromium and V8. [#55034](electron/electron#55034)
- Updated Chromium to 152.0.7977.167. [#54928](electron/electron#54928)
- Updated Node.js to v24.22.0. [#55004](electron/electron#55004)
##### [v44.7.2](https://github.com/electron/electron/releases/tag/v44.7.2)

### Release Notes for v44.7.2

#### Fixes

- Fixed an issue where clicks posted to a background app were dropped on macOS. [#54819](electron/electron#54819) <sup>(Also in [45](https://github.com/electron/electron/pull/54818))</sup>
- Fixed interrupted macOS updates leaving a broken app behind. [#54844](electron/electron#54844) <sup>(Also in [45](https://github.com/electron/electron/pull/54843))</sup>

#### Other Changes

- Backported fixes from upstream ANGLE, Chromium, PDFium and V8. [#54898](electron/electron#54898)

#### Documentation

- Documentation changes: [#54880](electron/electron#54880)
##### [v44.7.1](https://github.com/electron/electron/releases/tag/v44.7.1)

### Release Notes for v44.7.1

#### Fixes

- Fixed a crash when starting without an available display server on Linux. [#54794](electron/electron#54794) <sup>(Also in [45](https://github.com/electron/electron/pull/54781))</sup>
- Fixed a Linux crash creating a window with a menu bar when GTK failed to load. [#54859](electron/electron#54859) <sup>(Also in [45](https://github.com/electron/electron/pull/54846))</sup>
- Fixed a `WebContentsView` that was removed with `removeChildView()` and re-added with `addChildView()` staying hidden behind its sibling views on Linux. [#54798](electron/electron#54798)
- Fixed asar archives in non-ASCII folders failing to load on Linux. [#54849](electron/electron#54849) <sup>(Also in [45](https://github.com/electron/electron/pull/54848))</sup>
- Fixed renderer crashes during garbage collection inside ShadowRealms. [#54865](electron/electron#54865) <sup>(Also in [45](https://github.com/electron/electron/pull/54864))</sup>

#### Other Changes

- Refactored mouse forwarding on Windows to fix `setIgnoreMouseEvents(true, { forward: true })` related issues. [#54802](electron/electron#54802) <sup>(Also in [45](https://github.com/electron/electron/pull/54803))</sup>
- Updated Chromium to 152.0.7977.149. [#54085](electron/electron#54085)
##### [v44.7.0](https://github.com/electron/electron/releases/tag/v44.7.0)

### Release Notes for v44.7.0

#### Features

- The macOS `autoUpdater` now streams update downloads to disk, resumes an interrupted download on the next check instead of starting over, and applies a binary delta when the update feed offers one for the running version. [#54204](electron/electron#54204)

#### Fixes

- Fixed an uncatchable TypeError in `net.fetch` when receiving response headers with non-ASCII characters, and preserved multiple Set-Cookie headers. [#54672](electron/electron#54672)

#### Other Changes

- Backported fixes from upstream ANGLE, Chromium, Dawn, fontconfig, Skia, V8 and WebRTC. [#54666](electron/electron#54666)
- Backported fixes from upstream ANGLE, Chromium, Skia, V8 and WebRTC. [#54657](electron/electron#54657)
##### [v44.6.0](https://github.com/electron/electron/releases/tag/v44.6.0)

### Release Notes for v44.6.0

#### Features

- Added the experimental `protocol.registerSource()` to serve a custom scheme from directories on disk without a JavaScript handler. [#54522](electron/electron#54522) <sup>(Also in [45](https://github.com/electron/electron/pull/54521))</sup>

#### Fixes

- Fixed a crash on launch on macOS when the system refused to register the app for sleep/wake notifications. [#54596](electron/electron#54596)
- Fixed a crash on `navigator.usb.requestDevice()` in in-memory sessions. [#54616](electron/electron#54616) <sup>(Also in [45](https://github.com/electron/electron/pull/54615))</sup>
- Fixed `webview.findInPage()` hanging when the host page also has an iframe. [#54586](electron/electron#54586) <sup>(Also in [43](electron/electron#54584), [45](https://github.com/electron/electron/pull/54585))</sup>
- Updated time zone data to tzdata 2026d, including British Columbia's move to permanent UTC-7. [#54623](electron/electron#54623)

#### Documentation

- Documentation changes: [#54589](electron/electron#54589)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

44-x-y backport/approved ✅ backport This is a backport PR semver/minor backwards-compatible functionality

Projects

No open projects
Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants