* ci: centralize build-image SHA and pre-seed node-gyp headers
- Add .github/actions/build-image-sha as the single source of truth for
the ghcr.io/electron/build (and arch-tagged electron/test) image SHA,
with an optional override input for workflow_dispatch.
- Refactor build.yml, apply-patches.yml, build-git-cache.yml,
clean-src-cache.yml, clean-orphaned-cache-uploads.yml, and the three
publish workflows to resolve the SHA via a small ubuntu-slim setup job
instead of hardcoding it in each file.
- Bump the image to daad061f (electron/build-images#68, which pre-warms
the node-gyp header cache in the Linux images).
- Run the build.yml setup job on ubuntu-slim instead of ubuntu-latest.
- In install-dependencies (and the inline yarn installs in
pipeline-electron-lint and generate-types), link deps with
--mode=skip-build first, run `node-gyp install` with up to 3 retries
(5s backoff) to populate the header cache, then run the build phase.
This avoids the parallel-download race that intermittently fails the
first native-addon configure with an empty common.gypi on cold
macOS/Windows runners.
* ci: skip node-gyp header pre-seed on Linux
* ci: invoke node-gyp via its JS entrypoint for Windows compat
* ci: run clang-tidy on macOS and Windows
* ci: copy framework headers for clang-tidy on macOS
* chore: exclude electron_smooth_round_rect.cc in CI
* chore: C-style casts are discouraged; use static_cast [google-readability-casting]
* chore: add extra args on Windows to clear out warnings
* ci: fix for macOS --remote-build none
WebSQL support was removed in Electron 31 (see breaking-changes.md), and
the 'websql' key was subsequently removed from the storages lookup in
session.ClearStorageData() during the Chromium 126 bump (#41868).
The documentation for `ses.clearStorageData()` was not updated at the
time and still lists `websql` as a valid value for the `storages`
option. Passing `websql` now silently has no effect, leaving the docs
out of sync with the implementation.
Remove `websql` from the documented list of storage types so the
documentation matches the actual behavior.
Refs: #33900
Signed-off-by: Asish Kumar <officialasishkumar@gmail.com>
* fix: ensure corsEnabled: false protocol handlers do not work across protocols
Subresource requests for registered custom protocols are routed to
ElectronURLLoaderFactory via the renderer's per-scheme URLLoaderFactoryBundle
entry, which bypasses the network service's CorsURLLoaderFactory. This meant a
cross-origin page could fetch() a scheme registered with {supportFetchAPI: true}
and read the response body even when {corsEnabled: true} was not set.
Replicate CorsURLLoader::StartRequest's kCorsDisabledScheme gate in
ElectronURLLoaderFactory::CreateLoaderAndStart so cross-origin mode=cors
requests to such schemes fail before the JS handler runs, and tag cross-origin
mode=no-cors responses as opaque so the body is not script-readable while <img>
and similar subresource loads continue to work.
Re-enable the long-disabled "disallows CORS and fetch requests when only
supportFetchAPI is specified" test, add coverage for the opaque/no-cors,
same-origin, handler-not-invoked, corsEnabled-unaffected and net.fetch-unaffected
cases, and migrate spec helpers that were exercising a {supportFetchAPI: true}
scheme cross-origin to a corsEnabled scheme.
* chore: oxfmt
* test: strengthen layout-sensitive coverage for docked DevTools and attached WebContentsView
Improve test coverage for layout-dependent behavior by asserting geometry results:
- Test that opening right-docked DevTools shrinks the inspected page
viewport and that closing DevTools restores it.
- Test that a newly-attached WebContentsView becomes visible with a
viewport that immediately matches the window’s content bounds.
* fixup! test: strengthen layout-sensitive coverage for docked DevTools and attached WebContentsView
BUILD.gn previously hard-coded read_file(".git/packed-refs", ...) and
".git/HEAD" to derive electron_version. In a `git worktree` checkout
.git is a file containing a gitdir: pointer, not a directory, so GN's
read_file() fails and gn gen aborts unless override_electron_version is
set manually.
Ask git itself for the real locations via `git rev-parse --git-dir` /
`--git-common-dir` in a small helper script, and feed those resolved
paths to read_file() and the exec_script dependency list. Behaviour in
a plain clone is unchanged (both resolve to electron/.git/...), and the
tarball case still fails loudly with a pointer to
override_electron_version.
stop_dbus() was removed on 2025-09-14 by
99c4800e9e
I think CI isn't seeing this yet because its image has an older version.
This patched script should work on old & new versions of python-dbusmock.
* build: add chrome-release-verify and chrome-release-cls skills
Adds two project skills under .claude/skills/ for security backports:
* chrome-release-cls — given a Chrome Releases blog post URL, extract
every CVE/bug and locate the underlying Gerrit CL by searching the
local Chromium checkout and sub-repos.
* chrome-release-verify — end-to-end backport flow for a release
branch: maps CVEs→CLs, verifies which fixes are already in the synced
source tree, writes the cherry-pick patches locally, validates with
`e sync --3` + `lint --patches` (with the export→lint→re-apply loop),
then opens a single PR with the linked-CL/crbug/CVE body format.
* ci: skip platform builds for .claude/** changes
* fix: intermittent CI failure is-not-alwaysOnTop
Ensure that the `always-on-top-changed` event always fires with the
right 'alwaysOnTop' boolean, regardless of interaction between
SetZOrderLevel() and MoveBehindTaskBarIfNeeded(). We know what the
value will be when all of the HWND events settle, so use that value.
* test: temporary commit to torture-test the new change with 1000 iterations
* test: keep eventually-becomes-consistent test but do not loop 1000 times
* feat: add `Notification.getHistory()` static method (macOS)
Add `Notification.getHistory()` which returns a `Promise<Notification[]>`
of all delivered notifications still present in Notification Center.
Each returned Notification is a live object connected to the corresponding
delivered notification — interaction events (click, reply, action, close)
will fire on these objects, enabling apps to re-attach event handlers after
a restart.
Key implementation details:
- Queries UNUserNotificationCenter's getDeliveredNotifications API
- Creates live Notification objects with populated id, groupId, title,
subtitle, and body properties from what macOS provides
- Registers each object with the presenter via Restore() so the
NotificationCenterDelegate routes events correctly
- Restored notifications use is_restored_ flag to prevent removal from
Notification Center when the JS object is garbage collected
- Requires code-signed builds (unsigned builds resolve with empty array)
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
* test: fix typecheck
* fix: avoid dangling presenter pointer in GetHistory callback
* fix: document show() behavior
Notifications returned by getHistory() now set is_restored_ so that Dismiss() skips removal from Notification Center on GC. Calling show() on a restored notification removes the original from NC and posts a new one.
* fix: address code review feedback
* test: fix oxfmt linting
* docs: update docs/api/notification.md
Co-authored-by: Erick Zhao <erick@hotmail.ca>
---------
Co-authored-by: Claude <svc-devxp-claude@slack-corp.com>
Co-authored-by: Erick Zhao <erick@hotmail.ca>
* ci: build a patched siso for Windows builds
The Windows Chromium builds intermittently fail during manifest load
with 'The parameter is incorrect.' (ERROR_INVALID_PARAMETER) out of
bindflt.sys. Root cause is a handle-relative NtCreateFile race in
siso/toolsupport/ninjautil/file_parser.go, which opens each subninja
twice — once in the outer goroutine and once more per chunk for
ReadAt. (*os.File).ReadAt is documented as safe for concurrent use,
so the extra open is redundant and removing it both halves the
CreateFileW calls per subninja and sidesteps the race.
Add a new build-siso-windows job on ubuntu-latest (runs in parallel
with checkout-windows) that:
- reads chromium_version from DEPS and pulls the matching siso_version
SHA from the Chromium mirror's DEPS at that ref
- shallow-clones chromium.googlesource.com/build at that SHA
- applies the in-tree patches under .github/siso-patches/ via git am
- cross-compiles siso.exe for windows/amd64
- caches the binary keyed on siso SHA + sha256 of the patches, so
subsequent runs hit the cache and skip the clone/patch/build steps
- uploads the result as a siso-windows-amd64 artifact
The Windows build jobs now depend on build-siso-windows, download the
artifact into $RUNNER_TEMP/siso, and export SISO_PATH, which
depot_tools/siso.py already honors. Mirrored into windows-publish.yml
and the regenerated pipeline-segment-electron-publish.yml so release
builds pick it up too.
Notes: none
* ci: extract siso build into a reusable workflow segment
Move the build-siso-windows job body into
pipeline-segment-build-siso-windows.yml and call it from both build.yml
and windows-publish.yml via workflow_call. Also pin actions/cache to
v5.0.5 and add version comments next to the action SHAs introduced by
this change.
fix: prevent use-after-free when destroying guest WebContents during event emission
Multiple event emission sites in WebContents destroy the underlying C++
object via a JavaScript event handler calling webContents.destroy(), then
continue to dereference the freed `this` pointer. This is exploitable
through <webview> guest WebContents because Destroy() calls `delete this`
synchronously for guests, unlike non-guests which safely defer deletion.
The fix has two layers:
1. A new `is_emitting_event_` flag is checked in Destroy() — when true,
guest deletion is deferred to a posted task instead of executing
synchronously. This is separate from `is_safe_to_delete_` (which
gates LoadURL re-entrancy) to avoid rejecting legitimate loadURL
calls from event handlers.
2. AutoReset<bool> guards on `is_emitting_event_` are added to
CloseContents, RenderViewDeleted, DidFinishNavigation, and
SetContentsBounds, preventing synchronous destruction while their
Emit() calls are on the stack.
Destroy() now requires both `is_safe_to_delete_` (navigation re-entrancy)
and `!is_emitting_event_` (event emission) to allow synchronous guest
deletion. The existing AutoReset guards on `is_safe_to_delete_` in
DidStartNavigation, DidRedirectNavigation, and ReadyToCommitNavigation
are also now effective for guests.
Because of a bug after the [upstream refactor][0] Dev Tools stopped
showing 'Electron Isolated Context' in the execution context selector.
'Electron Isolated Context' runs with origin set to `file://`. Since
domain name is empty for the origin the respective UI item in the
context selector is created with an empty `subtitle`. However, with the
upstream change items with either of `title` or `subtitle` are omitted
from rendering.
Here we float an [in-review patch][1] until it is fixed upstream.
[0]: dbb61cf4b2
[1]: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7761316
* refactor: MessageChannel does not need to extend EventEmitter
Added in f66d4c7 but never used.
Apparently added as a copy-paste side effect when adding better interface
info into the lib types, eg extends/implements.
* refactor: ShareMenu does not need to extend EventEmitter
Added in f66d4c7 but never used.
Apparently added as a copy-paste side effect when adding better interface
info into the lib types, eg extends/implements.
* fix: UAF in api::UtilityProcessWrapper
Detach the wrapper from ServiceProcessHost during termination instead
of waiting for destruction. Add a regression test that forces GC.
This fixes a UAF error reported by ASAN: the wrapper lost its last JS
reference and become collectible after emitting exit *but* before it
had been removed from the global observer list.
UtilityProcessWrapper is now cppgc-managed as of b9e462f397, but its
ServiceProcessHost observer cleanup still depended on destructor-time
teardown.
* fixup! fix: UAF in api::UtilityProcessWrapper
fix: much better cleanup from Deepak code review
The PDF viewer's "save with changes" feature uses
`window.showSaveFilePicker()`, but the PDF extension runs in a
cross-origin iframe (chrome-extension:// inside the app's origin).
Chromium's File System Access API blocks cross-origin subframes from
showing file pickers unless the embedder explicitly allows them via
`ContentClient::IsFilePickerAllowedForCrossOriginSubframe()`.
Chrome overrides this in `ChromeContentClient` to allowlist the PDF
extension origin, but Electron never did — so the picker was always
blocked with a SecurityError.
This adds the same override to `ElectronContentClient`, allowing the
built-in PDF extension origin to bypass the cross-origin check.
docs: add ELECTRON_INSTALL env vars and remove ELECTRON_SKIP_BINARY_DOWNLOAD
these were added recently in a commit but no docs were there for them
also, ELECTRON_SKIP_BINARY_DOWNLOAD was deprecated in electron v42, so that is removed as well
fix: fail gha-done when any required job failed
Previously, the `gha-done` gate job used an `if:` expression that
evaluated to false whenever any needed job reported a failure, which
caused the job to be *skipped* rather than *failed*. GitHub branch
protection treats skipped required checks as non-blocking, so a PR
could be marked mergeable even though one of its test jobs had failed.
Keep the job always running and move the failure check into a step
that explicitly exits 1 when any dependency failed or was cancelled,
so the "GitHub Actions Completed" required check actually blocks the
merge in that case.
Notes: none
* refactor: migrate electron::api::GlobalShortcut to cppgc
* refactor: lazy-create electron::api::GlobalShortcut
copy the lazy-create idom used by electron::api::Screen
* refactor: use gin::WeakCellFactory in GlobalCallbacks
* fix: make a copy of `callback` before running it
safeguard against the callback changing the map, invalidating `cb`
* chore: reduce unnecessary diffs with main
* fixup! refactor: use gin::WeakCellFactory in GlobalCallbacks
fix: must Trace() the weak cell factory
* fix: destruction order
- Setup isolate dispose observer to run destruction sequences
and remove self persistent reference
- Skip NOTREACHED check during destruction, it can happen
as a result of plaform listeners scheduling callbacks when Unregister is invoked.
- Fix the order of unregistration in GlobalShortcut::Unregister
- Add GlobalShortcut::UnregisterAllInternal to avoid any callsites
that can re-enter V8
* fix: crash during gc from incorrect cppgc object headers
* chore: update patches
* chore: cleanup
* chore: fix lint
---------
Co-authored-by: deepak1556 <hop2deep@gmail.com>
refactor: use StartUpdating in desktopCapturer
Replace the one-shot Update() callback model with the continuous
StartUpdating() observer model for NativeDesktopMediaList.
Fixes a macOS DCHECK(can_refresh()) crash in UpdateSourceThumbnail(),
where ScreenCaptureKit's recurrent thumbnail capturer would post
UpdateSourceThumbnail callbacks after the one-shot refresh_callback_
had been consumed. Now, can_refresh() is always true because
refresh_callback_ is repopulated via ScheduleNextRefresh().
Each capturer (window, screen) gets its own ListObserver that tracks
readiness via OnSourceAdded and OnSourceThumbnailChanged events.
Once a list has both sources and thumbnails (or thumbnails aren't
requested), its data is snapshotted and the capturer checks if all
requested types are ready before resolving to JS.
Also remove the "skip_next_refresh_" Chromium patch, which was a
workaround for the timing mismatch between the one-shot Update()
model and ScreenCaptureKit's asynchronous thumbnail delivery.
refactor: simplify state logic in DesktopCapturer