* 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.
Co-authored-by: Charles Kerr <charles@charleskerr.com>
* test: temporary commit to torture-test the new change with 1000 iterations
Co-authored-by: Charles Kerr <charles@charleskerr.com>
* test: keep eventually-becomes-consistent test but do not loop 1000 times
Co-authored-by: Charles Kerr <charles@charleskerr.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
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.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Clone angle from github.com/google/angle in fix-sync action
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
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.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Sam Attard <sattard@anthropic.com>
* fix: nodeIntegrationInWorker not working in AudioWorklet
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* fix: deadlock on Windows when destroying non-AudioWorklet worker contexts
The previous change kept the WebWorkerObserver alive across
ContextWillDestroy so the worker thread could be reused for the next
context (AudioWorklet thread pooling, Chromium CL:5270028). This is
correct for AudioWorklet but wrong for PaintWorklet and other worker
types, which Blink does not pool — each teardown destroys the thread.
For those worker types, ~NodeBindings was deferred to the thread-exit
TLS callback. By that point set_uv_env(nullptr) had already run, so on
Windows the embed thread was parked in GetQueuedCompletionStatus with a
stale async_sent latch that swallowed the eventual WakeupEmbedThread()
from ~NodeBindings. uv_thread_join then blocked forever, deadlocking
renderer navigation. The worker-multiple-destroy crash case timed out
on win-x64/x86/arm64 as a result. macOS/Linux (epoll/kqueue) don't have
the latch and were unaffected.
Plumb is_audio_worklet from WillDestroyWorkerContextOnWorkerThread into
ContextWillDestroy. For non-AudioWorklet contexts, restore the
pre-existing behavior of calling lazy_tls->Set(nullptr) at the end of
the last-context cleanup so ~NodeBindings runs while the worker thread
is still healthy. AudioWorklet continues to keep the observer alive so
the next pooled context can share NodeBindings.
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* chore: address review feedback
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* fix: stop embed thread before destroying environments in worker teardown
FreeEnvironment (called via environments_.clear()) runs uv_run to drain
handle close callbacks. On Windows, both that uv_run and the embed
thread's PollEvents call GetQueuedCompletionStatus on the same IOCP
handle. IOCP completions are consumed by exactly one waiter, so the
embed thread can steal completions that FreeEnvironment needs, causing
uv_run to block indefinitely. On Linux/Mac epoll_wait/kevent can wake
multiple waiters for the same event so the race doesn't manifest.
Add NodeBindings::StopPolling() which cleanly joins the embed thread
without destroying handles or the loop, and allows PrepareEmbedThread +
StartPolling to restart it later. Call StopPolling() in
WebWorkerObserver::ContextWillDestroy before environments_.clear() so
FreeEnvironment's uv_run is the only thread touching the IOCP.
Split PrepareEmbedThread's handle initialization (uv_async_init,
uv_sem_init) from thread creation via a new embed_thread_prepared_ flag
so the handles survive across stop/restart cycles for pooled worklets
while the embed thread itself can be recreated.
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* chore: address outstanding feedback
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* chore: update patches
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
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.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
ci: build a patched siso for Windows builds (#51077)
* 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.
(cherry picked from commit 5523130c92)
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.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
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
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Fedor Indutny <indutny@signal.org>
fix: simpleFullScreen exits when web content calls requestFullscreen
SetHtmlApiFullscreen only checked IsFullscreen() to detect that the
window was already fullscreen, missing the simple-fullscreen case on
macOS. When web content triggered requestFullscreen the code fell
through to SetFullScreen(true) which toggled simple fullscreen off.
Include IsSimpleFullScreen() in the guard so the HTML-API fullscreen
state is updated without touching the window's fullscreen mode.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* chore: testing of desktopCapturer can run on arm
* fix: DesktopMediaListCaptureThread crash
Fixed a crash when Windows calls ::CoCreateInstance() in the
DesktopMediaListCaptureThread before COM is initialized.
* test: added test for desktopCapturer fetchWindowIcons
* chore: updating Chromium patch hash
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Kanishk Ranjan <68316017+KanishkRanjan@users.noreply.github.com>
* chore: backport cppgc cleanups
Key fixes:
- Replace `base::WeakPtrFactory` with `gin::WeakCellFactory` in
MenuMac, MenuViews, and NetLog, since weak pointers to cppgc-managed
objects must go through weak cells
- Replace `v8::Global<v8::Value>` with `cppgc::Persistent<Menu>` for
the menu reference in BaseWindow
- Stop using `gin_helper::Handle<T>` with cppgc types; use raw `T*`
and add a `static_assert` to prevent future misuse
- Add proper `Trace()` overrides for Menu, MenuMac, MenuViews, and
NetLog to ensure cppgc members are visited during garbage collection
- Replace `SelfKeepAlive` prevent-GC mechanism in Menu with a
`cppgc::Persistent` prevent-GC captured in `BindSelfToClosure`
- Introduce `GC_PLUGIN_IGNORE` macro to suppress
known-safe violations: mojo::Remote fields, ObjC bridging pointers,
and intentional persistent self-references
- Mark `ArgumentHolder` as `CPPGC_STACK_ALLOCATED()` in both Electron's
and gin's function_template.h to silence raw-pointer-to-GC-type
warnings
* chore: fix build
* chore: cherry-pick b54c7841e2cd from v8
[*lev] Correctly update use counts for nested builtin continuations
Fixed: 484527367
Change-Id: I4cda8c1bbb2788fca06b564eae509511aec0957e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7593054
Reviewed-by: Victor Gomes <victorgomes@chromium.org>
Auto-Submit: Darius Mercadier <dmercadier@chromium.org>
Commit-Queue: Darius Mercadier <dmercadier@chromium.org>
Cr-Commit-Position: refs/heads/main@{#105381}
* chore: cherry-pick ba0258ba9609 from v8
[inspector] Use std::shared_ptr for InspectedContext
Unfortunately at this point we are not able to move InspectedContext
to the managed C++ heap due to missing Heap* collections and the lack
of labeling retainer links.
The next best thing we can do for now is use std::shared_ptr for
InspectedContext and keep an instance on the stack every time we can
potentially transition into user JS.
Fixed: 486927780
Change-Id: I5e4921521a24cc3cd53ffb6cb5b6b6f9d98490e2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7613210
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Simon Zuend <szuend@chromium.org>
Cr-Commit-Position: refs/heads/main@{#105489}
chore: clean up clang-tidy warnings (#50862)
* chore: use emplace and use it correctly
* chore: redundant cast to the same type [google-readability-casting]
* chore: do not create objects with +new [google-objc-avoid-nsobject-new]
* chore: default arguments on virtual or override methods are prohibited [google-default-arguments]
* chore: warning: C-style casts are discouraged; use static_cast [google-readability-casting]
CFLocaleGetValue already returns CFTypeRef so that redundant static_cast was removed
* chore: refactor block to avoid use after move warning from clang-tidy
Looks like clang-tidy couldn't tell these were two mutually exclusive
branches so there was no actual issue, but refactoring is cleaner
anyway since it makes it more DRY.
* chore: C-style casts are discouraged; use static_cast [google-readability-casting]
No cast needed here, everything is already the correct type
* chore: C-style casts are discouraged; use static_cast/const_cast/reinterpret_cast [google-readability-casting]
* chore: use '= default' to define a trivial destructor [modernize-use-equals-default]
* chore: use range-based for loop instead [modernize-loop-convert]
* chore: redundant void argument list [modernize-redundant-void-arg]
* chore: address code review feedback
* chore: use auto
---------
Co-authored-by: Charles Kerr <charles@charleskerr.com>
1. Chromium can fire unrelated permission checks (e.g. 'background-sync')
on the default session. Copy a safeguard `permission === 'fileSystem'` from
"calls twice when trying to query a read/write file handle permissions".
2. add afterEach cleanup: reset setPermissionCheckHandler(null) and
remove ipcMain listeners for 'did-create-file-handle' and
'did-create-directory-handle'.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
fix: pass root_gen_dir from GN to generate_node_headers.py
PR #50828 replaced a local get_out_dir() (defaulting to 'Testing') with
the shared one from script/lib/util.py (defaulting to 'Default').
Neither default is correct because the actual output directory depends
on the active build config. Pass $root_gen_dir from the GN action so
the script always uses the correct path.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
fix: return numeric `blksize` and `blocks` from asar `fs.stat`
Previously, `fs.stat` on files inside `.asar` archives returned
`undefined` for `blksize` and `blocks`, violating the Node.js API
contract where these fields must be `number | bigint`.
Use `4096` for `blksize` (matching the convention used by `memfs` and
the proposed `node:vfs` module in nodejs/node#61478) and compute
`blocks` as `ceil(size / 512)` (standard 512-byte block units).
Fixes#42686
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: clavin <clavin@electronjs.org>
#47171 migrated `std::deque` to `base::circular_deque` in
`shell/common/crash_keys.cc`. However, `CrashKeyString` wraps a
`crashpad::Annotation` that holds self-referential pointers and
registers itself in a process-global linked list. `circular_deque`
relocates elements on growth (via `VectorBuffer::MoveConstructRange`),
leaving those pointers dangling — causing missing crash keys or a hung
crashpad handler (especially on macOS). The `base/containers/README.md`
warns: "Since `base::deque` does not have stable iterators and it will
move the objects it contains, it may not be appropriate for all uses."
Reverts to `std::deque`, whose block-based layout never relocates
existing elements. Adds a regression test that registers 50 dynamic
crash keys and verifies they all survive a renderer crash.
Notes: Fixed crash keys being lost and the crash reporter hanging on
macOS when many dynamic crash keys were registered.
Made-with: Cursor
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Alexey Kozy <alexey@anysphere.co>
fix: webContents.print() ignoring mediaSize when silent
PR #49523 moved the default media size fallback into OnGetDeviceNameToUse,
but the new code unconditionally writes kSettingMediaSize — clobbering
any mediaSize the caller had already set in WebContents::Print() from
options.mediaSize / pageSize. As a result, silent prints with an
explicit pageSize (e.g. "Letter") fell back to A4 with tiny content.
Only populate the default/printer media size when the caller hasn't
already supplied one, preserving the precedence:
1. user-supplied mediaSize / pageSize
2. printer default (when usePrinterDefaultPageSize is true)
3. A4 fallback
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
fix: move Electron help menu links to default app only (#50629)
* fix: remove Electron links from default help menu
* fix: remove help menu entirely from default menu
* fix: move Electron help menu links to default app
* docs: update default menu items list in menu.md
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Zeenat Lawal <zeenatlawal82@gmail.com>
Menu was holding a SelfKeepAlive to itself from construction, so any
Menu that was never opened (e.g. an application menu replaced before
being shown) stayed pinned in cppgc forever. Repeated calls to
Menu.setApplicationMenu leaked every prior Menu along with its model
and items.
Restore the original Pin/Unpin lifecycle: start keep_alive_ empty and
only assign `this` in OnMenuWillShow. OnMenuWillClose already clears
it.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
PR #50646 added a dock state allowlist in SetDockState() that collapsed any
non-matching value to "right". WebContents::OpenDevTools passes an empty
string when no `mode` option is given, which is the sentinel LoadCompleted()
uses to restore `currentDockState` from prefs. The allowlist clobbered that
sentinel to "right", so previously-undocked devtools would flash detached
and then snap back to the right dock.
Preserve the empty string through SetDockState() so the pref-restore path
runs; still reject any non-empty invalid value to keep the JS-injection
guard from #50646 intact.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* ci: use hermetic mac SDK for the release ffmpeg build
gn gen out/ffmpeg runs as a raw gn invocation, so it never receives the
mac_sdk_path arg that e build injects for out/Default. On macOS runners
that means out/Default builds against the hermetic build-tools SDK while
out/ffmpeg falls through to the runner's system Xcode SDK. Reuse the
value e build already wrote so both builds share the same sysroot.
Co-authored-by: Samuel Attard <sattard@anthropic.com>
* ci: copy hermetic SDK symlink into out/ffmpeg and rewrite path
mac_sdk_path must live under root_build_dir, so pointing out/ffmpeg at
//out/Default/... doesn't work. Copy the xcode_links symlink tree into
out/ffmpeg and rewrite the path. Gate on Darwin so Windows/Linux don't
run the sed/cp at all.
Co-authored-by: Samuel Attard <sattard@anthropic.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
fix: enforce size constraints on window creation on Windows and Linux (#49906)
* enforce size constraints on window creation
* set constraints after resizing on init
* restore conditional centering
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
ci: make src-cache upload atomic and sweep orphaned temp files
The checkout action's cp of the ~6GB zstd archive directly to the final
path on the cache share is non-atomic; an interrupted copy or a
concurrent reader produces zstd "Read error (39): premature end" on
restore, and the truncated file then satisfies the existence check so
no later run repairs it.
Upload to a run-unique *.tar.upload-<run_id>-<attempt> temp name on the
share and mv to the final path, discarding our temp if a concurrent run
got there first. A new clean-orphaned-cache-uploads workflow removes
temp files older than 4h every 4 hours.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Sam Attard <sattard@anthropic.com>
build: derive patches upstream-head ref from script path (#50727)
* build: derive patches upstream-head ref from script path
gclient-new-workdir.py symlinks each repo's .git/refs back to the source
checkout, so the fixed refs/patches/upstream-head was shared across all
worktrees. Parallel `e sync` runs in different worktrees clobbered each
other's upstream-head, breaking `e patches` and check-patch-diff.
Suffix the ref with an md5 of the script directory so each worktree writes
a distinct ref into the shared refs dir. Fall back to the legacy ref name
in guess_base_commit so existing checkouts keep working until next sync.
* fixup: also write legacy upstream-head ref and note it in docs
fix: re-enable MacWebContentsOcclusion with embedder window fix (#50579)
* fix: re-enable MacWebContentsOcclusion with embedder window fix
Replace the full revert of Chromium's MacWebContentsOcclusion cleanup
with a targeted patch that handles embedder windows shown after
WebContentsViewCocoa attachment. This lets us drop the feature flag
disable in feature_list.cc and re-enable upstream occlusion tracking.
Adds tests for show/hide event counts on macOS and visibility tracking
across multiple child WebContentsViews.
* test: drop show/hide event count assertion
The assertion that 'show' fires exactly once per w.show() call is not
an API guarantee - macOS can send multiple occlusion state
notifications during a single show() when other windows are on screen
(common on CI after hundreds of prior tests). The
visibilitychange-count test in api-web-contents-view-spec.ts covers
the actual invariant we care about.
* fix: ignore WebContentsOcclusionCheckerMac synthetic notifications in window delegate
On macOS 13.3-25.x, Chromium's occlusion checker enables manual
frame-intersection detection and posts synthetic
NSWindowDidChangeOcclusionStateNotification tagged with its class name
in userInfo. These fire when the checker's NSContainsRect heuristic
decides a window is covered by another window's frame, but the real
-[NSWindow occlusionState] hasn't changed.
Our delegate was treating these the same as real macOS notifications
and emitting show/hide events based on occlusionState, which was
unchanged - resulting in spurious duplicate show events when e.g.
Quick Look opened and its frame intersected the BrowserWindow.
chore: harden GitHub Actions against script injection patterns (#50512)
* fix: harden GitHub Actions against script injection vulnerabilities
Replace direct ${{ }} expression interpolation in run: blocks with
environment variables to prevent script injection attacks. Changes:
- archaeologist-dig.yml: move clone_url, head.sha, base.ref to env vars
- non-maintainer-dependency-change.yml: move user.login to env var
- issue-unlabeled.yml: move toJSON(labels) to env var
- issue-labeled.yml: move issue.number to env var
- pipeline-electron-lint.yml: validate chromium_revision format
- cipd-install/action.yml: move all inputs to env vars and quote them
- set-chromium-cookie/action.yml: reference secrets via $ENV_VAR
- Add security comments to all 5 pull_request_target workflows
https://claude.ai/code/session_01UUWmLxn5hyyxrhK8rGxU2s
* fix: allow version strings in chromium_revision validation
The previous regex `^[a-f0-9]+$` only matched git SHAs but
chromium_revision is a version string like `148.0.7741.0`.
Broaden to `^[a-zA-Z0-9._-]+$` which still blocks shell
metacharacters.
https://claude.ai/code/session_01UUWmLxn5hyyxrhK8rGxU2s
---------
Co-authored-by: Claude <noreply@anthropic.com>
build: replace npx with lockfile-pinned binaries (#50598)
* build: replace npx with lockfile-pinned binaries
- nan-spec-runner: reorder yarn install first, invoke nan node-gyp bin directly
- publish-to-npm: use host npm with E404 try/catch (closes existing TODO)
- upload-symbols: add @sentry/cli devDep, invoke from node_modules/.bin
- remove script/lib/npx.py (dead since #48243)
* build: bump @sentry/cli to 1.70.0 for arm support
* build: bump @sentry/cli to 1.72.0, skip CDN download on test jobs
@sentry/cli fetches its platform binary from Sentry CDN at postinstall.
Only upload-symbols.py (release pipeline) needs the binary; set
SENTRYCLI_SKIP_DOWNLOAD=1 in the two test-segment workflows that
call install-dependencies. The 64k variant uses pre-built artifacts
and does not install deps.
ci: zstd-compress the src cache and drop the doubled win_toolchain (#50702)
* ci: shrink src cache and fix Windows tar cleanup
- Exclude platform-specific toolchains (llvm-build, rust-toolchain) from
the src cache; all platforms now fetch them via fix-sync post-restore
- Exclude unused test data and benchmarks: blink/web_tests, jetstream,
speedometer, catapult/tracing/test_data, swiftshader/tests/regres
- Fix Windows restore leaving the tarball on disk after extraction
($src_cache was scoped to the previous PowerShell step)
- Bump src-cache key v1 -> v2
* ci: fetch llvm/rust toolchains in gn-check and clang-tidy
These workflows restore the src cache but don't run fix-sync. Now that
llvm-build and rust-toolchain are excluded from the cache, they need to
download them directly — gn gen read_file()s both, and clang-tidy runs
the binary from llvm-build.
* ci: fetch clang-tidy package explicitly
update.py's default 'clang' package doesn't include the clang-tidy
binary; it ships as a separate package.
* ci: preserve blink/web_tests/BUILD.gn when stripping test data
//BUILD.gn references //third_party/blink/web_tests:wpt_tests as a
target label, so the BUILD.gn must exist for gn gen. The data = [...]
entries it declares are runtime-only and not existence-checked at gen
time, so the actual test directories can still be removed.
* ci: compress src cache with zstd and drop gclient sync -vv
The src cache was an uncompressed tar (~16GB after exclusions). Switch
to zstd -T0 --long=30 for ~4x smaller transfer and multi-threaded
compression. Decompress on restore:
- Linux/macOS: zstd -d -c | tar -xf -
- Windows: zstd -d to an intermediate .tar, then the existing 7z
-snld20 extraction (preserves symlink handling)
All filename references updated .tar -> .tar.zst. -f added to the two
-o invocations so re-runs overwrite instead of failing.
Also drop -vv from gclient sync; default verbosity is sufficient.
* ci: keep .tar extension for src cache (zstd content inside)
The sas-sidecar that issues Azure SAS tokens validates filenames against
/^v[0-9]+-[a-z\-]+-[a-f0-9]+\.(tar|tgz)$/ and is not easily redeployed,
so keep the .tar extension and decode zstd on restore. Windows
decompresses to a distinct intermediate (src_cache.tar) so input and
output don't collide.
* ci: log NTFS 8.3/lastaccess/Defender state before Windows cache extract
Temporary diagnostics to see whether 8.3 short-name generation is the
cause of the ~20 min tar extraction.
* ci: revert src-cache exclusion additions
The new exclusions (web_tests contents, jetstream, speedometer,
catapult test_data, regres, llvm-build, rust-toolchain) caused siso/RBE
cache misses — even data-only deps are part of action input hashes.
Revert to the original exclusion list and drop the corresponding
toolchain-fetch plumbing. zstd compression, the Windows tar cleanup,
and the -vv removal remain.
* ci: drop win_toolchain from src cache; remove NTFS diagnostics
The Windows src cache includes 14.6GB of depot_tools/win_toolchain —
7.3GB of MSVC/SDK doubled because tar captures both the vs_files.ciopfs
backing store and the live ciopfs mount at vs_files/. Every Windows
cache consumer already re-fetches this via vs_toolchain.py update
--force (fix-sync for build/publish, inline for gn-check/clang-tidy),
so the cached copy is never used.
Diagnostics removed — CI confirmed 8dot3, last-access, and Defender are
all already off on the AKS Windows nodes.
* ci: unmount ciopfs vs_files before removing win_toolchain
vs_files is a live ciopfs mount during the win-targeted checkout; rm -rf
fails with EBUSY until it's unmounted.
* ci: skip win_toolchain download during checkout instead of removing after
fusermount isn't on the checkout container, so the ciopfs mount can't be
torn down before rm. Setting DEPOT_TOOLS_WIN_TOOLCHAIN=0 makes the
win_toolchain hook a no-op (vs_toolchain.py:525-527), so there's no
download and no mount. All Windows consumers re-fetch it post-restore
anyway. The rm -rf stays as a safety net.
* ci: also set ELECTRON_DEPOT_TOOLS_WIN_TOOLCHAIN=0 for checkout sync
build.yml sets ELECTRON_DEPOT_TOOLS_WIN_TOOLCHAIN=1 at the job level for
the Windows checkout, which makes e d inject DEPOT_TOOLS_WIN_TOOLCHAIN=1
and override the inline =0. Need both: the ELECTRON_ var stops e d from
overriding, the plain one stops vs_toolchain.py from defaulting to 1.
* ci: extract Windows src cache with piped tar instead of 7z
7z takes ~20 min to extract the ~1.1M-entry tar regardless of size —
~1ms per entry of header parsing and path handling, single-threaded,
well under the 75k IOPS / 1000 MBps the ephemeral disk can do. Switch
to the same zstd -d | tar -xf - pipe used on Linux/macOS (via Git Bash
tar). No intermediate src_cache.tar, download deleted after extract.
The -snld20 flag was working around 7z's own "dangerous symlink"
refusal; GNU tar extracts symlinks as-is so it shouldn't be needed.
* ci: keep depot_tools/win_toolchain scripts in src cache
The rm -rf removed get_toolchain_if_necessary.py (a depot_tools source
file), breaking vs_toolchain.py update --force on restore.
DEPOT_TOOLS_WIN_TOOLCHAIN=0 on the sync already prevents the vs_files
download, so the rm was only removing scripts.
* ci: split src cache into 4 parallel-extractable shards
Windows tar extraction is ~1ms/entry for ~1.2M entries (~20 min)
regardless of tool, well under the 75k IOPS / 1000 MBps the D16lds_v5
ephemeral disk can do. Tar is a sequential stream so the only way to
parallelize is to split at creation time.
Shards (balanced by entry count, ~220-360k each):
a: src/third_party/blink
b: src/third_party/{dawn,electron_node,tflite,devtools-frontend}
c: src/third_party (rest)
d: src (excluding third_party)
DEPSHASH is now the raw hash; shard files are
v2-src-cache-shard-{a..d}-${DEPSHASH}.tar (all pass the sas-sidecar
filename regex). sas-token is now a JSON keyed by shard letter. All
restore paths extract the four shards in parallel with per-PID wait so
a failed shard aborts the step.
* Revert "ci: split src cache into 4 parallel-extractable shards"
This reverts commit 970574998b.
fix-sync re-downloads llvm-build on macOS/Windows with the base clang
and objdump packages, but not clang-tidy. A local gclient sync pulls
clang-tidy (checkout_clang_tidy=True in DEPS), so CI's llvm-build tree
diverges from a local one. siso hashes the toolchain as action input,
so cache-only local runs against the CI-populated RBE cache miss.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
V8's second-pass weak callbacks run inside a
DisallowJavascriptExecutionScope: they may touch the V8 API but must
not invoke JS, directly or indirectly. Several Electron Wrappables
(WebContents in particular) emit JS events from their destructors,
so deleting synchronously inside SecondWeakCallback can crash with
"Invoke in DisallowJavascriptExecutionScope" when GC happens to
collect the JS wrapper during a foreground GC task — typically during
shutdown's uv_run drain after a leaked WebContentsView.
This was previously latent and timing-dependent (electron/electron#47420,
electron/electron#45416, podman-desktop/podman-desktop#12409). The
esbuild migration's keepNames option (which wraps every function/class
with an Object.defineProperty call) shifted heap layout enough to make
the spec/fixtures/crash-cases/webcontentsview-create-leak-exit case
reliably reproduce it on every run, giving a clean signal for the fix.
Both WrappableBase and DeprecatedWrappableBase SecondWeakCallback now
post the deletion via base::SequencedTaskRunner::GetCurrentDefault()
so the destructor (and any Emit it does) runs once V8 has left the GC
scope. Falls back to synchronous deletion if no task runner is
available (early/late process lifetime).
Fixeselectron/electron#47420.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Sam Attard <sattard@anthropic.com>
WebContentsPermissionHelper::CheckPermission was hardcoding
GetPrimaryMainFrame() and deriving the requesting origin from
web_contents_->GetLastCommittedURL(), so the setPermissionCheckHandler
callback always received the top frame's origin and
details.isMainFrame/details.requestingUrl always reflected the main
frame, even when a cross-origin subframe with allow="serial" or
allow="camera; microphone" triggered the check.
Thread the requesting RenderFrameHost through CheckPermission,
CheckSerialAccessPermission, and CheckMediaAccessPermission so the
permission manager receives the real requesting frame. Update the
serial delegate and WebContents::CheckMediaAccessPermission callers to
pass the frame they already have.
Adds a regression test that loads a cross-origin iframe with
allow="camera; microphone", calls enumerateDevices() from within the
iframe, and asserts the permission check handler receives the iframe
origin for requestingOrigin, isMainFrame, and requestingUrl.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Sam Attard <sattard@anthropic.com>
fix: resolve getFileHandle concurrent stalling by queuing callbacks (#50597)
Previously, concurrent calls to FileSystemAccessPermissionContext::ConfirmSensitiveEntryAccess
for the same file path would silently discard the subsequent callbacks because
the internal callback map used a single callback per file path and std::map::try_emplace
would drop the callback if the key already existed. This caused Promises in JS
(e.g., dirHandle.getFileHandle()) to stall indefinitely.
This commit updates the callback map to hold a vector of callbacks, so all
concurrent requesters for the same filepath are grouped together and resolved
once the asynchronous blocklist check completes.
Notes: Fixed an issue where concurrent `getFileHandle` requests on the same path could stall indefinitely.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Kunal Dubey <21157775+xakep8@users.noreply.github.com>
fix: validate dock_state_ against allowlist before JS execution
The dock_state_ member was concatenated directly into a JavaScript
string and executed via ExecuteJavaScript() in the DevTools context.
We should validate against the four known dock states and fall back
to "right" for any unrecognized value for safety
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
When silent printing with non-default margins (custom, no margins, or
printable area margins), the kFitToPrintableArea scaling option causes
double-marginalization: the custom margins define the content area, then
the scaling additionally fits content to the printer's printable area.
Only apply kFitToPrintableArea when using default margins in silent mode.
For non-default margins, use the same scaling as non-silent prints.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
fix: glitchy rendering and maximize behavior with different GTK themes (#50550)
* fix glitchy rendering with different gtk themes especially when maximizing
* use actual insets, not restored insets
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
ShowInvalidPrinterSettingsError() called TerminatePrintJob(true),
but when no print_job_ had been created yet (e.g. settings validation
failed before a job could start), TerminatePrintJob bails out
immediately without reaching ReleasePrintJob() where the callback
is invoked. This left the CompletionCallback stuck in callback_
until WebContents destruction, causing webContents.print() to only
fire its callback when the application closed.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
fix the appearance of transparent frameless and client frame windows
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
* remove comment based label removal
* ci: add functionality for programmatic add/remove needs-signed-commits label
* add new line to pull-request-opened-synchronized
The `OnTraceBufferUsageAvailable` callback creates V8 handles via
`Dictionary::CreateEmpty()` before `promise.Resolve()` enters its
`SettleScope` (which provides a `HandleScope`). When the callback
fires asynchronously from a Mojo response (i.e. when a trace session
is active), there is no `HandleScope` on the stack, causing a fatal
V8 error: "Cannot create a handle without a HandleScope".
Add an explicit `v8::HandleScope` at the top of the callback, matching
the pattern used by the other contentTracing APIs which resolve their
promises through `SettleScope` or the static `ResolvePromise` helper.
Made-with: Cursor
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Alexey Kozy <alexey@anysphere.co>
* build: enable V8 builtins PGO
Removes the gn arg that disabled V8 builtins profile-guided optimization
and adds a V8 patch to warn instead of abort when the builtin PGO profile
data does not match. Also strips the PGO-related flags from the generated
mksnapshot_args so they are not passed through to downstream mksnapshot
invocations.
Co-authored-by: Sam Attard <sattard@anthropic.com>
* docs: clarify Node.js async_hooks as reason for promise_hooks flag
Addresses review feedback: the v8_enable_javascript_promise_hooks flag
is set to support Node.js async_hooks, not used directly by Electron.
Co-authored-by: Sam Attard <sattard@anthropic.com>
* chore: update patches
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Sam Attard <sattard@anthropic.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
fix: register PrintDialogLinuxFactory on Linux
Chromium 145 refactored Linux print dialog creation to use a factory
pattern instead of directly calling LinuxUi::CreatePrintDialog().
Chrome registers this factory in
ChromeBrowserMainExtraPartsViewsLinux::ToolkitInitialized(), but
Electron did not, causing PrintingContextLinux::EnsurePrintDialog()
to leave print_dialog_ null on every call.
Without a dialog, UseDefaultSettings() and UpdatePrinterSettings()
return success but with empty/unprocessed settings, causing
PrintMsgPrintParamsIsValid() to fail. This broke both window.print()
(no dialog appears) and webContents.print() (callback stuck until
app close with "Invalid printer settings").
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* fix: fire AXMenuOpened event when a visible ARIA menu instance is added to the DOM
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
* fix: remove redundent FireMenuPopupEndForDeletedMenus
MENU_POPUP_END for deleted menus is already handled by
AXTreeManager::OnNodeWillBeDeleted, which
fires the event directly on the menu node before destruction.
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
* chore: add feature flag (kDynamicMenuPopupEvents)
Co-authored-by: Keeley Hammond <vertedinde@electronjs.org>
* chore: update patches
Co-authored-by: Keeley Hammond <vertedinde@electronjs.org>
* chore: update patches after trop
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
Co-authored-by: Keeley Hammond <vertedinde@electronjs.org>
Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
The frameNamesToWindow map was a holdover from the BrowserWindowProxy
IPC shim. Since nativeWindowOpen became the only code path, Blink's
FrameTree::FindOrCreateFrameForNavigation resolves named window targets
directly in the renderer, scoped to the opener's browsing context
group. When a matching named window exists, Blink navigates it without
ever sending a CreateNewWindow IPC to the browser, so this map was
never consulted in the legitimate same-opener case.
The only time the map found a match was when two unrelated renderers
happened to use the same target name, in which case openGuestWindow
would short-circuit before consuming the guest WebContents that
Chromium had already created for the new window, leaking it.
Adds a test verifying Blink handles same-opener named-target reuse
end-to-end without any browser-side tracking.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Sam Attard <sattard@anthropic.com>
* fix: hex-encode Windows notification icon temp filenames
NotificationPresenterWin was using SHA1HashString(origin.spec()) directly
as the basename for the temporary PNG written for toast icons.
SHA1HashString returns raw digest bytes, so the generated filename could
contain invalid path characters on Windows. That caused WriteFile to fail
when saving notification icons, which left toast XML without the expected
icon path.
Hex-encode the digest before appending .png so the temporary filename is
filesystem-safe while keeping deterministic naming for a given origin.
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* Update shell/browser/notifications/win/notification_presenter_win.cc
Co-authored-by: Robo <hop2deep@gmail.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
GetDefaultPrinterDPI() creates a blank GtkPrintSettings and reads
its resolution, which returns 0 for uninitialized settings. With
DPI=0, SetPrintableAreaIfValid() computes a zero scale factor,
producing empty page dimensions that fail PrintMsgPrintParamsIsValid().
Fall back to kDefaultPdfDpi (72) when GTK returns 0, matching the
existing Windows fallback pattern when CreateDC fails.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
The weak persistent tracking the OffscreenReleaseHolderMonitor was tied
to the texture object, but the release() closure holds a raw pointer to
the monitor via its v8::External data. If JS retained texture.release
while dropping the texture itself, the monitor would be freed on GC and
a later release() call would crash.
Track the release function instead of the texture object. Since the
texture holds release as a property, this keeps the monitor alive as
long as either is reachable.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Sam Attard <sattard@anthropic.com>
gfx::PNGCodec::Decode() returns a null SkBitmap when it fails to decode
the clipboard contents as a PNG. Passing that null bitmap to
gfx::Image::CreateFrom1xBitmap() triggers a crash.
Return an empty gfx::Image instead, matching the existing null-check
pattern in skia_util.cc.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Sam Attard <sattard@anthropic.com>
feat: add nativeTheme.shouldDifferentiateWithoutColor on macOS
Adds nativeTheme.shouldDifferentiateWithoutColor on macOS that maps to
NSWorkspace.accessibilityDisplayShouldDifferentiateWithoutColor. If true,
the user has indicated that they prefer UI that differentiates items with
something other than color alone. This is useful for users with color
vision deficiency.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Robert Böhnke <robb@robb.is>
* feat: support notification priority on Windows
Add Windows notifications support urgency/priority levels.
This maps the existing `urgency` option (previously Linux-only) to
Windows toast notification priorities:
- 'critical' maps to ToastNotificationPriority_High, which sorts the
notification above default-priority items in Action Center.
- 'normal' and 'low' both map to ToastNotificationPriority_Default.
Note that on Windows, 'critical' priority does not prevent the toast
from being auto-dismissed. Users should additionally set `timeoutType`
to 'never' for that behavior.
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* chore: make linter happy
Co-authored-by: Charles Kerr <charles@charleskerr.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
* fix: correct utility process exit code on Windows
On Windows, process exit codes are 32-bit unsigned integers (DWORD).
When passed from Chromium to Electron as a signed int and then
implicitly converted to uint64_t, values with the high bit set
(e.g., NTSTATUS codes) undergo sign extension, producing incorrect
values.
Cast the exit code to uint32_t before widening to uint64_t to
prevent sign extension and preserve the original Windows exit code.
Fixes#49455
Co-authored-by: João Silva <joaomrsilva@tecnico.ulisboa.pt>
* fix: narrow HandleTermination and Shutdown to uint32_t, add tests
Co-authored-by: João Silva <joaomrsilva@tecnico.ulisboa.pt>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: João Silva <joaomrsilva@tecnico.ulisboa.pt>
fix: improved the appearance of shadows and borders on frameless windows on Wayland (#50007)
* remove painting from linux frame layout
* use chromium csd strategy for frameless windows
* Apply suggestions from code review
Remove unneeded virtual methods
* removed inline destructors
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
fix: correctly set IsActive() in BaseWindow on MacOS
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Kyle Cutler <kycutler@microsoft.com>
Avoids a freeze when failing to enter fullscreen on macOS.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: John Beutner <beutner.john@gmail.com>
* docs: fix markdown formatting in fuses.md
* Use bulleted list (was being run together on one line)
* Wrap ASCII diagram in code block
Co-authored-by: Ryan Zimmerman <ryan@exodus.io>
* docs: apply suggestions from code review
Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
Co-authored-by: Erick Zhao <erick@hotmail.ca>
Co-authored-by: Ryan Zimmerman <ryan@exodus.io>
* docs: fix misapplied suggestion
Co-authored-by: Ryan Zimmerman <ryan@exodus.io>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Ryan Zimmerman <ryan@exodus.io>
Chromium added a top-level package.json in CL:7485999 that sets
the type to module and breaks commonjs tests run via
node-spec-runner.js. This commit temporarily changes the type to
commonjs while running the tests, then changes it back to module when done.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
docs: reorganize the comments for clarifying `webContents.setWindowOpenHandler` example
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: z0gSh1u <zx.cs@qq.com>
Upstream DevTools' HostRuntime checks `IS_NODE` before `IS_BROWSER` when
selecting the platform runtime. In Electron, `process` is available in
renderer processes, so `IS_NODE` evaluates to `true` in the DevTools
context. This causes DevTools to dynamically import the Node.js platform
runtime, which uses `node:worker_threads`. DevTools Web Workers running
under the `devtools://` protocol cannot load Node.js built-in modules,
so the import fails and breaks features like the formatter worker.
Fix by swapping the check order to prefer `IS_BROWSER` when both are
true. This is safe because in pure Node.js environments (the only case
where the node runtime is needed), `window` and `self` are both
undefined, so `IS_BROWSER` is always `false` regardless of check order.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
The update-patches artifact is a single .patch file, so zipping it
is unnecessary overhead. With archive: false, gh run download fetches
the raw file directly without requiring a decompression step.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
ci: upload patch conflict fix as artifact in apply-patches
When patch-up.js cannot auto-push the 3-way-merged patch diff (e.g. on
fork PRs), the checkout action already writes patches/update-patches.patch
and tells the user to check CI artifacts — but nothing was uploading it.
This adds the missing upload-artifact step to the apply-patches job so
the resolved diff is available for download, and documents in CLAUDE.md
that pulling this artifact and applying it with `git am` is the fast
path for fixing patch conflicts on PR branches without a full local sync.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
* fix: preserve staged update dir when pruning orphaned update dirs on macOS
The previous squirrel.mac patch cleaned up all staged update directories
before starting a new download. This kept disk usage bounded but broke
quitAndInstall() if called while a subsequent checkForUpdates() was in
flight — the already-staged bundle would be deleted out from under it.
This reworks the patch to read ShipItState.plist and preserve the
directory it references, deleting only truly orphaned update.XXXXXXX
directories. Disk footprint stays bounded (at most 2 dirs: staged +
in-progress) and quitAndInstall() remains safe mid-check.
Also adds test coverage for the quitAndInstall/checkForUpdates race and
a triple-stack scenario where 3 updates arrive without a restart.
Refs https://github.com/electron/electron/issues/50200
Co-authored-by: Samuel Attard <sattard@anthropic.com>
* chore: update patches
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
* fix: prevent traffic light buttons flashing on deminiaturize
When a window with a custom `trafficLightPosition` is minimized and
restored, macOS re-layouts the title bar container during the
deminiaturize animation, causing the traffic light buttons to briefly
appear at their default position before being repositioned.
Fix this by hiding the buttons container in `windowWillMiniaturize` and
restoring them (with a redraw to the correct position) in
`windowDidDeminiaturize`.
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* chore: address feedback from review
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
docs: update linux frameless window docs to account for hasShadow:false
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: George Xu <george.xu@slack-corp.com>
fix: bind offscreen paint callback to child WebContents
Previously, MaybeOverrideCreateParamsForNewWindow bound the
OffScreenWebContentsView's paint callback to the parent WebContents
using base::Unretained(this). This was both unsafe (dangling pointer
risk if the parent is destroyed before the child) and semantically
incorrect — paint events belong to the child window, not the opener.
Replace the callback in MaybeOverrideCreateParamsForNewWindow with
base::DoNothing(), then rebind it to the child WebContents in
AddNewContents via a new SetCallback method on OffScreenWebContentsView.
- POSIX: validate StringToSizeT result and token count when splitting
the socket message into argv and additionalData; previously a
malformed message could produce incorrect slicing.
- Windows: base64-encode additionalData before embedding in the
null-delimited wchar_t buffer. The prior reinterpret_cast approach
dropped everything after the first aligned 0x0000 in the serialized
payload, so complex objects could arrive truncated.
Manually backported from #50119
* fix: read nodeIntegrationInWorker from per-frame WebPreferences
Previously the renderer checked a process-wide command-line switch to
decide whether to create a Node.js environment for dedicated workers.
When a renderer process hosted multiple WebContents with different
nodeIntegrationInWorker values (e.g. via window.open with overridden
webPreferences in setWindowOpenHandler), all workers in the process
used whichever value the first WebContents set on the command line.
Instead, plumb the flag through blink's WorkerSettings at worker
creation time, copying it from the initiating frame's WebPreferences.
The check on the worker thread then reads the per-worker value. Nested
workers inherit the flag from their parent worker via
WorkerSettings::Copy.
The --node-integration-in-worker command-line switch is removed as it
is no longer consumed.
Co-authored-by: Samuel Attard <sattard@anthropic.com>
* chore: update patches
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
fix: validate protocol scheme names in setAsDefaultProtocolClient
On Windows, `app.setAsDefaultProtocolClient(protocol)` directly
concatenates the protocol string into the registry key path with no
validation. A protocol name containing `\` could write to an arbitrary
subkey under `HKCU\Software\Classes\`, potentially hijacking existing
protocol handlers.
To fix this, add `Browser::IsValidProtocolScheme()` which validates that a protocol
name conforms to the RFC 3986 scheme grammar:
scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
This rejects backslashes, forward slashes, whitespace, and any other
characters not permitted in URI schemes.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* fix: use requesting frame origin instead of top-level URL for permissions
`WebContentsPermissionHelper::RequestPermission` passes
`web_contents_->GetLastCommittedURL()` as the origin to the permission
manager instead of the actual requesting frame's origin. This enables
origin confusion when granting permissions to embedded third-party iframes,
since app permission handlers see the top-level origin instead of the
iframe's. The same pattern exists in the HID, USB, and Serial device
choosers, where grants are keyed to the primary main frame's origin rather
than the requesting frame's.
Fix this by using `requesting_frame->GetLastCommittedOrigin()` in all
affected code paths, renaming `details.requestingUrl` to
`details.requestingOrigin`, and populating it with the serialized
origin only.
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* chore: keep requestingUrl name in permission handler details
The previous commit changed the details.requestingUrl field to
details.requestingOrigin in permission request/check handlers. That
field was already populated from the requesting frame's RFH, so the
rename was unnecessary and would break apps that read the existing
property. Revert to requestingUrl to preserve the existing API shape.
The functional changes to use the requesting frame in
WebContentsPermissionHelper and the HID/USB/Serial choosers remain.
Co-authored-by: Samuel Attard <sattard@anthropic.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
Matches the existing validation applied to request headers in
electron_api_url_loader.cc.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
git format-patch honors diff.renames, which defaults to 'true' (rename
detection only). If a user has diff.renames=copies configured at the
system or global level, exported patches may encode new files as copies
of similar existing files, causing spurious diffs against patches
exported on other machines. Pin diff.renames=true to match git's
default.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
The sender-mismatch check in invokeInWebContents and invokeInWebFrameMain
used a negative condition (`type === 'frame' && sender !== expected`),
which only rejected mismatched frame senders and accepted anything else.
Invert to a positive check so only the exact expected frame can resolve
the reply — matches the guard style used elsewhere in lib/browser/.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
* docs: document that getCursorScreenPoint() needs a Window on Wayland
Co-authored-by: Charles Kerr <charles@charleskerr.com>
* feat: add IsWayland() helper
Co-authored-by: Charles Kerr <charles@charleskerr.com>
* fix: Wayland crash in GetCursorScreenPoint()
fix: support Screen::GetCursorScreenPoint() on X11
Co-authored-by: Charles Kerr <charles@charleskerr.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
fix: delete temporary blink* globals after restoring Blink implementations (#49991)
ElectronRendererClient::DidCreateScriptContext (and the worker
equivalent) save Blink's fetch/Response/FormData/Request/Headers/
EventSource as temporary globalThis.blink* properties before Node
initialization may overwrite them. node/init.ts and worker/init.ts
restore the originals but previously never deleted the temporary
blink* globals.
They persisted as non-standard global pollution visible to page
content when contextIsolation is disabled -- a minor fingerprinting
signal and a bypass for any preload that wraps window.fetch (page
could call blinkfetch() instead).
Co-authored-by: Samuel Attard <sam@electronjs.org>
PowerMonitor registered OS-level callbacks (HWND UserData and
WTS/suspend notifications on Windows, shutdown handler and lock-screen
observer on macOS) but never cleaned them up in its destructor. The JS
layer also only held the native object in a closure-local variable,
allowing GC to reclaim it while those registrations still referenced
freed memory.
Retain the native PowerMonitor at module level in power-monitor.ts so
it cannot be garbage-collected. Add DestroyPlatformSpecificMonitors()
to properly tear down OS registrations on destruction: on Windows,
unregister WTS and suspend notifications, clear GWLP_USERDATA, and
destroy the HWND; on macOS, remove the emitter from the global
MacLockMonitor and reset the Browser shutdown handler.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
these variables hit with-Werror,-Wunused when printing is disabled
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
Previously, GetProtocolLaunchPath and FormatCommandLineString in
browser_win.cc used naive quoting which could break when paths or
arguments contained backslashes, spaces, or embedded quotes.
Fix by extracting the CommandLineToArgvW-compatible quoting logic from
relauncher_win.cc into a shared utility and use it in both browser_win.cc
and relauncher_win.cc to properly quote the exe path and each argument
individually.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* fix: set default desktop name that matches exec name on linux
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
* chromium patches for global shortcuts
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
* use app name for shortcut description
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
* chore: fixup .patches after trop
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
Previously, when trashItemAtURL: failed (e.g. on network shares or
under app translocation), the code fell back to constructing an
AppleScript that interpolated the bundle path directly into a string
literal via %@ with no escaping. This was fragile and unnecessary —
trashItemAtURL: has been the standard API since 10.8 and covers the
relevant cases. The fix simply removes the AppleScript fallback
entirely, so Trash() now returns the result of trashItemAtURL: directly.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Previously, UsbChooserController::OnDeviceChosen looked up the chosen
device_id via chooser_context_->GetDeviceInfo(), which searches all
known USB devices on the system rather than the filtered list shown to
the select-usb-device handler. This meant a device excluded by the
renderer's filters or exclusion_filters could still be granted
permission if the handler returned its GUID.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Enter the destination context scope before creating the VideoFrame V8
wrapper, matching the sibling Element and Blob branches. Without this,
ScriptState::ForCurrentRealm resolved to the calling context instead of
the target context, producing an incorrect wrapper.
Also switch to ScriptState::From with an explicit context argument to
make the intent clearer.
Adds spec coverage for VideoFrame crossing the bridge in both
directions and adds VideoFrame to the existing prototype checks.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
The setter branch was deriving source_context from getter-> instead of
setter->. Currently latent since the only call site passes both from
the same preload context, but this would crash or mis-resolve if a
future call site passed a setter without a getter or from a different
context.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
EnterFullscreenModeForTab, RequestPointerLock, and RequestKeyboardLock
bind callbacks with base::Unretained(this); fullscreen also captures a
raw RenderFrameHost*. These callbacks may be invoked by the app's JS
permission handler after the WebContents or RenderFrameHost is destroyed.
Use GetWeakPtr() in all three call sites, and capture a
GlobalRenderFrameHostToken instead of the raw RenderFrameHost* for
fullscreen so the pointer is resolved and null-checked only when the
callback fires. Cancel in-flight permission requests from ~WebContents()
via a new ElectronPermissionManager::CancelPendingRequests()` so stale
callbacks are never handed back to JS.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
fix: authenticate curl requests to googlesource in lint workflow
The "Download GN Binary" and "Download clang-format Binary" steps
fetch files from chromium.googlesource.com without passing
authentication cookies. When googlesource rate-limits or returns a
transient error (502), the HTML error page is piped into `base64 -d`,
causing `base64: invalid input`.
The `set-chromium-cookie` action already configures `~/.gitcookies`
in a prior step. Pass `-b ~/.gitcookies` to both `curl` calls so
they authenticate, matching what the cookie verification step itself
does.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* test: add failing test for `setFullscreen(false)`
`setFullscreen(false)` should do nothing
when not already in fullscreen, but it hides the menu bar
on Linux.
Co-authored-by: WofWca <wofwca@protonmail.com>
* fix: menu bar hiding on two setFullScreen(false)
This fixes the following bug on Linux (and maybe macOS):
1. Create a window with a menu bar.
2. Call `win.setFullScreen(false)`.
The menu bar will hide.
See the original bug in our project:
https://github.com/deltachat/deltachat-desktop/issues/4752.
Co-authored-by: WofWca <wofwca@protonmail.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: WofWca <wofwca@protonmail.com>
fix: update label/sublabel/icon in macOS item on open
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
fix: correct window sizing on Linux when constraints on resizability are enforced (#49903)
* fix window sizing on linux when constraints are applied
* added tests
* apply window style directly when changing resizability
* Revert "apply window style directly when changing resizability"
This reverts commit 949e2ee2ab.
* set size constraints for resizability on window and linux
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
* chore: bump chromium in DEPS to 146.0.7680.31
* chore: update patches
* fix(patch-conflict): adapt MacWebContentsOcclusion for version check removal
Upstream removed the manualOcclusionDetectionSupportedForCurrentMacOSVersion
check, now always initializing occlusion detection. Adapted patch to keep
the feature flag gate around the simplified initialization code.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7602735
* fix(patch-update): patch out GLIC Summarize in pdf_extension_util
Upstream added a Glic summarize button feature in pdf_extension_util.cc.
The new ShouldShowGlicSummarizeButton() function uses Profile::FromBrowserContext
and glic::GlicEnabling which are not available in Electron builds.
Wrapped the ENABLE_GLIC code block in #if 0 to disable it.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7596305
---------
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
feat: Shadows and CSD for frameless windows on Wayland (#49295)
* fix window sizing and content sizing on Linux when CSD is in use
* fixed size constraints
* layout helper
* CSD shadows for frameless windows on Linux
* simplify min/max size calculation
* use base window size for min/max
* respect HasShadow option
* moved windows min/max size overrides
* add newline at end of file
* fix setting background color for frameless csd windows
* fix wco positioning nad sizing to match prod
* safety improvements
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
fix: apply zoomFactor from setWindowOpenHandler to window.open() windows
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Inside gtk_util::GdkPixbufFromSkBitmap, g_bytes_new() was called
inline as an argument to gdk_pixbuf_new_from_bytes(), which per
GTK docs does not take ownership of the GBytes - it adds its own
internal reference. The caller's GBytes* was never stored or
unreffed, leaking 4 x width x height bytes of pixel data on every
call.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: redeemer <marcin.probola@gmail.com>
* build: lint commits on Chromium roller branches
Assisted-By: Claude Opus 4.5
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
* chore: add ability to skip linting CLs by adding #nolint
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
* chore: only exit with non-zero exit code in CI
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
* docs: clarify ASAR integrity is supported in MAS builds
Add a note to the ASAR integrity documentation explicitly stating
that this feature is fully supported and recommended in Mac App
Store builds. While MAS-installed apps have system-level protections,
ASAR integrity provides an additional security layer and is important
for MAS builds distributed outside the Mac App Store.
Slack thread: https://electronhq.slack.com/archives/CB6CG54DB/p1771449093872419?thread_ts=1771446183.473289&cid=CB6CG54DBhttps://claude.ai/code/session_01A97nfiqHUVxLNaQyHVXS7j
Co-authored-by: Claude <noreply@anthropic.com>
* docs: clarify ASAR integrity support for MAS builds
Updates the ASAR integrity documentation to explicitly mention that
it is supported and recommended in Mac App Store builds. Clarifies
that while MAS-installed apps have system-level protections (Resources
folder owned by root), ASAR integrity is especially important when
distributing MAS builds through other channels like direct download,
since those installations won't have the read-only protections.
https://claude.ai/code/session_012mBNZQW34h91NRcdFaLxNh
Co-authored-by: Claude <noreply@anthropic.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
fix: accurate window sizing and support for content sizing on Linux/Wayland with CSD (#49209)
* fix window sizing and content sizing on Linux when CSD is in use
* fixed size constraints
* simplify min/max size calculation
* use base window size for min/max
* moved windows min/max size overrides
* remove unnecessary checks for client frame
* cleanup
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
fix: enable WASM trap handlers in all Node.js processes
```
Original reason for revert:
Some apps started throwing exception on startup
https://github.com/electron/electron/issues/48956
```
We now move the trap handler registeration before
any user script execution. Add a fuse to support
disabling the feature is application needs to run
in memory constrained environments.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
* chore: bump chromium in DEPS to 146.0.7653.0
* chore: bump chromium in DEPS to 146.0.7653.1
* chore: bump chromium in DEPS to 146.0.7655.0
* chore: bump chromium in DEPS to 146.0.7657.1
* chore: bump chromium in DEPS to 146.0.7659.0
* chore: bump chromium in DEPS to 146.0.7661.0
* chore: bump chromium in DEPS to 146.0.7663.1
* chore: bump chromium in DEPS to 146.0.7665.1
* chore: bump chromium in DEPS to 146.0.7667.1
* chore: bump chromium in DEPS to 146.0.7668.2
* chore: bump chromium in DEPS to 146.0.7670.0
* chore: bump chromium in DEPS to 146.0.7672.1
* chore: bump chromium in DEPS to 146.0.7674.1
* chore: bump chromium in DEPS to 146.0.7676.1
* chore: bump chromium in DEPS to 146.0.7678.1
* chore: bump chromium in DEPS to 146.0.7680.1
* chore: bump chromium in DEPS to 146.0.7680.4
* chore: bump chromium in DEPS to 146.0.7680.0
* chore: bump chromium to 146.0.7666.0 (main) (#49528)
* chore: bump chromium in DEPS to 146.0.7652.0
* fix(patch-conflict): update mas_avoid_private_macos_api_usage context for constrainFrameRect method
The upstream CL added a new constrainFrameRect:toScreen: method override to
NativeWidgetMacNSWindow as part of headless mode window zoom implementation.
The MAS patch's #endif for frameViewClassForStyleMask now correctly appears
after that method, since constrainFrameRect is a public API override that
doesn't need to be guarded.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7487666
* fix(patch-conflict): update printing.patch for base::DictValue rename
Updated printing.patch to use the new base::DictValue type name instead of
base::Value::Dict following Chromium's type renaming change. This affects
CompleteUpdatePrintSettings() signature and related code.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7509820
* fix(patch-conflict): update accessibility_ui patch for base::DictValue/ListValue rename
Updated adjust_accessibility_ui_for_electron.patch to use the new
base::DictValue and base::ListValue type names instead of base::Value::Dict
and base::Value::List following Chromium's type renaming change.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7509820
* chore: update patches
* 6625736: Rename DURABLE_STORAGE to PERSISTENT_STORAGE for consistency | https://chromium-review.googlesource.com/c/chromium/src/+/6625736
* chore: bump chromium in DEPS to 146.0.7653.0
* chore: update patches
* 7000847: add type tag to v8::External for gin_helper function templates
The upstream gin function templates now use v8::ExternalPointerTypeTag
for type safety when using v8::External. Updated Electron's forked
gin_helper function template to use the same kGinInternalCallbackHolderBaseTag
that Chromium's gin uses.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7000847
* fix(patch-update): extend V8 Object API deprecation patch for Node.js
Extended the existing patch to cover additional files that use
GetAlignedPointerFromInternalField and SetAlignedPointerInInternalField:
- src/stream_base-inl.h
- src/udp_wrap.cc
- src/js_udp_wrap.cc
- src/node_process_methods.cc
- src/node_snapshotable.cc
- src/base_object.cc
These APIs now require an EmbedderDataTypeTag parameter.
Ref: https://chromium-review.googlesource.com/c/v8/v8/+/7087956
* 7000847: add type tag to v8::External calls in shared_texture
Updated v8::External::New and v8::External::Value calls to use the
kExternalPointerTypeTagDefault tag as required by the V8 API change
that deprecates the tagless versions.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7000847
* 7508687: use ChildProcessId for file permission APIs
The ChildProcessSecurityPolicy::CanReadFile and GrantReadFile APIs
now require ChildProcessId instead of int. Updated to use GetID()
instead of GetDeprecatedID() for these specific calls.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7508687
* 7000847: add type tag to v8::External calls in callback and osr_converter
The v8::External API now requires an EmbedderPointerTypeTag parameter
for both New() and Value() methods to improve V8 sandbox type safety.
Updated calls in:
- callback.cc: TranslatorHolder constructor and CallTranslator
- osr_converter.cc: OffscreenSharedTextureValue converter
Ref: https://chromium-review.googlesource.com/c/v8/v8/+/7000847
* fixup! 7087956: [api] Promote deprecation of v8::Context and v8::Object API methods
Extended the Node.js patch to cover histogram.cc which also uses
SetAlignedPointerInInternalField and GetAlignedPointerFromInternalField
APIs that now require the EmbedderDataTypeTag parameter.
Ref: https://chromium-review.googlesource.com/c/v8/v8/+/7087956
* chore: bump chromium in DEPS to 146.0.7655.0
* chore: update patches
* 7509043: update WebSpellingMarker type for API change
The upstream Chromium API changed - WebSpellingMarker was moved from a
nested type within WebTextCheckClient to a standalone type in the blink
namespace.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7509043
* 7498491: update process_id to use OriginatingProcess type
The upstream Chromium API changed - URLLoaderFactoryParams::process_id
was changed from an integer to a union type network::OriginatingProcess
that distinguishes between browser and renderer processes.
- For browser process requests, use OriginatingProcess::browser()
- For renderer process lookups, check !is_browser() and use
renderer_process().value() to get the child_id
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7498491
* 5710330: Add crash keys to debug NativeWidgetMacNSWindowBorderlessFrame exception | https://chromium-review.googlesource.com/c/chromium/src/+/5710330
5710330 added a new NSNextStepFrame interface extension and
implementations for NativeWidgetMacNSWindowTitledFrame and
NativeWidgetMacNSWindowBorderlessFrame. These use private macOS APIs
that are not available in Mac App Store builds.
* chore: update patches
* chore: bump chromium in DEPS to 146.0.7661.0
* chore: bump chromium in DEPS to 146.0.7663.0
* fix(patch-conflict): update accessibility_ui for string_view API change
Upstream removed redundant std::string(default_api_type) conversion as part
of a string_view optimization cleanup. Updated patch context to match.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7514107
* fix(patch-conflict): update service process launch options for sandbox API refactor
Upstream removed content/common/sandbox_init_win.cc and
content/public/common/sandbox_init_win.h, moving the functionality directly
into ChildProcessLauncherHelper. Updated patch to call
sandbox::policy::SandboxWin::StartSandboxedProcess directly with the
LaunchOptions pointer instead of going through the removed helper.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7528253
* fix(patch-conflict): update MAS safestorage for keychain API refactor
Upstream refactored KeychainPassword::GetPassword() to use a new
GetPasswordImpl() helper function with improved error tracking via
base::expected<std::string, OSStatus>. Adapted patch to use the new
GetPasswordImpl with the suffixed account name and handle migration
from legacy accounts through the new API.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7516438
* chore: update patches
* chore: bump chromium in DEPS to 146.0.7663.0
* fix: base::Value::Dict -> base::DictValue
https://chromium-review.googlesource.com/c/chromium/src/+/7513889
* fix: include new cookie exclusion reason
https://chromium-review.googlesource.com/c/chromium/src/+/7486527
* fix: enable libc++ ABI flag for trivially copyable std::vector<bool>
Required for changes introduced in the following CL
https://chromium-review.googlesource.com/c/chromium/src/+/7513653
* fixup! fix: base::Value::Dict -> base::DictValue https://chromium-review.googlesource.com/c/chromium/src/+/7513889
* fix: spellcheck not working in tests
https://chromium-review.googlesource.com/c/chromium/src/+/7452579
* fix: cookie test failing due to multiple rejection reasons
https://chromium-review.googlesource.com/c/chromium/src/+/7506629
* fix: macos sizing unmaximized window incorrectly
https://chromium-review.googlesource.com/c/chromium/src/+/7487666
Changes to headless mode caused the unmaximized window to subtract
the height of the menubar.
* fix: skip tests for incompatible BoringSSL ML-DSA crypto
https://boringssl-review.googlesource.com/c/boringssl/+/84929
* test: fix pseudonymization registration in utility process on Linux
Ref: 7486913: Pass pseudonymization salt via shared memory at process launch | https://chromium-review.googlesource.com/c/chromium/src/+/7486913
* fix: restore MAS patch-outs
Restores some `#if !IS_MAS_BUILD()` gates dropped in 773054ad59
* fixup! 7508687: use ChildProcessId for file permission APIs
* fixup! fix(patch-conflict): update MAS safestorage for keychain API refactor
* chore: add note about parallel upstream change
* fixup! Merge remote-tracking branch 'origin/main' into roller/chromium/main
* Revert "fixup! 7508687: use ChildProcessId for file permission APIs"
This reverts commit 05c43e4e5d.
The _impl version has the signature, but not the public interface. :oof:
* fixup! fix(patch-conflict): update MAS safestorage for keychain API refactor
---------
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
Co-authored-by: Samuel Maddock <samuelmaddock@electronjs.org>
Co-authored-by: clavin <clavin@electronjs.org>
(cherry picked from commit a65cfed500)
* chore: update patches after rebase
---------
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
Co-authored-by: Samuel Maddock <samuelmaddock@electronjs.org>
Co-authored-by: clavin <clavin@electronjs.org>
Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
* Revert "fix: fix Windows MSIX release build errors (#49613)"
This reverts commit 4b5d5f9dd5.
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
* refactor: use WRL ComPtr pattern for MSIX to avoid exception handling
The MSIX auto-updater code was using C++/WinRT (winrt::* namespace), which requires exception handling (/EHsc). Mixing exception and non-exception handling code in the same binary is problematic at runtime. This commit refactors electron_api_msix_updater.cc to use an upstream Chromium pattern and eliminates the need for special exception handling build flags
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
* build: import correct packages
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
* build: consolidate IPackage declarations
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
* refactor: use IPackageManager/IPackageManager5/IPackageManager9 and IPackage/IPackage2/IPackage4/IPackage6 interfaces as needed for different API methods.
Also consolidates duplicate completion handler logic, fixes a bug in
RegisterRestartOnUpdate where the command line string could go out of
scope, and removes unused includes.
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
fix: clean up old staged updates before downloading new update
When checkForUpdates() is called while an update is already staged,
Squirrel creates a new temporary directory for the download without
cleaning up the old one. This can lead to disk usage growth when
new versions are released while the app hasn't restarted.
This adds a force parameter to pruneUpdateDirectories that bypasses
the AwaitingRelaunch state check. This is called before creating a
new temp directory, ensuring old staged updates are cleaned up.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Andy Locascio <loc@anthropic.com>
Refs https://chromium-review.googlesource.com/6880247
Fixes a crash that can arise in the File System Access API in the
following scenario:
1. Create fileHandle1 at path1.
2. Call fileHandle1.remove() or user manually delete the file.
3. Create fileHandle2 at path2.
4. fileHandle2.move(path1).
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
chore: bump chromium to 146.0.7650.0 41-x-y
* chore: bump chromium in DEPS to 146.0.7650.0
* 7496671: WaaP: Control hung delay for Initial WebUI
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7496671
* 7494302: [//media] Rename renderable_gpu_memory_buffer_video_frame_pool*
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7494302
* chore: update patches
* 7502996: [DevTools] Add ability to toggle Chromium feature flags from DevTools
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7502996
* 7456200: Vectorize StringImpl::CopyChars and EqualIgnoringASCIICase using Highway.
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7456200
* 7236627: spellcheck: supply full spelling marker info, incld. marker type
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7236627
* chore: rm dependency on wtf::string from blink public headers
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7456200
added a public dependency on //third_party/highway for
//third_party/blink/renderer/platform/wtf:wtf which will not be
inherited by //content/renderer since wtf is internal dependency of
blink leading to the following compilation error
```
In file included from ../../content/public/renderer/window_features_converter.cc:5:
In file included from ../../content/public/renderer/window_features_converter.h:10:
In file included from ../../third_party/blink/public/web/web_window_features.h:38:
In file included from ../../third_party/blink/renderer/platform/wtf/text/wtf_string.h:40:
../../third_party/blink/renderer/platform/wtf/text/string_impl.h:27:10: fatal error: 'hwy/highway.h' file not found
27 | #include <hwy/highway.h>
| ^~~~~~~~~~~~~~~
1 error generated.
```
Use `gn desc out/Testing content/renderer:renderer_sources --blame`
to verify the inherited config and dependency list.
* 7493995: Restore directive part of wasm-eval error message
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7493995
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
* docs: add type reference links in Menu and MenuItem API documentation
Co-authored-by: Sourav Bera <sbera987654321@gmail.com>
* docs: revert type links in Menu return types to fix parser
Co-authored-by: Sourav Bera <sbera987654321@gmail.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Sourav Bera <sbera987654321@gmail.com>
fix: second argument to shell.writeShortcutLink is optional
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
fix: return early from beep on linux if there is no default gdk display
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Noah Gregory <noahmgregory@gmail.com>
docs: Update shell.md: Document that shell.trashItem requires backslashes
In Windows many functions relating to files (e.g. shell.openItem, the Node fs functions, as well as native Win32 APIs) will accept either type of slash / or \ as a folder separator.
shell.trashItem does not work with / as folder separator in Windows. This documentation change explains that.
See also:
https://github.com/electron/electron/issues/28831
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: sam marshall <s.marshall@open.ac.uk>
description: Guide for performing Node.js version upgrades in the Electron project. Use when working on the roller/node/main branch to fix patch conflicts during `e sync --3`. Covers the patch application workflow, conflict resolution, analyzing upstream Node.js changes, building, running the Node.js test suite, and proper commit formatting for patch fixes.
---
# Electron Node.js Upgrade: Phase One
## Summary
Run `e sync --3` repeatedly, fixing patch conflicts as they arise, until it succeeds. Then export patches and commit changes atomically.
## Success Criteria
Phase One is complete when:
-`e sync --3` exits with code 0 (no patch failures)
- All changes are committed per the commit guidelines
Do not stop until these criteria are met.
**CRITICAL** Do not delete or skip patches unless 100% certain the patch is no longer needed. For major version upgrades, patches that shim deprecated V8 APIs or backport upstream changes are often deletable because the new Node.js version already incorporates them — but verify before removing. Complicated conflicts or hard to resolve issues should be presented to the user after you have exhausted all other options. Do not delete the patch just because you can't solve it.
**CRITICAL** Never use `git am --skip` and then manually recreate a patch by making a new commit. This destroys the original patch's authorship, commit message, and position in the series. If `git am --continue` reports "No changes", investigate why — the changes were likely absorbed by a prior conflict resolution's 3-way merge. Present this situation to the user rather than skipping and recreating.
## Context
The `roller/node/main` branch is created by automation to update Electron's Node.js dependency version in `DEPS`. No work has been done to handle breaking changes between the old and new versions.
There are two types of Node.js version updates:
- **Bumps** (patch/minor): Automated by `electron-roller[bot]` with commit title `chore: bump node to v{version}`. Trivial patch index updates are handled automatically by `patchup[bot]`. These often land cleanly, but may require manual patch fixes.
- **Major upgrades** (e.g., v22 → v24): Manual, large PRs with commit title `chore: upgrade Node.js to v{X}.{Y}.{Z}`. These typically involve deleting obsolete patches, adapting many others, and updating `@types/node` in `package.json`.
**Key directories:**
- Current directory: Electron repo (always run `e` commands here)
-`docs/development/patches.md`: Patch system documentation
## Pre-flight Checks
Run these once at the start of each upgrade session:
1.**Clear rerere cache** (if enabled): `git rerere clear` in both the electron and `../third_party/electron_node` repos. Stale recorded resolutions from a prior attempt can silently apply wrong merges.
2.**Ensure pre-commit hooks are installed**: Check that `.git/hooks/pre-commit` exists. If not, run `yarn husky` to install it. The hook runs `lint-staged` which handles clang-format for C++ files.
## Workflow
1. Run `e sync --3` (the `--3` flag enables 3-way merge, always required)
2. If succeeds → skip to step 5
3. If patch fails:
- Identify target repo and patch from error output
- Analyze failure (see references/patch-analysis.md)
- Fix conflict in `../third_party/electron_node` working directory
- Run `git am --continue` in `../third_party/electron_node`
- Repeat until all patches for that repo apply
- IMPORTANT: Once `git am --continue` succeeds you MUST run `e patches node` to export fixes
- Return to step 1
4. When `e sync --3` succeeds, run `e patches all`
5.**Read `references/phase-one-commit-guidelines.md` NOW**, then commit changes following those instructions exactly.
## Commands Reference
| Command | Purpose |
|---------|---------|
| `e sync --3` | Clone deps and apply patches with 3-way merge |
| `git am --continue` | Continue after resolving conflict (run in node repo) |
| `e patches node` | Export commits from node repo to patch files |
| `e patches all` | Export all patches from all targets |
| Creating new patch (rare, avoid) | Commit in node repo, then `e patches node` |
Fix existing patches 99% of the time rather than creating new ones.
## Patch Fixing Rules
1.**Preserve authorship**: Keep original author in TODO comments (from patch `From:` field)
2.**Never change TODO assignees**: `TODO(name)` must retain original name
3.**Update descriptions**: If upstream changed APIs or macros, update patch commit message to reflect current state
4.**Never skip-and-recreate a patch**: If `git am --continue` says "No changes — did you forget to use 'git add'?", do NOT run `git am --skip` and create a replacement commit. The patch's changes were already absorbed by a prior 3-way merge resolution. This means an earlier conflict resolution pulled in too many changes. Present the situation to the user for guidance — the correct fix may require re-doing an earlier resolution more carefully to keep each patch's changes separate.
# Electron Node.js Upgrade: Phase Two
## Summary
Run `e build -k 999 -- --quiet` repeatedly, fixing build issues as they arise, until it succeeds. Then run `e start --version` to validate Electron launches and commit changes atomically.
Run Phase Two immediately after Phase One is complete.
## Success Criteria
Phase Two is complete when:
-`e build -k 999 -- --quiet` exits with code 0 (no build failures)
-`e start --version` has been run to check Electron launches
- All changes are committed per the commit guidelines
Do not stop until these criteria are met. Do not delete code or features, never comment out code in order to take short cut. Make all existing code, logic and intention work.
## Context
The `roller/node/main` branch is created by automation to update Electron's Node.js dependency version in `DEPS`. No work has been done to handle breaking changes between the old and new versions. Node.js APIs (especially internal V8 integration, OpenSSL/BoringSSL compatibility, and build system files) frequently change between versions. In every case the code in Electron must be updated to account for the change in Node.js, strongly avoid making changes to the code in Node.js to fix Electron's build.
**Key directories:**
- Current directory: Electron repo (always run `e` commands here)
-`../third_party/electron_node`: Node.js repo (do not touch this code to fix build issues, just read it to obtain context)
## Workflow
1. Run `e build -k 999 -- --quiet` (the `--quiet` flag suppresses per-target status lines, showing only errors and the final result)
2. If succeeds → skip to step 6
3. If build fails:
- Identify underlying file in "electron" from the compilation error message
- Analyze failure
- Fix build issue by adapting Electron's code for the change in Node.js
- Run `e build -t {target_that_failed}.o` to build just the failed target we were specifically fixing
- You can identify the target_that_failed from the failure line in the build log. E.g. `FAILED: 2e506007-8d5d-4f38-bdd1-b5cd77999a77 "./obj/electron/shell/browser/api/electron_api_utility_process.o" CXX obj/electron/shell/browser/api/electron_api_utility_process.o` the target name is `obj/electron/shell/browser/api/electron_api_utility_process.o`
- **Read `references/phase-two-commit-guidelines.md` NOW**, then commit changes following those instructions exactly.
- Return to step 1
4.**CRITICAL**: After ANY commit (especially patch commits), immediately run `git status` in the electron repo
- Look for other modified `.patch` files that only have index/hunk header changes
- These are dependent patches affected by your fix
6. When `e build` succeeds, run `e start --version`
7. Check if you have any pending changes in the Node.js repo by running `git status` in `../third_party/electron_node`
- If you have changes follow the instructions below in "A. Patch Fixes" to correctly commit those modifications into the appropriate patch file
## Commands Reference
| Command | Purpose |
|---------|---------|
| `e build -k 999 -- --quiet` | Build Electron, continue on errors, suppress status lines |
| `e build -t {target}.o` | Build just one specific target to verify a fix |
| `e start --version` | Validate Electron launches after successful build |
## Two Types of Build Fixes
### A. Patch Fixes (for files in patched Node.js files)
When the error is in a file that Electron patches (check with `grep -l "filename" patches/node/*.patch`):
1. Edit the file in the Node.js source tree (`../third_party/electron_node/...`)
2. Create a fixup commit targeting the original patch commit:
```bash
cd ../third_party/electron_node
git add <modified-file>
git commit --fixup=<original-patch-commit-hash>
GIT_SEQUENCE_EDITOR=: git rebase --autosquash --autostash -i <commit>^
```
3. Export the updated patch: `e patches node`
4. Commit the updated patch file following `references/phase-one-commit-guidelines.md`.
To find the original patch commit to fixup: `git log --oneline | grep -i "keyword from patch name"`
The base commit for rebase is the Node.js commit before patches were applied. Find it by checking the `refs/patches/upstream-head` ref.
### B. Electron Code Fixes (for files in shell/, electron/, etc.)
When the error is in Electron's own source code:
1. Edit files directly in the electron repo
2. Commit directly (no patch export needed)
# Electron Node.js Upgrade: Phase Three
## Summary
Run the Node.js test suite via `script/node-spec-runner.js`, fix failing tests, and commit fixes until all tests pass. Certain tests are permanently disabled (listed in `script/node-disabled-tests.json`) and should not be run.
Run Phase Three immediately after Phase Two is complete.
## Success Criteria
Phase Three is complete when:
- `node script/node-spec-runner.js --default` exits with zero failures
- All changes are committed per the commit guidelines
Do not stop until these criteria are met.
## Context
Electron runs a subset of Node.js's upstream test suite using a custom runner (`script/node-spec-runner.js`). Tests are executed with the built Electron binary via `ELECTRON_RUN_AS_NODE=true`. Many tests need adaptation because Electron uses BoringSSL (not OpenSSL) and Chromium's V8 (which may differ from Node.js's bundled V8).
**Key files:**
- `script/node-spec-runner.js` — Test runner script
- `script/node-disabled-tests.json` — Permanently disabled tests (do not try to fix these)
- `../third_party/electron_node/test/` — Node.js test files (where patches apply)
- `patches/node/fix_crypto_tests_to_run_with_bssl.patch` — BoringSSL crypto test adaptations
- `patches/node/test_formally_mark_some_tests_as_flaky.patch` — Flaky test list
## Workflow
1. Run `node script/node-spec-runner.js --default` from the electron repo
2. If all tests pass → Phase Three is complete
3. If tests fail:
- Identify the failing test file(s) from the output
- Analyze each failure (see "Common Failure Patterns" below)
- Fix the test in `../third_party/electron_node/test/...`
- Re-run the specific failing test to verify: `node script/node-spec-runner.js {test-path}`
- The test path is relative to the node `test/` directory, e.g. `test/parallel/test-crypto-key-objects-raw.js`
- Do NOT use `--default` when running specific tests — it adds the full suite flags
- Do NOT run tests directly with `ELECTRON_RUN_AS_NODE` — the runner handles environment setup (e.g. temporarily switching `package.json` from ESM to CommonJS)
- Commit the fix using the fixup workflow and commit guidelines
- Return to step 1
## Commands Reference
| Command | Purpose |
|---------|---------|
| `node script/node-spec-runner.js --default` | Run full Node.js test suite |
| `node script/node-spec-runner.js test/parallel/test-foo.js` | Run a single test |
| `NODE_REGENERATE_SNAPSHOTS=1 node script/node-spec-runner.js test/test-runner/test-foo.mjs` | Regenerate snapshot for a snapshot-based test |
## Common Failure Patterns
### BoringSSL incompatibilities
Electron uses BoringSSL (via Chromium) instead of OpenSSL. Many crypto features are missing or behave differently:
When guarding tests, prefer checking cipher availability (`ciphers.includes(algo)`) over blanket BoringSSL checks where possible, as it's more precise and self-documenting.
New upstream tests that exercise these features will need guards added to the `fix_crypto_tests_to_run_with_bssl` patch.
### Snapshot test mismatches
Some tests compare output against committed `.snapshot` files using `assert.strictEqual` — these are NOT wildcard comparisons. When Chromium's V8 produces different output (e.g. different stack traces due to V8 enhancements), the snapshot must be regenerated:
- Crypto/BoringSSL tests → `fix crypto tests to run with bssl`
- Snapshot tests → the specific snapshot patch (e.g. `test: accomodate V8 thenable`)
- Flaky tests → `test: formally mark some tests as flaky`
3. Create a fixup commit:
```bash
cd ../third_party/electron_node
git add test/path/to/test.js
git commit --fixup=<patch-commit-hash>
GIT_SEQUENCE_EDITOR=: git rebase --autosquash --autostash -i <commit>^
```
4. Export: `e patches node`
5. **Read `references/phase-three-commit-guidelines.md` NOW**, then commit the updated patch file.
### B. New Patches (rare)
Only create a new patch when the fix doesn't belong in any existing patch. The new patch commit in `../third_party/electron_node` must include a description explaining why the patch exists and when it can be removed — the lint check enforces this.
## Adding to Disabled Tests
Only add a test to `script/node-disabled-tests.json` as a **last resort** — when the test is fundamentally incompatible with Electron's architecture (not just a BoringSSL difference that can be guarded). Tests disabled here are completely skipped and never run.
# Critical: Read Before Committing
- Before ANY Phase One commits: Read `references/phase-one-commit-guidelines.md`
- Before ANY Phase Two commits: Read `references/phase-two-commit-guidelines.md`
- Before ANY Phase Three commits: Read `references/phase-three-commit-guidelines.md`
# High-Churn Patches
These patches consistently require the most work during Node.js upgrades:
- **`fix_handle_boringssl_and_openssl_incompatibilities.patch`** — Electron uses BoringSSL (via Chromium) while Node.js expects OpenSSL. This patch is large and complex, and upstream OpenSSL API changes frequently break it.
- **`fix_crypto_tests_to_run_with_bssl.patch`** — Companion to the above; adapts Node.js crypto tests for BoringSSL. Can grow significantly during major upgrades.
- **`support_v8_sandboxed_pointers.patch`** — V8 sandbox pointer support requires careful adaptation when V8 APIs change.
- **`build_add_gn_build_files.patch`** — The GN build file patch is large and touches many build targets. Upstream build system changes frequently conflict.
# Major Version Upgrades
Major Node.js version transitions (e.g., v22 → v24) are significantly more involved than patch bumps:
1. **Expect patch deletions.** Electron uses Chromium's V8, which is often ahead of the V8 version bundled in Node.js. Many patches exist to bridge this gap — shimming newer V8 APIs that Chromium's V8 has but Node.js' older V8 doesn't. When Node.js bumps to a newer major version, its V8 catches up to Chromium's, and those bridge patches can be deleted. In the v22 → v24 upgrade, 17 patches were deleted for this reason.
2. **Update `@types/node`** in `package.json` to match the new major version.
3. **Post-upgrade regressions are expected.** Even after the upgrade lands, follow-up fix PRs for edge cases (ESM path handling, certificate loading, platform-specific issues) are normal.
# Skill Directory Structure
This skill has additional reference files in `references/`:
- patch-analysis.md - How to analyze patch failures
- phase-one-commit-guidelines.md - Commit format for Phase One
- phase-two-commit-guidelines.md - Commit format for Phase Two
- phase-three-commit-guidelines.md - Commit format for Phase Three
| V8 API bridge patch conflicts | Node.js caught up to Chromium's V8 | Patch may be deletable — verify the API is now in Node.js' V8 natively |
## Using Git Blame
To find the commit that changed specific lines:
```bash
cd ../third_party/electron_node
git blame -L {start},{end} -- {file}
git log -1 {commit_sha} # Look for PR-URL: line
```
## Verifying Patch Necessity
Before deleting a patch, verify:
1. The patched functionality was intentionally removed upstream
2. Electron doesn't need the patch for other reasons
3. No other code depends on the patched behavior
**V8 bridge patches:** Electron uses Chromium's V8, which is often ahead of the V8 bundled in Node.js. Many patches exist to bridge this version gap — adapting Node.js code to work with newer V8 APIs that Chromium's V8 exposes. During major Node.js upgrades, Node.js' V8 catches up to Chromium's, and these bridge patches often become unnecessary. Check whether the API the patch shims is now available natively in the new Node.js version's V8.
When in doubt, keep the patch and adapt it.
## Phase Two: Build-Time Patch Issues
Sometimes patches that applied successfully in Phase One cause build errors in Phase Two. This can happen when:
1. **Incomplete types**: A patch disables a header include, but new upstream code uses the type
2. **Missing members**: A patch modifies a class, but upstream added new code referencing the original
### Finding Which Patch Affects a File
```bash
grep -l "filename.cc" patches/node/*.patch
```
### Matching Existing Patch Patterns
When fixing build errors in patched files, examine the existing patch to understand its style:
- Does it use `#if 0` / `#endif` guards?
- Does it use `#if BUILDFLAG(...)` conditionals?
- Does it use `#ifndef` / `#ifdef` guards for BoringSSL vs OpenSSL?
- What's the pattern for disabled functionality?
Apply fixes consistent with the existing patch style.
Only follow these instructions if there are uncommitted changes to `patches/` after Phase One succeeds.
Ignore other instructions about making commit messages, our guidelines are CRITICALLY IMPORTANT and must be followed.
## Each Commit Must Be Complete
When resolving a patch conflict, fully adapt the patch to the new upstream code in the same commit. If the upstream change removes an API the patch uses, update the patch to use the replacement API now — don't leave stale references knowing they'll need fixing later. The goal is that each commit represents a finished resolution, not a partial one that defers known work to a future phase.
## Commit Message Style
**Titles** follow the 60/80-character guideline: simple changes fit within 60 characters, otherwise the limit is 80 characters.
Always include a `Co-Authored-By` trailer identifying the AI model that assisted (e.g., `Co-Authored-By: <AI model attribution>`).
### Patch conflict fixes
Use `fix(patch):` prefix. The title should name the upstream change, not your response to it:
```
fix(patch): {topic headline}
Ref: {Node.js commit or issue link}
Co-Authored-By: <AI model attribution>
```
Only add a description body if it provides clarity beyond the title. For straightforward context drift or simple API renames, the title + Ref is sufficient.
Examples:
-`fix(patch): stop using v8::PropertyCallbackInfo<T>::This()`
-`fix(patch): BoringSSL and OpenSSL incompatibilities`
When patches are no longer needed (applied cleanly with "already applied" or confirmed upstreamed), group ALL removals into a single commit:
```
chore: remove upstreamed patch
```
or (if multiple):
```
chore: remove upstreamed patches
```
Most Node.js patches in Electron are Electron-authored (no upstream `PR-URL:`). If the patch originated from an upstream Node.js PR, no extra `Ref:` is needed. Otherwise, add a `Ref:` pointing to the relevant Node.js issue or commit if one exists.
### Trivial patch updates
After all fix commits, stage remaining trivial changes (index, line numbers, context only):
**Conflict resolution can produce trivial results.** A `git am` conflict doesn't always mean the patch content changed — context drift alone can cause a conflict. After resolving and exporting, inspect the patch diff: if only index hashes, line numbers, and context lines changed (not the patch's own `+`/`-` lines), it's trivial and belongs here, not in a `fix(patch):` commit.
## Atomic Commits
Each patch conflict fix gets its own commit with its own Ref.
IMPORTANT: Try really hard to find the PR or commit reference per the instructions below. Each change you made should in theory have been in response to a change made in Node.js that you identified or can identify. Try for a while to identify and include the ref in the commit message. Do not give up easily.
## Finding Commit/Issue References
Use `git log` or `git blame` on Node.js source files in `../third_party/electron_node`. Look for:
```
PR-URL: https://github.com/nodejs/node/pull/XXXXX
```
or issue references in the patch itself:
```
Refs: https://github.com/nodejs/node/issues/XXXXX
```
Note: Most Node.js patches in Electron are Electron-authored and won't have upstream references. In that case, check `git log` in the Node.js repo to find which upstream commit caused the conflict.
If no reference found after searching: `Ref: Unable to locate reference`
## Example Commits
### Patch conflict fix (simple — title is sufficient)
```
fix(patch): stop using v8::PropertyCallbackInfo<T>::This()
Only follow these instructions if there are uncommitted changes after fixing a test failure during Phase Three.
Ignore other instructions about making commit messages, our guidelines are CRITICALLY IMPORTANT and must be followed.
## Commit Message Style
**Titles** follow the 60/80-character guideline: simple changes fit within 60 characters, otherwise the limit is 80 characters.
Always include a `Co-Authored-By` trailer identifying the AI model that assisted (e.g., `Co-Authored-By: <AI model attribution>`).
## Commit Types
### Patch updates (most test fixes)
Test fixes go into existing patches via the fixup workflow. Use `fix(patch):` prefix with a descriptive topic:
```
fix(patch): {topic headline}
Ref: {Node.js commit or issue link}
Co-Authored-By: <AI model attribution>
```
Examples:
-`fix(patch): guard DH key test for BoringSSL`
-`fix(patch): adapt new crypto tests for BoringSSL`
-`fix(patch): correct thenable snapshot for Chromium V8`
-`fix(patch): skip AES-KW tests with BoringSSL`
Group related test fixes into a single commit when they address the same root cause (e.g., multiple crypto tests all needing BoringSSL guards for the same missing cipher). Don't create one commit per test file if they share the same fix pattern.
### Snapshot regeneration
When a snapshot test fails because Chromium's V8 produces different output, regenerate it:
Only follow these instructions if there are uncommitted changes in the Electron repo after any fixes are made during Phase Two that result a target that was failing, successfully building.
Ignore other instructions about making commit messages, our guidelines are CRITICALLY IMPORTANT and must be followed.
## Commit Message Style
**Titles** follow the 60/80-character guideline: simple changes fit within 60 characters, otherwise the limit is 80 characters. Exception: upstream Node.js PR titles are used verbatim even if longer.
Always include a `Co-Authored-By` trailer identifying the AI model that assisted (e.g., `Co-Authored-By: <AI model attribution>`).
## Two Commit Types
### For Electron Source Changes (shell/, electron/, etc.)
When the upstream Node.js commit has a `PR-URL:`:
```
node#{PR-Number}: {upstream PR's original title}
Ref: {Node.js PR link}
Co-Authored-By: <AI model attribution>
```
When there is no `PR-URL:` but there is an issue reference or commit:
```
fix: {description of the adaptation}
Ref: {Node.js issue or commit link}
Co-Authored-By: <AI model attribution>
```
Use the **upstream commit's original title** when available — do not paraphrase or rewrite it. To find it: check the commit message in `../third_party/electron_node` for `PR-URL:` or `Refs:` lines.
Only add a description body if it provides clarity beyond what the title already says (e.g., when Electron's adaptation is non-obvious). For simple renames, method additions, or straightforward API updates, the title + Ref link is sufficient.
Each change should have its own commit and its own Ref. Logically group into commits that make sense rather than one giant commit. You may include multiple "Ref" links if required.
IMPORTANT: Try really hard to find a reference. Each change you made should in theory have been in response to a change in Node.js. Check `git log` and `git blame` in the Node.js repo. Do not give up easily.
### For Patch Updates (patches/node/*.patch)
Use the same fixup workflow as Phase One and follow `references/phase-one-commit-guidelines.md` for the commit message format (`fix(patch):` prefix, topic style).
## Dependent Patch Header Updates
After any patch modification, check for other affected patches:
```bash
git status
# If other .patch files show as modified with only index, line number, and context changes:
Use `git log` or `git blame` on Node.js source files in `../third_party/electron_node`. Look for:
```
PR-URL: https://github.com/nodejs/node/pull/XXXXX
Refs: https://github.com/nodejs/node/issues/XXXXX
```
Note: Many Node.js patches in Electron are Electron-authored and won't have upstream `PR-URL:` lines. Check the patch's own commit message for `Refs:` lines, or use `git log` in the Node.js repo to find which upstream commit caused the build break.
If no reference found after searching: `Ref: Unable to locate reference`
## Example Commits
### Electron Source Fix (with upstream PR)
```
node#61898: src: stop using v8::PropertyCallbackInfo<T>::This()
Ref: https://github.com/nodejs/node/pull/61898
Co-Authored-By: <AI model attribution>
```
### Electron Source Fix (with issue reference, no PR)
```
fix: adapt to v8::PropertyCallbackInfo<T>::This() removal
Updated NodeBindings to use HolderV2() after upstream Node.js
ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 e d gclient sync --with_branch_heads --with_tags -vv
ELECTRON_DEPOT_TOOLS_WIN_TOOLCHAIN=0 DEPOT_TOOLS_WIN_TOOLCHAIN=0 ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 e d gclient sync --with_branch_heads --with_tags
if [[ "${{ inputs.is-release }}" != "true" ]]; then
# Re-export all the patches to check if there were changes.
Electron embeds Chromium (rendering) and Node.js (backend) to enable desktop apps with web technologies. The parent directory (`../`) is the Chromium source tree.
### Process Model
Electron has two primary process types, mirroring Chromium:
- **Renderer process** (`shell/renderer/` + `lib/renderer/`): Runs web content in BrowserWindows
### Native ↔ JavaScript Bridge
Each API is implemented as a C++/JS pair:
- C++ side: `shell/browser/api/electron_api_{name}.cc/.h` — uses `gin::Wrappable` and `ObjectTemplateBuilder`
- JS side: `lib/browser/api/{name}.ts` — exports the module, registered in `lib/browser/api/module-list.ts`
- Binding: `NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_{name}, Initialize)` in C++ and registered in `shell/common/node_bindings.cc`
- Type declaration: `typings/internal-ambient.d.ts` maps `process._linkedBinding('electron_browser_{name}')`
### Patches System
Electron patches upstream dependencies (Chromium, Node.js, V8, etc.) rather than forking them. Patches live in `patches/` organized by target, with `patches/config.json` mapping directories to repos.
⚠️ This PR contains unsigned commits. This repository enforces [commit signatures](https://docs.github.com/en/authentication/managing-commit-signature-verification)
for all incoming PRs. To get your PR merged, please sign those commits
(`git rebase --exec 'git commit -S --amend --no-edit -n' @{upstream}`) and force push them to this branch
(`git push --force-with-lease`)
For more information on signing commits, see GitHub's documentation on [Telling Git about your signing key](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key).
printf "<!-- disallowed-non-maintainer-change -->\n\nHello @${{ github.event.pull_request.user.login }}! It looks like this pull request touches one of our dependency or CI files, and per [our contribution policy](https://github.com/electron/electron/blob/main/CONTRIBUTING.md#dependencies-upgrades-policy) we do not accept these types of changes in PRs." | gh pr review $PR_URL -r --body-file=-
printf "<!-- disallowed-non-maintainer-change -->\n\nHello @${PR_AUTHOR}! It looks like this pull request touches one of our dependency or CI files, and per [our contribution policy](https://github.com/electron/electron/blob/main/CONTRIBUTING.md#dependencies-upgrades-policy) we do not accept these types of changes in PRs." | gh pr review $PR_URL -r --body-file=-
⚠️ This PR contains unsigned commits. This repository enforces [commit signatures](https://docs.github.com/en/authentication/managing-commit-signature-verification)
for all incoming PRs. To get your PR merged, please sign those commits
(`git rebase --exec 'git commit -S --amend --no-edit -n' @{upstream}`) and force push them to this branch
(`git push --force-with-lease`)
For more information on signing commits, see GitHub's documentation on [Telling Git about your signing key](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key).
If asked to fix a patch conflict on a branch that already has an open PR, check the PR's failed **Apply Patches** CI run for an `update-patches` artifact before running `e sync` locally. CI has already performed the 3-way merge and exported the resolved patch diff — applying it is much faster than a full local sync.
```bash
# Find the failed Apply Patches run for the PR and download the artifact
gh run list --repo electron/electron --branch <pr-branch> --workflow "Apply Patches" --limit 1
gh run download <run-id> --repo electron/electron --name update-patches
# Apply the CI-generated fix, then push
git am update-patches.patch
git push
```
If no artifact exists (e.g. the 3-way merge itself failed), fall back to `e sync --3` and resolve manually.
## Testing
**Test location:**`spec/` directory
@@ -155,6 +171,14 @@ e test # Run full test suite
When working on the `roller/chromium/main` branch to upgrade Chromium activate the "Electron Chromium Upgrade" skill.
## Node.js Upgrade Workflow
When working on the `roller/node/main` branch to upgrade Node.js activate the "Electron Node.js Upgrade" skill.
## Pull Requests
PR bodies must always include a `Notes:` section as the **last line** of the body. This is a consumer-facing release note for Electron app developers — describe the user-visible fix or change, not internal implementation details. Use `Notes: none` if there is no user-facing change.
## Code Style
**C++:** Follows Chromium style, enforced by clang-format
Emitted when the user clicks the native macOS new tab button. The new
tab button is only visible if the current `BrowserWindow` has a
`tabbingIdentifier`
`tabbingIdentifier`.
You must create a window in this handler in order for macOS tabbing to work as expected.
### Event: 'browser-window-blur'
@@ -633,7 +635,7 @@ Returns `string` - The current application directory.
Returns `string` - A path to a special directory or file associated with `name`. On
failure, an `Error` is thrown.
If `app.getPath('logs')` is called without called`app.setAppLogsPath()` being called first, a default log directory will be created equivalent to calling `app.setAppLogsPath()` without a `path` parameter.
If `app.getPath('logs')` is called without calling`app.setAppLogsPath()` being called first, a default log directory will be created equivalent to calling `app.setAppLogsPath()` without a `path` parameter.
### `app.getFileIcon(path[, options])`
@@ -648,7 +650,7 @@ Returns `Promise<NativeImage>` - fulfilled with the app's icon, which is a [Nati
Fetches a path's associated icon.
On _Windows_, there a 2 kinds of icons:
On _Windows_, there are 2 kinds of icons:
* Icons associated with certain file extensions, like `.mp3`, `.png`, etc.
* Icons inside the file itself, like `.exe`, `.dll`, `.ico`.
Both the available languages and regions and the possible return values differ between the two operating systems.
As can be seen with the example above, on Windows, it is possible that a preferred system language has no country code, and that one of the preferred system languages corresponds with the language used for the regional format. On macOS, the region serves more as a default country code: the user doesn't need to have Finnish as a preferred language to use Finland as the region,and the country code `FI` is used as the country code for preferred system languages that do not have associated countries in the language name.
As can be seen with the example above, on Windows, it is possible that a preferred system language has no country code, and that one of the preferred system languages corresponds with the language used for the regional format. On macOS, the region serves more as a default country code: the user doesn't need to have Finnish as a preferred language to use Finland as the region,and the country code `FI` is used as the country code for preferred system languages that do not have associated countries in the language name.
* Canonical without braces: `XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX` (braces will be added automatically)
* Hex digits are case-insensitive.
This method should be called early (before showing notifications) so the value is baked into the registration/shortcut. Supplying an empty string or an unparsable value throws and leaves the existing (or generated) CLSID unchanged. If this method is never called, a random CLSID is generated once per run and exposed via `app.toastActivatorCLSID`.
### `app.setActivationPolicy(policy)` _macOS_
*`policy` string - Can be 'regular', 'accessory', or 'prohibited'.
@@ -1226,7 +1241,7 @@ Returns `boolean` - whether hardware acceleration is currently enabled.
### `app.disableDomainBlockingFor3DAPIs()`
By default, Chromium disables 3D APIs (e.g. WebGL) until restart on a per
domain basis if the GPU processes crashes too frequently. This function
domain basis if the GPU process crashes too frequently. This function
disables that behavior.
This method can only be called before app is ready.
@@ -1285,6 +1300,8 @@ For `infoType` equal to `basic`:
Using `basic` should be preferred if only basic information like `vendorId` or `deviceId` is needed.
Promise is rejected if the GPU is completely disabled, i.e. no hardware and software implementations are available.
### `app.setBadgeCount([count])` _Linux_ _macOS_
*`count` Integer (optional) - If a value is provided, set the badge to the provided value otherwise, on macOS, display a plain white dot (e.g. unknown number of notifications). On Linux, if a value is not provided the badge will not display.
@@ -1315,7 +1332,7 @@ Returns `boolean` - Whether the current desktop environment is Unity launcher.
*`type` string (optional) _macOS_ - Can be one of `mainAppService`, `agentService`, `daemonService`, or `loginItemService`. Defaults to `mainAppService`. Only available on macOS 13 and up. See [app.setLoginItemSettings](app.md#appsetloginitemsettingssettings-macos-windows) for more information about each type.
*`type` string (optional) _macOS_ - Can be `mainAppService`, `agentService`, `daemonService`, or `loginItemService`. Defaults to `mainAppService`. Only available on macOS 13 and up. See [app.setLoginItemSettings](app.md#appsetloginitemsettingssettings-macos-windows) for more information about each type.
*`serviceName` string (optional) _macOS_ - The name of the service. Required if `type` is non-default. Only available on macOS 13 and up.
*`path` string (optional) _Windows_ - The executable path to compare against. Defaults to `process.execPath`.
*`args` string[] (optional) _Windows_ - The command-line arguments to compare against. Defaults to an empty array.
@@ -1330,13 +1347,13 @@ Returns `Object`:
*`wasOpenedAtLogin` boolean _macOS_ - `true` if the app was opened at login automatically.
*`wasOpenedAsHidden` boolean _macOS__Deprecated_ - `true` if the app was opened as a hidden login item. This indicates that the app should not open any windows at startup. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
*`restoreState` boolean _macOS__Deprecated_ - `true` if the app was opened as a login item that should restore the state from the previous session. This indicates that the app should restore the windows that were open the last time the app was closed. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
*`status` string _macOS_ - can be one of `not-registered`, `enabled`, `requires-approval`, or `not-found`.
*`status` string _macOS_ - can be `not-registered`, `enabled`, `requires-approval`, or `not-found`.
*`executableWillLaunchAtLogin` boolean _Windows_ - `true` if app is set to open at login and its run key is not deactivated. This differs from `openAtLogin` as it ignores the `args` option, this property will be true if the given executable would be launched at login with **any** arguments.
*`launchItems` Object[] _Windows_
*`name` string _Windows_ - name value of a registry entry.
*`path` string _Windows_ - The executable to an app that corresponds to a registry entry.
*`args` string[] _Windows_ - the command-line arguments to pass to the executable.
*`scope` string _Windows_ - one of`user` or `machine`. Indicates whether the registry entry is under `HKEY_CURRENT USER` or `HKEY_LOCAL_MACHINE`.
*`scope` string _Windows_ - can be`user` or `machine`. Indicates whether the registry entry is under `HKEY_CURRENT USER` or `HKEY_LOCAL_MACHINE`.
*`enabled` boolean _Windows_ - `true` if the app registry key is startup approved and therefore shows as `enabled` in Task Manager and Windows settings.
@@ -1702,8 +1719,13 @@ platforms) that allows you to perform actions on your app icon in the user's doc
A `boolean` property that returns `true` if the app is packaged, `false` otherwise. For many apps, this property can be used to distinguish development and production environments.
@@ -32,9 +32,19 @@ update process. Apps that need to disable ATS can add the
### Windows
On Windows, you have to install your app into a user's machine before you can
use the `autoUpdater`, so it is recommended that you use
[electron-winstaller][installer-lib] or [Electron Forge's Squirrel.Windows maker][electron-forge-lib] to generate a Windows installer.
On Windows, the `autoUpdater` module automatically selects the appropriate update mechanism
based on how your app is packaged:
* **MSIX packages**: If your app is running as an MSIX package (created with [electron-windows-msix][msix-lib] and detected via [`process.windowsStore`](process.md#processwindowsstore-readonly)),
the module uses the MSIX updater, which supports direct MSIX file links and JSON update feeds.
***Squirrel.Windows**: For apps installed via traditional installers (created with
[electron-winstaller][installer-lib] or [Electron Forge's Squirrel.Windows maker][electron-forge-lib]),
the module uses Squirrel.Windows for updates.
You don't need to configure which updater to use; Electron automatically detects the packaging
format and uses the appropriate one.
#### Squirrel.Windows
Apps built with Squirrel.Windows will trigger [custom launch events](https://github.com/Squirrel/Squirrel.Windows/blob/51f5e2cb01add79280a53d51e8d0cfa20f8c9f9f/docs/using/custom-squirrel-events-non-cs.md#application-startup-commands)
that must be handled by your Electron application to ensure proper setup and teardown.
@@ -55,6 +65,14 @@ The installer generated with Squirrel.Windows will create a shortcut icon with a
same ID for your app with `app.setAppUserModelId` API, otherwise Windows will
not be able to pin your app properly in task bar.
#### MSIX Packages
When your app is packaged as an MSIX, the `autoUpdater` module provides additional
functionality:
* Use the `allowAnyVersion` option in `setFeedURL()` to allow updates to older versions (downgrades)
* Support for direct MSIX file links or JSON update feeds (similar to Squirrel.Mac format)
## Events
The `autoUpdater` object emits the following events:
@@ -92,7 +110,7 @@ Returns:
Emitted when an update has been downloaded.
On Windows only `releaseName` is available.
With Squirrel.Windows only `releaseName` is available.
> [!NOTE]
> It is not strictly necessary to handle this event. A successfully
@@ -100,6 +118,13 @@ On Windows only `releaseName` is available.
This event is emitted after a user calls `quitAndInstall()`.
When this API is called, the `before-quit` event is not emitted before all windows are closed. As a result you should listen to this event if you wish to perform actions before the windows are closed while a process is quitting, as well as listening to `before-quit`.
@@ -110,11 +135,23 @@ The `autoUpdater` object has the following methods:
description: "Changed API to accept a single `options` argument (contains `url`, `headers`, and `serverType` properties)."
```
-->
* `options` Object
*`url` string
* `url` string - The update server URL. For _Windows_ MSIX, this can be either a direct link to an MSIX file (e.g., `https://example.com/update.msix`) or a JSON endpoint that returns update information (see the [Squirrel.Mac][squirrel-mac] README for more information).
@@ -756,6 +760,9 @@ Returns [`Rectangle`](structures/rectangle.md) - The `bounds` of the window as `
> [!NOTE]
> On macOS, the y-coordinate value returned will be at minimum the [Tray](tray.md) height. For example, calling `win.setBounds({ x: 25, y: 20, width: 800, height: 600 })` with a tray height of 38 means that `win.getBounds()` will return `{ x: 25, y: 38, width: 800, height: 600 }`.
> [!NOTE]
> On Wayland, this method will return `{ x: 0, y: 0, ... }` as introspecting or programmatically changing the global window coordinates is prohibited.
#### `win.getBackgroundColor()`
Returns `string` - Gets the background color of the window in Hex (`#RRGGBB`) format.
@@ -969,6 +976,9 @@ Moves window to `x` and `y`.
Returns `Integer[]` - Contains the window's current position.
> [!NOTE]
> On Wayland, this method will return `[0, 0]` as introspecting or programmatically changing the global window coordinates is prohibited.
#### `win.setTitle(title)`
* `title` string
@@ -1043,7 +1053,7 @@ under this mode apps can choose to optimize their UI for tablets, such as
enlarging the titlebar and hiding titlebar buttons.
This API returns whether the window is in tablet mode, and the `resize` event
can be be used to listen to changes to tablet mode.
@@ -862,6 +866,9 @@ Returns [`Rectangle`](structures/rectangle.md) - The `bounds` of the window as `
> [!NOTE]
> On macOS, the y-coordinate value returned will be at minimum the [Tray](tray.md) height. For example, calling `win.setBounds({ x: 25, y: 20, width: 800, height: 600 })` with a tray height of 38 means that `win.getBounds()` will return `{ x: 25, y: 38, width: 800, height: 600 }`.
> [!NOTE]
> On Wayland, this method will return `{ x: 0, y: 0, ... }` as introspecting or programmatically changing the global window coordinates is prohibited.
#### `win.getBackgroundColor()`
Returns `string` - Gets the background color of the window in Hex (`#RRGGBB`) format.
@@ -1087,6 +1094,9 @@ Not supported on Wayland (Linux).
Returns `Integer[]` - Contains the window's current position.
> [!NOTE]
> On Wayland, this method will return `[0, 0]` as introspecting or programmatically changing the global window coordinates is prohibited.
#### `win.setTitle(title)`
* `title` string
@@ -1159,7 +1169,7 @@ under this mode apps can choose to optimize their UI for tablets, such as
enlarging the titlebar and hiding titlebar buttons.
This API returns whether the window is in tablet mode, and the `resize` event
can be be used to listen to changes to tablet mode.
@@ -172,7 +172,7 @@ Enables net log events to be saved and writes them to `path`.
Sets the verbosity of logging when used together with `--enable-logging`.
`N` should be one of [Chrome's LogSeverities][severities].
Note that two complimentary logging mechanisms in Chromium -- `LOG()`
Note that two complementary logging mechanisms in Chromium -- `LOG()`
and `VLOG()` -- are controlled by different switches. `--log-level`
controls `LOG()` messages, while `--v` and `--vmodule` control `VLOG()`
messages. So you may want to use a combination of these three switches
@@ -354,6 +354,11 @@ Affects the default output directory of [v8.setHeapSnapshotNearHeapLimit](https:
Disable exposition of [Navigator API][] on the global scope from Node.js.
### `--experimental-transform-types`
Enables the [transformation](https://nodejs.org/api/typescript.html#type-stripping)
of TypeScript-only syntax into JavaScript code.
## Chromium Flags
There isn't a documented list of all Chromium switches, but there are a few ways to find them.
@@ -370,6 +375,13 @@ Keep in mind that standalone switches can sometimes be split into individual fea
Finally, you'll need to ensure that the version of Chromium in Electron matches the version of the browser you're using to cross-reference the switches.
### Chromium features relevant to Electron apps
* `AlwaysLogLOAFURL`: enables script attribution for
description: "The `resultFilePath` parameter is now optional."
```
-->
* `resultFilePath` string (optional)
Returns `Promise<string>` - resolves with a path to a file that contains the traced data once all child processes have acknowledged the `stopRecording` request
@@ -76,6 +107,15 @@ will be returned in the promise.
* `types` string[] - An array of strings that lists the types of desktop sources
to be captured, available types can be `screen` and `window`.
@@ -94,18 +105,56 @@ The `desktopCapturer` module has the following methods:
Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [`DesktopCapturerSource`](structures/desktop-capturer-source.md) objects, each `DesktopCapturerSource` represents a screen or an individual window that can be captured.
> [!NOTE]
> Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher,
> which can detected by [`systemPreferences.getMediaAccessStatus`][].
<!-- markdownlint-disable-next-line MD032 -->
> * Capturing audio requires `NSAudioCaptureUsageDescription` Info.plist key on macOS 14.2 Sonoma and higher - [read more](#macos-versions-142-or-higher).
> * Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher, which can detected by [`systemPreferences.getMediaAccessStatus`][].
`desktopCapturer.getSources(options)` only returns a single source on Linux when using Pipewire.
PipeWire supports a single capture for both screens and windows. If you request the window and screen type, the selected source will be returned as a window capture.
`navigator.mediaDevices.getUserMedia` does not work on macOS for audio capture due to a fundamental limitation whereby apps that want to access the system's audio require a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html). Chromium, and by extension Electron, does not provide this.
### macOS versions 14.2 or higher
It is possible to circumvent this limitation by capturing system audio with another macOS app like Soundflower and passing it through a virtual audio input device. This virtual device can then be queried with `navigator.mediaDevices.getUserMedia`.
`NSAudioCaptureUsageDescription` Info.plist key must be added in order for audio to be captured by
`desktopCapturer`. If instead you are running Electron from another program like a terminal or IDE
then that parent program must contain the Info.plist key.
This is in order to facillitate use of Apple's new [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps#Configure-the-sample-code-project) by Chromium.
> [!WARNING]
> Failure of `desktopCapturer` to start an audio stream due to `NSAudioCaptureUsageDescription`
> permission not present will still create a dead audio stream however no warnings or errors are
> displayed.
As of Electron `v39.0.0-beta.4`, Chromium [made Apple's new `CoreAudio Tap API` the default](https://source.chromium.org/chromium/chromium/src/+/ad17e8f8b93d5f34891b06085d373a668918255e)
for desktop audio capture. There is no fallback to the older `Screen & System Audio Recording`
permissions system even if [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps) stream creation fails.
If you need to continue using `Screen & System Audio Recording` permissions for `desktopCapturer`
on macOS versions 14.2 and later, you can apply a Chromium feature flag to force use of that older
permissions system:
```js
// main.js (right beneath your require/import statments)
`navigator.mediaDevices.getUserMedia` does not work on macOS versions 12.7.6 and prior for audio
capture due to a fundamental limitation whereby apps that want to access the system's audio require
a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html).
Chromium, and by extension Electron, does not provide this. Only in macOS 13 and onwards does Apple
provide APIs to capture desktop audio without the need for a signed kernel extension.
It is possible to circumvent this limitation by capturing system audio with another macOS app like
[BlackHole](https://existential.audio/blackhole/) or [Soundflower](https://rogueamoeba.com/freebies/soundflower/)
and passing it through a virtual audio input device. This virtual device can then be queried
Notification replied to (com.github.Electron:notification:EAF7B87C-A113-43D7-8E76-F88EC9D73D44)
```
### `ELECTRON_DEBUG_MSIX_UPDATER`
Adds extra logs to MSIX updater operations on Windows to aid in debugging. Extra logging will be displayed when MSIX update operations are initiated, including package updates, package registration, and restart registration. This helps diagnose issues with MSIX package updates and deployments.
Sample output:
```sh
UpdateMsix called with URI: https://example.com/app.msix
An `Accelerator | null` indicating the item's [user-assigned accelerator](https://developer.apple.com/documentation/appkit/nsmenuitem/1514850-userkeyequivalent?language=objc) for the menu item.
An [`Accelerator | null`](../tutorial/keyboard-shortcuts.md#accelerators) indicating the item's [user-assigned accelerator](https://developer.apple.com/documentation/appkit/nsmenuitem/1514850-userkeyequivalent?language=objc) for the menu item.
> [!NOTE]
> This property is only initialized after the `MenuItem` has been added to a `Menu`. Either via `Menu.buildFromTemplate` or via `Menu.append()/insert()`. Accessing before initialization will just return `null`.
#### `menuItem.icon`
A `NativeImage | string` (optional) indicating the
item's icon, if set.
A `NativeImage | string` (optional) indicating the item's icon, if set.
This property can be dynamically changed.
#### `menuItem.sublabel`
A `string` indicating the item's sublabel.
This property can be dynamically changed.
#### `menuItem.toolTip` _macOS_
A `string` indicating the item's hover text.
#### `menuItem.enabled`
A `boolean` indicating whether the item is enabled. This property can be
dynamically changed.
A `boolean` indicating whether the item is enabled.
This property can be dynamically changed.
#### `menuItem.visible`
A `boolean` indicating whether the item is visible. This property can be
dynamically changed.
A `boolean` indicating whether the item is visible.
This property can be dynamically changed.
#### `menuItem.checked`
A `boolean` indicating whether the item is checked. This property can be
dynamically changed.
A `boolean` indicating whether the item is checked.
This property can be dynamically changed.
A `checkbox` menu item will toggle the `checked` property on and off when
selected.
@@ -161,7 +170,7 @@ This property can be dynamically changed.
#### `menuItem.sharingItem` _macOS_
A `SharingItem` indicating the item to share when the `role` is `shareMenu`.
A [`SharingItem`](structures/sharing-item.md) indicating the item to share when the `role` is `shareMenu`.
This property can be dynamically changed.
@@ -171,4 +180,4 @@ A `number` indicating an item's sequential unique id.
@@ -28,7 +28,7 @@ The `Menu` class has the following static methods:
#### `Menu.setApplicationMenu(menu)`
-`menu` Menu | null
-`menu`[Menu](menu.md) | null
Sets `menu` as the application menu on macOS. On Windows and Linux, the
`menu` will be set as each window's top menu.
@@ -39,14 +39,14 @@ indicate which letter should get a generated accelerator. For example, using
opens the associated menu. The indicated character in the button label then gets an
underline, and the `&` character is not displayed on the button label.
In order to escape the `&` character in an item name, add a proceeding `&`. For example, `&&File` would result in `&File` displayed on the button label.
In order to escape the `&` character in an item name, add a preceding `&`. For example, `&&File` would result in `&File` displayed on the button label.
Passing `null` will suppress the default menu. On Windows and Linux,
this has the additional effect of removing the menu bar from the window.
> [!NOTE]
> The default menu will be created automatically if the app does not set one.
> It contains standard items such as `File`, `Edit`, `View`, `Window` and `Help`.
> It contains standard items such as `File`, `Edit`, `View`, and `Window`.
#### `Menu.getApplicationMenu()`
@@ -70,9 +70,9 @@ for more information on macOS' native actions.
A `boolean` that indicates whether the user prefers UI that differentiates items using something other than color alone (e.g. shapes or labels). This maps to [NSWorkspace.accessibilityDisplayShouldDifferentiateWithoutColor](https://developer.apple.com/documentation/appkit/nsworkspace/accessibilitydisplayshoulddifferentiatewithoutcolor).
@@ -42,11 +42,15 @@ Returns `boolean` - Whether or not desktop notifications are supported on the cu
*`timeoutType` string (optional) _Linux__Windows_ - The timeout duration of the notification. Can be 'default' or 'never'.
*`replyPlaceholder` string (optional) _macOS_ - The placeholder to write in the inline reply input field.
*`sound` string (optional) _macOS_ - The name of the sound file to play when the notification is shown.
*`urgency` string (optional) _Linux_ - The urgency level of the notification. Can be 'normal', 'critical', or 'low'.
*`urgency` string (optional) _Linux__Windows_ - The urgency level of the notification. Can be 'normal', 'critical', or 'low'.
*`actions` [NotificationAction[]](structures/notification-action.md) (optional) _macOS_ - Actions to add to the notification. Please read the available actions and limitations in the `NotificationAction` documentation.
*`closeButtonText` string (optional) _macOS_ - A custom title for the close button of an alert. An empty string will cause the default localized text to be used.
*`toastXml` string (optional) _Windows_ - A custom description of the Notification on Windows superseding all properties above. Provides full customization of design and behavior of the notification.
> [!NOTE]
> On Windows, `urgency` type 'critical' sorts the notification higher in Action Center (above default priority notifications), but does not prevent auto-dismissal. To prevent auto-dismissal, you should also set
> `timeoutType` to 'never'.
### Instance Events
Objects created with `new Notification` emit the following events:
@@ -67,6 +71,22 @@ Emitted when the notification is shown to the user. Note that this event can be
multiple times as a notification can be shown multiple times through the
*`reason`_Windows_ string (optional) - The reason the notification was closed. This can be 'userCanceled', 'applicationHidden', or 'timedOut'.
Emitted when the notification is closed by manual intervention from the user.
@@ -88,21 +125,85 @@ is closed.
On Windows, the `close` event can be emitted in one of three ways: programmatic dismissal with `notification.close()`, by the user closing the notification, or via system timeout. If a notification is in the Action Center after the initial `close` event is emitted, a call to `notification.close()` will remove the notification from the action center but the `close` event will not be emitted again.
Emitted when an error is encountered while creating and showing the native notification.
```js
const{Notification,app}=require('electron')
app.whenReady().then(()=>{
constn=newNotification({
title:'Bad Action'
})
n.on('failed',(e,err)=>{
console.log('Notification failed: ',err)
})
n.show()
})
```
### Instance Methods
Objects created with the `new Notification()` constructor have the following instance methods:
@@ -126,12 +243,42 @@ call this method before the OS will display it.
If the notification has been shown before, this method will dismiss the previously
shown notification and create a new one with identical properties.
```js
const{Notification,app}=require('electron')
app.whenReady().then(()=>{
constn=newNotification({
title:'Title!',
subtitle:'Subtitle!',
body:'Body!'
})
n.show()
})
```
#### `notification.close()`
Dismisses the notification.
On Windows, calling `notification.close()` while the notification is visible on screen will dismiss the notification and remove it from the Action Center. If `notification.close()` is called after the notification is no longer visible on screen, calling `notification.close()` will try remove it from the Action Center.
> Import shared textures into Electron and converts platform specific handles into [`VideoFrame`](https://developer.mozilla.org/en-US/docs/Web/API/VideoFrame). Supports all Web rendering systems, and can be transferred across Electron processes. Read [here](https://github.com/electron/electron/blob/main/shell/common/api/shared_texture/README.md) for more information.
> Import shared textures into Electron and converts platform specific handles into [`VideoFrame`](https://developer.mozilla.org/en-US/docs/Web/API/VideoFrame). Supports all Web rendering systems, and can be transferred across Electron processes. Read [here](../../shell/common/api/shared_texture/README.md) for more information.
*`depthPerComponent` number - The number of bits per color component.
*`detected` boolean - `true` if the display is detected by the system.
*`displayFrequency` number - The display refresh rate.
*`id` number - Unique identifier associated with the display. A value of of -1 means the display is invalid or the correct `id` is not yet known, and a value of -10 means the display is a virtual display assigned to a unified desktop.
*`id` number - Unique identifier associated with the display. A value of -1 means the display is invalid or the correct `id` is not yet known, and a value of -10 means the display is a virtual display assigned to a unified desktop.
*`internal` boolean - `true` for an internal display and `false` for an external display.
*`label` string - User-friendly label, determined by the platform.
*`maximumCursorSize` [Size](size.md) - Maximum cursor size in native pixels.
| `button` | macOS | Used as the label for the button | "Show" (or a localized string by system default if first of such `button`, otherwise empty) | Only the first one is used. If multiple are provided, those beyond the first will be listed as additional actions (displayed when mouse active over the action button). Any such action also is incompatible with `hasReply` and will be ignored if `hasReply` is `true`. |
| `button` | macOS, Windows | Used as the label for the button | "Show" on macOS (localized) if first `button`, otherwise empty; Windows uses provided `text` | macOS: Only the first one is used as primary; others shown as additional actions (hover). Incompatible with `hasReply` (beyond first ignored). |
| `selection` | Windows | Used as the label for the submit button for the selection menu | "Select" | Requires an `items` array property specifying option labels. Emits the `action` event with `(index, selectedIndex)` where `selectedIndex` is the chosen option (>= 0). Ignored on platforms that do not support selection actions. |
### Button support on macOS
@@ -15,6 +17,37 @@ In order for extra notification buttons to work on macOS your app must meet the
following criteria.
* App is signed
* App has it's `NSUserNotificationAlertStyle` set to `alert` in the `Info.plist`.
* App has its `NSUserNotificationAlertStyle` set to `alert` in the `Info.plist`.
If either of these requirements are not met the button won't appear.
### Selection support on Windows
To add a selection (combo box) style action, include an action with `type: 'selection'`, a `text` label for the submit button, and an `items` array of strings:
```js
const{Notification,app}=require('electron')
app.whenReady().then(()=>{
constitems=['One','Two','Three']
constn=newNotification({
title:'Choose an option',
actions:[{
type:'selection',
text:'Apply',
items
}]
})
n.on('action',(e)=>{
console.log(`User triggered action at index: ${e.actionIndex}`)
When the user activates the selection action, the notification's `action` event will be emitted with two parameters: `actionIndex` (the action's index in the `actions` array) and `selectedIndex` (the zero-based index of the chosen item, or `-1` if unavailable). On non-Windows platforms selection actions are ignored.
*`ntHandle` Buffer (optional) _Windows_ - NT HANDLE holds the shared texture. Note that this NT HANDLE is local to current process.
*`ntHandle` Buffer (optional) _Windows_ - NT HANDLE holds the shared texture. Note that this NT HANDLE is local to current process. Output textures of `rgba`, `bgra`, `rgbaf16` formats don't have a keyed mutex on the texture handle, but `nv12` format texture handles do have a keyed mutex.
*`ioSurface` Buffer (optional) _macOS_ - IOSurfaceRef holds the shared texture. Note that this IOSurface is local to current process (not global).
*`javascript` boolean (optional) - Enables JavaScript support. Default is `true`.
*`webSecurity` boolean (optional) - When `false`, it will disable the
same-origin policy (usually using testing websites by people), and set
`allowRunningInsecureContent` to `true` if this options has not been set
`allowRunningInsecureContent` to `true` if this option has not been set
by user. Default is `true`.
*`allowRunningInsecureContent` boolean (optional) - Allow an https page to run
JavaScript, CSS or plugins from http URLs. Default is `false`.
@@ -156,6 +156,8 @@
`WebContents` when the preferred size changes. Default is `false`.
* `transparent` boolean (optional) - Whether to enable background transparency for the guest page. Default is `true`. **Note:** The guest page's text and background colors are derived from the [color scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme) of its root element. When transparency is enabled, the text color will still change accordingly but the background will remain transparent.
*`enableDeprecatedPaste` boolean (optional) _Deprecated_ - Whether to enable the `paste` [execCommand](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand). Default is `false`.
*`focusOnNavigation` boolean (optional) - Whether to focus the WebContents
@@ -383,7 +383,7 @@ Emitted after a server side redirect occurs during navigation. For example a 30
redirect.
This event cannot be prevented, if you want to prevent redirects you should
checkout out the `will-redirect` event above.
check out the `will-redirect` event above.
#### Event: 'did-navigate'
@@ -933,7 +933,7 @@ copying data between CPU and GPU memory, with Chromium's hardware acceleration s
Only a limited number of textures can exist at the same time, so it's important that you call `texture.release()` as soon as you're done with the texture.
By managing the texture lifecycle by yourself, you can safely pass the `texture.textureInfo` to other processes through IPC.
More details can be found in the [offscreen rendering tutorial](../tutorial/offscreen-rendering.md). To learn about how to handle the texture in native code, refer to [offscreen rendering's code documentation.](https://github.com/electron/electron/blob/main/shell/browser/osr/README.md).
More details can be found in the [offscreen rendering tutorial](../tutorial/offscreen-rendering.md). To learn about how to handle the texture in native code, refer to [offscreen rendering's code documentation.](../../shell/browser/osr/README.md).
```js
const { BrowserWindow } = require('electron')
@@ -1465,7 +1465,7 @@ Ignore application menu shortcuts while this web contents is focused.
without a recognized 'action' value will result in a console error and have
the same effect as returning `{action: 'deny'}`.
Called before creating a window a new window is requested by the renderer, e.g.
Called before creating a window when a new window is requested by the renderer, e.g.
by `window.open()`, a link with `target="_blank"`, shift+clicking on a link, or
submitting a form with `<form target="_blank">`. See
[`window.open()`](window-open.md) for more details and how to use this in
// For `background-tab` disposition (e.g., when middle-clicking or ctrl/cmd-clicking a link),
// `options.webContents` is undefined because its creation can be deferred. So load the URL manually.
if (details.disposition === 'background-tab') {
browserView.webContents.loadURL(details.url)
}
return browserView.webContents
}
}
@@ -1748,11 +1753,12 @@ Returns `Promise<PrinterInfo[]>` - Resolves with a [`PrinterInfo[]`](structures/
* `footer` string (optional) - string to be printed as page footer.
* `pageSize` string | Size (optional) - Specify page size of the printed document. Can be `A0`, `A1`, `A2`, `A3`,
`A4`, `A5`, `A6`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width`.
* `usePrinterDefaultPageSize` boolean (optional) - Whether to use a given printer's default page size. Default is `false`. Cannot be combined with `pageSize`. When `deviceName` is provided, uses the default page size of that specific printer. When `deviceName` is not provided, uses the default page size of the system's default printer. If the printer's default page size cannot be retrieved, falls back to A4 (210mm x 297mm).
* `callback` Function (optional)
* `success` boolean - Indicates success of the print call.
* `failureReason` string - Error description called back if the print fails.
When a custom `pageSize` is passed, Chromium attempts to validate platform specific minimum values for `width_microns` and `height_microns`. Width and height must both be minimum 353 microns but may be higher on some operating systems.
When a custom `pageSize` is passed, Chromium attempts to validate platform specific minimum values for `width_microns` and `height_microns`. Width and height must both be minimum 353 microns but may be higher on some operating systems. If a valid `pageSize` is not passed and `usePrinterDefaultPageSize` is `false`, an error will be thrown.
Prints window's web page. When `silent` is set to `true`, Electron will pick
the system's default printer if `deviceName` is empty and the default settings for printing.
@@ -2168,7 +2174,7 @@ Returns `boolean` - If _offscreen rendering_ is enabled returns whether it is cu
* `fps` Integer
If _offscreen rendering_ is enabled sets the frame rate to the specified number.
Only values between 1 and 240 are accepted.
When `webPreferences.offscreen.useSharedTexture` is `false` only values between 1 and 240 are accepted.
#### `contents.getFrameRate()`
@@ -2234,6 +2240,16 @@ Returns `string` - The identifier of a WebContents stream. This identifier can b
with `navigator.mediaDevices.getUserMedia` using a `chromeMediaSource` of `tab`.
The identifier is restricted to the web contents that it is registered to and is only valid for 10 seconds.
@@ -588,6 +588,7 @@ Stops any `findInPage` request for the `webview` with the provided `action`.
* `footer` string (optional) - string to be printed as page footer.
* `pageSize` string | Size (optional) - Specify page size of the printed document. Can be `A3`,
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` in microns.
* `usePrinterDefaultPageSize` boolean (optional) - Whether to use the system's default page size. Default is `false`. Cannot be combined with `pageSize`. When `deviceName` is provided, uses the default page size of that specific printer. When `deviceName` is not provided, uses the default page size of the system's default printer. If the printer's default page size cannot be retrieved, falls back to A4 (210mm x 297mm).
* JavaScript will always be disabled in the opened `window` if it is disabled on
the parent window.
*Non-standard features (that are not handled by Chromium or Electron) given in
`features` will be passed to any registered `webContents`'s
`did-create-window` event handler in the `options` argument.
*Features that are not handled by Chromium and not in Electron's allowlist of
presentational `BrowserWindowConstructorOptions` are ignored. The raw
`features` string is still available to the main process via
`setWindowOpenHandler`.
*`frameName` follows the specification of `target` located in the [native documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#parameters).
* When opening `about:blank`, the child window's [`WebPreferences`](structures/web-preferences.md) will be copied
from the parent window, and there is no way to override it because Chromium
@@ -20,6 +20,14 @@ Previously, PDF resources created a separate guest [WebContents](https://www.ele
Under the hood, Chromium [enabled](https://chromium-review.googlesource.com/c/chromium/src/+/7239572) a feature that changes PDFs to use out-of-process iframes (OOPIFs) instead of the `MimeHandlerViewGuest` extension.
### Behavior Changed: Updated Cookie Change Cause in the Cookie 'changed' Event
We have updated the [cookie](https://www.electronjs.org/docs/latest/api/cookies#event-changed) change cause in the cookie 'changed' event.
When a new cookie is set, the change cause is `inserted`.
When a cookie is deleted, the change cause remains `explicit`.
When the cookie being set is identical to an existing one (same name, domain, path, and value, with no actual changes), the change cause is `inserted-no-change-overwrite`.
When the value of the cookie being set remains unchanged but some of its attributes are updated, such as the expiration attribute, the change cause will be `inserted-no-value-change-overwrite`.
## Planned Breaking API Changes (40.0)
### Deprecated: `clipboard` API access from renderer processes
@@ -33,6 +41,12 @@ your preload script and expose it using the [contextBridge](https://www.electron
Debug symbols for MacOS (dSYM) now use xz compression in order to handle larger file sizes. `dsym.zip` files are now
`dsym.tar.xz` files. End users using debug symbols may need to update their zip utilities.
### Deprecated: `showHiddenFiles` in Dialogs on Linux
This property will still be honored on macOS and Windows, but support on Linux
will be removed in Electron 42. GTK intends for this to be a user choice rather
than an app choice and has removed the API to do this programmatically.
## Planned Breaking API Changes (39.0)
### Deprecated: `--host-rules` command line switch
### Behavior Changed: `NSAudioCaptureUsageDescription` should be included in your app's Info.plist file to use `desktopCapturer` (🍏 macOS ≥14.2)
Per [Chromium update](https://source.chromium.org/chromium/chromium/src/+/ad17e8f8b93d5f34891b06085d373a668918255e) which enables Apple's newer [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps#Configure-the-sample-code-project) by default, you now must have `NSAudioCaptureUsageDescription` defined in your `Info.plist` to use `desktopCapturer`.
Electron's `desktopCapturer` will create a dead audio stream if the new permission is absent however no errors or warnings will occur. This is partially a side-effect of Chromium not falling back to the older `Screen & System Audio Recording` permissions system if the new system fails.
To restore previous behavior:
```js
// main.js (right beneath your require/import statments)
app.commandLine.appendSwitch(
'disable-features',
'MacCatapLoopbackAudioForScreenShare'
)
```
### Behavior Changed: shared texture OSR `paint` event data structure
When using shared texture offscreen rendering feature, the `paint` event now emits a more structured object.
@@ -76,7 +106,7 @@ Users can force XWayland by passing `--ozone-platform=x11`.
Previously, Electron changed the value of `XDG_CURRENT_DESKTOP` internally to `Unity`, and stored the original name of the desktop session
in a separate variable. `XDG_CURRENT_DESKTOP` is no longer overriden and now reflects the actual desktop environment.
in a separate variable. `XDG_CURRENT_DESKTOP` is no longer overridden and now reflects the actual desktop environment.
### Removed: macOS 11 support
@@ -157,7 +187,7 @@ window is not currently visible.
`app.commandLine` was only meant to handle chromium switches (which aren't case-sensitive) and switches passed via `app.commandLine` will not be passed down to any of the child processes.
If you were using `app.commandLine` to control the behavior of the main process, you should do this via `process.argv`.
If you were using `app.commandLine` to control the behavior of the main process, you should do this via `process.argv`.
### Deprecated: `NativeImage.getBitmap()`
@@ -187,7 +217,7 @@ from upstream Chromium.
### Deprecated: `null` value for `session` property in `ProtocolResponse`
Previously, setting the ProtocolResponse.session property to `null`
Would create a random independent session. This is no longer supported.
would create a random independent session. This is no longer supported.
Using single-purpose sessions here is discouraged due to overhead costs;
however, old code that needs to preserve this behavior can emulate it by
@@ -198,7 +228,7 @@ and then using it in `ProtocolResponse.session`.
When calling `Session.clearStorageData(options)`, the `options.quota`
property is deprecated. Since the `syncable` type was removed, there
is only type left -- `'temporary'` -- so specifying it is unnecessary.
is only one type left -- `'temporary'` -- so specifying it is unnecessary.
### Deprecated: Extension methods and events on `session`
@@ -527,7 +557,7 @@ more information.
### Removed: The `--disable-color-correct-rendering` switch
This switch was never formally documented but it's removal is being noted here regardless. Chromium itself now has better support for color spaces so this flag should not be needed.
This switch was never formally documented but its removal is being noted here regardless. Chromium itself now has better support for color spaces so this flag should not be needed.
### Behavior Changed: `BrowserView.setAutoResize` behavior on macOS
@@ -1218,7 +1248,7 @@ more details.
### API Changed: `webContents.printToPDF()`
`webContents.printToPDF()` has been modified to conform to [`Page.printToPDF`](https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF) in the Chrome DevTools Protocol. This has been changes in order to
`webContents.printToPDF()` has been modified to conform to [`Page.printToPDF`](https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF) in the Chrome DevTools Protocol. This has been changed in order to
address changes upstream that made our previous implementation untenable and rife with bugs.
@@ -6,7 +6,7 @@ This is not a comprehensive end-all guide to creating an Electron Browser API, r
## Add your files to Electron's project configuration
Electron uses [GN](https://gn.googlesource.com/gn) as a meta build system to generate files for its compiler, [Ninja](https://ninja-build.org/). This means that in order to tell Electron to compile your code, we have to add your API's code and header file names into [`filenames.gni`](https://github.com/electron/electron/blob/main/filenames.gni).
Electron uses [GN](https://gn.googlesource.com/gn) as a meta build system to generate files for its compiler, [Ninja](https://ninja-build.org/). This means that in order to tell Electron to compile your code, we have to add your API's code and header file names into [`filenames.gni`](../../filenames.gni).
You will need to append your API file names alphabetically into the appropriate files like so:
In the [`typings/internal-ambient.d.ts`](https://github.com/electron/electron/blob/main/typings/internal-ambient.d.ts) file, we need to append a new property onto the `Process` interface like so:
In the [`typings/internal-ambient.d.ts`](../../typings/internal-ambient.d.ts) file, we need to append a new property onto the `Process` interface like so:
In your [`shell/common/node_bindings.cc`](https://github.com/electron/electron/blob/main/shell/common/node_bindings.cc) file, add your node binding name to Electron's built-in modules.
In your [`shell/common/node_bindings.cc`](../../shell/common/node_bindings.cc) file, add your node binding name to Electron's built-in modules.
```cpp title='shell/common/node_bindings.cc'
#define ELECTRON_BROWSER_MODULES(V) \
@@ -159,7 +159,7 @@ We will need to create a new TypeScript file in the path that follows:
Note that `git-import-patches` will mark the commit that was `HEAD` when it was run as `refs/patches/upstream-head`. This lets you keep track of which commits are from Electron patches (those that come after `refs/patches/upstream-head`) and which commits are in upstream (those before `refs/patches/upstream-head`).
Note that `git-import-patches` will mark the commit that was `HEAD` when it was run as `refs/patches/upstream-head` (and a checkout-specific `refs/patches/upstream-head-<hash>` so that gclient worktrees sharing a `.git/refs` directory don't clobber each other). This lets you keep track of which commits are from Electron patches (those that come after `refs/patches/upstream-head`) and which commits are in upstream (those before `refs/patches/upstream-head`).
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.