Compare commits

..

162 Commits

Author SHA1 Message Date
Samuel Attard
30cf60a935 fix: propagate requesting frame through sync permission checks (#50679)
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.
2026-04-04 15:59:25 -07:00
Charles Kerr
ec30e4cdae refactor: remove unused field ServiceWorkerMain.start_worker_promise_ (#50674)
added in a467d068 but never used.
2026-04-04 14:22:48 -05:00
Samuel Attard
40033db422 chore: resolve dependabot security alerts (#50680) 2026-04-04 11:56:48 -07:00
Samuel Attard
c3d441cf7d ci: add Datadog metrics to clean-src-cache job (#50642)
* ci: add Datadog metrics to clean-src-cache job

Report free space (before/after cleanup), space freed, and total space
for both cross-instance-cache and win-cache volumes to Datadog, matching
the pattern used in the macOS disk cleanup workflow.

https://claude.ai/code/session_013bpDsZLrFDpWMiARNFH4z9

* ci: use awk instead of bc, add workflow_dispatch trigger

- Replace bc with awk for KB-to-GB conversion since bc may not be
  available in the container image
- Add workflow_dispatch trigger for manual testing

https://claude.ai/code/session_013bpDsZLrFDpWMiARNFH4z9

* ci: remove workflow_dispatch, handled in another PR

https://claude.ai/code/session_013bpDsZLrFDpWMiARNFH4z9

* ci: move DD_API_KEY to job-level env for if-condition

The step-level env is not available when GitHub evaluates the step's
if expression, so env.DD_API_KEY was always empty. Move it to
job-level env so the conditional works correctly.

https://claude.ai/code/session_013bpDsZLrFDpWMiARNFH4z9

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-03 22:17:29 -07:00
Charles Kerr
14583d22e6 refactor: remove use of deprecated API base::GetProc() (#50650)
* refactor: replace deprecated API base::GetProcId() in web_frame_main

* refactor: replace deprecated API base::GetProcId() in web_contents

* refactor: replace deprecated API base::GetProcId() in a11y ui

* refactor: frame.osProcessId now returns 0 instead of -1 for invalid processes.

This is consistent with WebContents.getOSProcessId
2026-04-03 15:48:41 -05:00
Charles Kerr
68bfe49120 refactor: remove never-used JS API (#50649)
* chore: do not expose v8Util.getObjectHash() to JS

Not used, documented, or typed. Added in ddad3e4846.

* chore: do not expose DownloadItem.isDone() to JS

Not used, documented, or typed. Added in dcad25c98c.

* chore: do not expose BrowserWindow.isWebViewFocused() to JS

Not used, documented, or typed. Added in a949e9542d.
2026-04-03 13:04:27 -05:00
Kunal Dubey
2c6332a7d6 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.
2026-04-03 18:04:55 +02:00
Bohdan Tkachenko
ddc1bd9553 fix: forward activation token from libnotify on notification click (#50568)
* feat: forward activation token from libnotify notification clicks

When a notification action is clicked on Linux, retrieve the activation
token from libnotify (if available) via dlsym and set it using
`base::nix::SetActivationToken()`. This enables proper window focus
handling under Wayland, where the compositor requires a valid activation
token to grant focus to the application.

The `notify_notification_get_activation_token` symbol is resolved at
runtime to maintain compatibility with older libnotify versions that
do not expose this API.

* refactor: simplify libnotify soname loading and activation token lookup

Replace the chained Load() calls with a loop over a constexpr array of
sonames, and inline the lazy EnsureActivationTokenFunc() into
Initialize() since it is only called once and the library handle is
already known at that point.
2026-04-03 10:40:36 -05:00
Shelley Vohr
12109371d3 fix: validate dock_state_ against allowlist before JS execution (#50646)
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
2026-04-03 10:39:16 -05:00
Charles Kerr
69891d04bf test: improve cookie changed event coverage (#50655)
test: add tests for cookie changed overwrite and inserted

test: add tests for cookie changed inserted-no-value-change-overwrite

test: add tests for cookie changed expired-overwrite
2026-04-03 10:26:17 -05:00
David Sanders
188813e206 ci: fix pulling previous object checksums (#50635)
* ci: fix pulling previous object checksums

* chore: fix artifact finding

* chore: skip unpack

* refactor: dawidd6/action-download-artifact can't handle non-archived artifacts

Assisted-by: Claude Opus 4.6

* refactor: use Octokit in standalone script

Assisted-by: Claude Opus 4.6
2026-04-03 04:52:50 +00:00
Charles Kerr
8b768b8211 chore: stop exposing unused menu methods to JS (#50634)
* chore: remove unused undocumented API `menu.worksWhenHiddenAt()`.

Not used, documented, or typed. Added by 544d8a423c.

* chore: remove unused undocumented API `menu.getCommandIdAt()

Not used, documented, or typed. Added by dae98fa43f.

* chore: do not expose `menu.getIndexOfCommandId()` to JS

Added by dae98fa43f but not documented, typed, or used by JS code.

The C++ method is used by other shell code, but not in JS.

* chore: remove unused undocumented API `menu.getLabelAt()`

Not used, documented, or typed. Added by dae98fa43f.

* chore: remove unused undocumented API `menu.getToolTipAt()`

Not used, documented, or typed. Added by 06d48514c6.

* chore: remove unused undocumented API `menu.getSubLabelAt()`

Not used, documented, or typed. Added by dae98fa43f.
2026-04-02 22:04:18 -05:00
Mitchell Cohen
82b97ddf5b ci: run BrowserWindow test spec on Wayland (#50572)
add browserwindow test spec for wayland
2026-04-02 17:19:23 -05:00
Charles Kerr
16f408a502 chore: remove declaration for nonexistent method WebContents._getPrintersAsync() (#50628)
chore: remove declaration for nonexistent method WebContents._getPrintersAsync()

added in 8f51d3e1 but never implemented / never used
2026-04-02 15:29:10 -05:00
Michaela Laurencin
246aa63910 ci: correct contributing link and add link to ai tool policy (#50632)
* ci: correct contributing link and add link to ai tool policy

* add missing bracket
2026-04-02 13:54:13 -05:00
Shelley Vohr
230f02faf2 fix: don't force kFitToPrintableArea scaling when custom margins are set (#50615)
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.
2026-04-02 20:41:21 +02:00
Charles Kerr
1362d7b94d refactor: remove unused internal method WebContents.equal() (#50626)
refactor: remove unused internal method WebContents.equal()

last use removed in Feb 2021 @ 51bb0ad36d
2026-04-02 12:46:39 -05:00
Mitchell Cohen
877fe479b5 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
2026-04-02 09:52:27 -05:00
Shelley Vohr
f41438ff73 fix: prefill native print dialog options on macOS with OOP printing (#50600)
Chromium enabled out-of-process (OOP) printing by default on macOS in
https://chromium-review.googlesource.com/c/chromium/src/+/6032774. This
broke webContents.print() option prefilling (e.g. copies, collate,
duplex) in two ways:

1. ScriptedPrint() silently aborted because RegisterSystemPrintClient()
   was only called from GetDefaultPrintSettings(), but Electron's flow
   calls UpdatePrintSettings() instead when options are provided.

2. PrinterQueryOop::UpdatePrintSettings() sends settings to the remote
   PrintBackend service, but on macOS the native dialog runs in-browser
   using the local PrintingContextMac::print_info_, which was never
   updated with the user's requested settings.

Fix by registering the system print client in UpdatePrintSettings() and
applying cached settings to the local printing context before showing
the in-browser system print dialog.
2026-04-02 16:06:35 +02:00
Shelley Vohr
c6e201c965 build: allow clearing src & cross mnt cache via dispatch (#50638) 2026-04-02 10:01:08 +00:00
Niklas Wenzel
156a4e610c fix: extension service workers not starting beyond first app launch (#50611)
* fix: extension service worker not starting beyond first app launch

* fix: set preference only for extensions with service workers
2026-04-02 10:02:06 +02:00
Charles Kerr
81f8fc1880 refactor: remove unused internal method contents.canGoToIndex() (#50606)
refactor: remove unused internal method contents.canGoToIndex()

refactor: make WebContents::CanGoToIndex() private

The JS binding has been unused since 2021-04-27 #28839 0a1b26b1
2026-04-01 22:37:41 +02:00
Charles Kerr
343d6e5f3f test: add tests for navigationHistory.goToIndex() (#50607)
test: add tests for navigationHistory.goToIndex()
2026-04-01 22:37:19 +02:00
Asish Kumar
e7080835f1 docs: add destroy method to native addon tutorials to prevent hang on quit (#50561)
Native addons that hold persistent references to callbacks, emitters,
and threadsafe functions prevent Electron from quitting cleanly since
Electron 40.5.0 due to changes in Node.js shutdown behavior. This adds
a `destroy()` method to all four native code tutorials (Swift macOS,
Obj-C macOS, C++ Linux, C++ Win32) that releases these resources and
must be called before app quit.

The destroy method resets callback and emitter references and aborts the
threadsafe function, allowing the addon's destructor to run properly.
An [!IMPORTANT] note is added to each tutorial's JavaScript wrapper
section explaining when and why to call destroy().

Fixes #50457

Signed-off-by: Asish Kumar <officialasishkumar@gmail.com>
2026-04-01 13:13:09 -05:00
LiRongWan
7c1a6f7e95 docs: recommend subdirectory for userData to avoid Chromium conflicts (#50563)
Fixes #45414

Storing files directly in the userData root can cause naming conflicts
with Chromium's own subdirectories (Cache, GPUCache, Local Storage, etc.).
Added a recommendation to use a subdirectory such as
path.join(app.getPath('userData'), 'my-app-data') instead.

Notes: no-notes
2026-04-01 09:54:08 -05:00
Calvin
22ac2b13fb fix: remove menu update debug log (#50608) 2026-04-01 17:06:26 +09:00
Samuel Attard
a8acb96608 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.
2026-03-31 20:23:43 +00:00
Mitchell Cohen
97773bf50c fix: prevent borders and smearing in transparent frameless/client frame windows on Linux (#50541)
fix the appearance of transparent frameless and client frame windows
2026-03-31 11:24:10 -05:00
Shelley Vohr
1e0846749b fix: invoke print callback directly when no print job exists (#50431)
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.
2026-03-31 11:01:59 -05:00
electron-roller[bot]
8cd766ff53 chore: bump chromium to 148.0.7763.0 (main) (#50582) 2026-03-31 10:16:35 +02:00
dependabot[bot]
e5b20a11d2 build(deps): bump github/codeql-action from 4.34.1 to 4.35.1 (#50590)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.34.1 to 4.35.1.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](3869755554...c10b8064de)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.35.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 10:15:41 +02:00
Alexey
e0bd4ffc39 fix: add missing HandleScope in contentTracing.getTraceBufferUsage() (#50556)
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
2026-03-31 10:21:43 +09:00
Samuel Attard
bbbcae1a12 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.
2026-03-30 14:13:00 -07:00
Samuel Attard
3e1666be08 chore: remove dead C++ code from shell/ (#50513)
Removes unreferenced code found via codebase sweep. Each category below may
indicate a missing feature rather than truly-unused code — see PR description.

Dead class (1):
  ElectronNavigationUIData — never instantiated; ElectronBrowserClient uses
  upstream ExtensionNavigationUIData directly

Unused methods (7):
  CertificateManagerModel: ImportUserCert, ImportCACerts, ImportServerCert,
    Delete, is_user_db_available (only PKCS12 path is used)
  AutofillDriverFactory::AddDriverForFrame + CreationCallback type
  ZoomLevelDelegate::SetDefaultZoomLevelPref
  gtk_util: GetOpenLabel, GetSaveLabel

Unused members (2):
  AutofillPopup::selected_index_
  InspectableWebContents::synced_setting_names_

Declaration fixes (6):
  menu_util.h: BuildMenuItemWithImage signature corrected (GtkWidget* → gfx::Image&)
  win_frame_view.h: GetReadableFeatureColor (impl removed, decl left behind)
  frameless_view.h: friend class NativeWindowsViews (typo, class does not exist)
  Forward decls: WebDialogHelper, ChromeContentRendererClient,
    ElectronNativeWindowObserver, ValueStoreFactory
2026-03-30 10:36:00 -07:00
electron-roller[bot]
a06b49aca1 chore: bump chromium to 148.0.7759.0 (main) (#50515)
* chore: bump chromium in DEPS to 148.0.7755.0

* chore: bump chromium in DEPS to 148.0.7756.0

* chore: update patches

* 7698536: Wire up experiment arms for Glic summarize pdf button.

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7698536

* 7695602: Include gperf to sources for iOS builds

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7695602

* 7671200: Expose IgnoreDuplicateNavs in WebView

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7671200

* chore: bump chromium in DEPS to 148.0.7758.0

* chore: update patches

* 7701873: Allow running completion callbacks directly in CommitPresentedFrameToCA() on Mac

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7701873

* 7697732: Enhance diagnostic logging for ScreenCaptureKit errors on macOS

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7697732

* 7698176: Disallow cookies with empty name and ambiguous value

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7698176

* 7607319: Code Health: Use span in base::HexEncode

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7607319

* chore: bump chromium in DEPS to 148.0.7759.0

* chore: update patches

* 7696478: [extensions] Move StreamContainer to extensions/browser/mime_handler/

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7696478

* 7656748: Fixed controlled frame fullscreen crash

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7656748

* chore: update patches

* fixup! 7696478: [extensions] Move StreamContainer to extensions/browser/mime_handler/

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2026-03-30 10:32:35 -07:00
Keeley Hammond
d318893aa0 fix: fix devtools patch type error on release builds (#50551)
fix: fix devtools types
2026-03-27 22:40:51 +00:00
Keeley Hammond
f133e2f775 refactor: improve input handling in FilePath gin converter (#50540)
refactor: improve input handling in file_path_converter

Properly handle paths containing ASCII control characters in the FilePath gin converter
2026-03-27 14:30:58 -04:00
John Kleinschmidt
b44b9ba316 ci: update nick-fields/retry to v4.0.0 (#50521) 2026-03-27 13:44:06 -04:00
dependabot[bot]
d5e4429724 build(deps-dev): bump @datadog/datadog-ci from 4.1.2 to 5.9.1 (#50407)
Bumps [@datadog/datadog-ci](https://github.com/DataDog/datadog-ci/tree/HEAD/packages/datadog-ci) from 4.1.2 to 5.9.1.
- [Release notes](https://github.com/DataDog/datadog-ci/releases)
- [Commits](https://github.com/DataDog/datadog-ci/commits/v5.9.1/packages/datadog-ci)

---
updated-dependencies:
- dependency-name: "@datadog/datadog-ci"
  dependency-version: 5.9.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 13:29:15 -04:00
John Kleinschmidt
8f11366f50 ci: don't request review for PRs in draft or WIP (#50539) 2026-03-27 13:27:52 -04:00
electron-roller[bot]
0dabcfdec4 chore: bump node to v24.14.1 (main) (#50480)
* chore: bump node in DEPS to v24.14.1

* chore: update patches

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2026-03-27 13:26:58 -04:00
Hichem
b4460a05da docs: Document known issue with dock.hide() method (#50476)
* Document known issue for dock.hide() method

Added a note about a known issue with dock.hide() method.

* Adjust workaround time for dock.hide() method

Updated workaround time for dock.hide() known issue.

* Fix known issue timing for dock.hide() workaround

Updated the workaround time in the known issue section for dock.hide() to 1000ms.

* Adjust workaround delay for dock.hide() method

Updated workaround time for dock.hide() known issue.
2026-03-27 10:00:04 -04:00
Niklas Wenzel
0a1ea1f028 docs: clarify allowed characters in protocol names (#50411) 2026-03-27 09:39:16 -04:00
Mitchell Cohen
b41ec6586a fix: correct linux zygote process titles (#50509)
* fix: correct linux zygote process titles

* pass argv on mac as well

* lint
2026-03-27 08:24:05 -04:00
Niklas Wenzel
4eff8f20f2 feat: make Chrome extensions work on custom protocols (#49951) 2026-03-26 20:00:51 -04:00
Shelley Vohr
8cb61e8b9b test: add interactive macOS dialog tests (#50363) 2026-03-26 17:06:03 -04:00
WofWca
b9731b89dc docs: update Notification support info (#50364)
This is a follow-up to
74fd10450f
(https://github.com/electron/electron/pull/48132).
The support for these has been added for Windows,
but not all documentation has been updated accordingly

Co-authored-by: Charles Kerr <charles@charleskerr.com>
2026-03-26 17:04:34 -04:00
dependabot[bot]
d64e1146dd build(deps): bump actions/download-artifact from 7.0.0 to 8.0.1 (#50444)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7.0.0 to 8.0.1.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v7...3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-26 16:17:53 -04:00
Jan Hannemann
ae6b219545 fix: outdated execution path for COM activation (#50471)
* fix: outdated execution path

* fix: use stub exe when detected
2026-03-26 18:21:58 +00:00
electron-roller[bot]
c44d60cfe4 chore: bump chromium to 148.0.7751.0 (main) (#50427)
* chore: bump chromium in DEPS to 148.0.7749.0

* chore: bump chromium in DEPS to 148.0.7751.0

* chore: update patches

* 7681299: Introduce OccludedWidgetInputProtector to track always-on-top widgets

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7681299

* 7685453: chrome://accessibility: Don't AllowJavascript() in async calls

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7685453

* 7665878: Prefer browser runtime over Node.js in HostRuntime detection

Refs https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7665878

* 7674037: Rename the bookmark-related interfaces of the Clipboard class to URL.

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7674037

* 7621713: Migrate ServiceWorker framework to ChildProcessId

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7621713

* 7680500: Migrate ServiceWorkerHost to ChildProcessId

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7680500

* chore: update roller commit message lint script to handle devtools CLs

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2026-03-26 10:18:24 -04:00
Samuel Attard
9928c7d828 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>
2026-03-26 14:02:50 +00:00
David Sanders
f5bc6f7949 ci: fix variable name when downloading previous object checkusms (#50510) 2026-03-26 09:31:30 -04:00
Keeley Hammond
a839fb94aa fix: [a11y] fire AXMenuOpened event when ARIA menu is added to DOM (#50377)
* fix: fire AXMenuOpened event when a visible ARIA menu instance is added to the DOM

* 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.

* chore: add feature flag (kDynamicMenuPopupEvents)

* chore: update patches
2026-03-25 21:33:49 +00:00
Michaela Laurencin
2e2c56adde ci: add functionality for programmatic add/remove needs-signed-commits label (#50316)
* remove comment based label removal

* ci: add functionality for programmatic add/remove needs-signed-commits label

* add new line to pull-request-opened-synchronized
2026-03-25 15:38:44 -04:00
Samuel Attard
678adeaf7c fix: crash calling OSR shared texture release() after texture GC'd (#50473)
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.
2026-03-25 10:48:41 -07:00
Samuel Attard
1d14694dec refactor: remove dead named-window lookup from guest-window-manager (#50474)
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.
2026-03-25 10:48:30 -07:00
Samuel Attard
a48f03fb8d fix: crash in clipboard.readImage() on malformed image data (#50475)
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.
2026-03-25 10:47:00 -07:00
Shelley Vohr
f6b43cb0ef fix: fall back to default DPI when GTK returns 0 on Linux (#50453)
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.
2026-03-25 12:37:40 -05:00
Shelley Vohr
7451d560ba fix: register PrintDialogLinuxFactory on Linux (#50430)
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").
2026-03-25 12:37:03 -05:00
Damglador
27edd6e21c fix: pulseaudio stream and icon names (#49270)
Use platform_util::GetXdgAppId() with fallback to argv0 as PA_PROP_APPLICATION_ICON_NAME.
Use electron::GetPossiblyOverriddenApplicationName()
to set environment variable "ELECTRON_PA_APP_NAME" in audio_service.cc,
to use it in pulse_util.cc for setting input/output pa_context name.

This replaces hard-codded kBrowserDisplayName that was used for PA_PROP_APPLICATION_ICON_NAME,
and PRODUCT_STRING that was used for pa_context names.

This is done to make audio streams recognizable in tools like qpwgrapth and general audio managers,
instead of having 20 "Chromium" outputs and "Chromium input" inputs, that are actually coming from
completely different applications.
2026-03-25 12:25:44 -05:00
Shelley Vohr
ec3a18d438 fix: hex-encode Windows notification icon temp filenames (#50454)
* 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.

* Update shell/browser/notifications/win/notification_presenter_win.cc

Co-authored-by: Robo <hop2deep@gmail.com>

---------

Co-authored-by: Robo <hop2deep@gmail.com>
2026-03-25 09:29:58 -07:00
Samuel Attard
02d4101ca3 chore: remove redundant chromium patches (#50463)
- export_gin_v8platform_pageallocator_for_usage_outside_of_the_gin.patch:
  gin::V8Platform::GetPageAllocator() is now exported upstream via the
  public v8::Platform interface, so we no longer need to patch gin to
  expose a custom accessor. Update javascript_environment.cc to use the
  upstream API instead.

- fix_getcursorscreenpoint_wrongly_returns_0_0.patch: this fix has
  landed upstream in Chromium and is no longer needed as a local patch.
2026-03-24 17:21:13 -07:00
Keeley Hammond
fdaba4c6b0 chore: add CODEOWNERS for .claude folder (#50434)
Add wg-infra as code owners for the .claude folder to protect
Claude Code configuration files from unauthorized modifications.

https://claude.ai/code/session_01YK2mEzC3DLrhqbcXW9jwUr

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-24 15:39:35 -07:00
Robo
542ff828ab refactor: SafeV8Function to be backed by cppgc (#50397)
* refactor: SafeV8Function to be backed by cppgc

* spec: focus renderer before attempting paste

* spec: remove listeners to prevent leak on failed tests
2026-03-24 16:59:32 -05:00
pranjal-ogg
4371a4dceb docs: add cold-start deep link handling example (#49142)
docs: handle cold-start deep links on Windows/Linux

add a check for `process.argv` in the `app.whenReady()` callback to handle deep links when the application is cold-started on Windows and Linux.
2026-03-24 13:28:53 -05:00
dependabot[bot]
60f4b07723 build(deps): bump actions-cool/issues-helper from 3.7.6 to 3.8.0 (#50446)
Bumps [actions-cool/issues-helper](https://github.com/actions-cool/issues-helper) from 3.7.6 to 3.8.0.
- [Release notes](https://github.com/actions-cool/issues-helper/releases)
- [Changelog](https://github.com/actions-cool/issues-helper/blob/main/CHANGELOG.md)
- [Commits](71b62d7da7...200c78641d)

---
updated-dependencies:
- dependency-name: actions-cool/issues-helper
  dependency-version: 3.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-24 13:28:30 -05:00
dependabot[bot]
f282bec8ef build(deps): bump github/codeql-action from 4.33.0 to 4.34.1 (#50447)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.33.0 to 4.34.1.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](b1bff81932...3869755554)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.34.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-24 13:28:12 -05:00
dependabot[bot]
cef388de3d build(deps): bump actions/github-script from 7.0.1 to 8.0.0 (#50445)
Bumps [actions/github-script](https://github.com/actions/github-script) from 7.0.1 to 8.0.0.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v7.0.1...ed597411d8f924073f98dfc5c65a23a2325f34cd)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-24 09:54:56 -05:00
Anirudh Sevugan
1828690467 fix: deprecate ELECTRON_SKIP_BINARY_DOWNLOAD env (#50406)
* fix: remove ELECTRON_SKIP_BINARY_DOWNLOAD

it is redundant as of electron v42
its purpose was to skip the binary download for post install script
but as of electron v42, post install script is gone
and replaced with a lazy download

it was also slated for removal in [this comment](https://github.com/electron/rfcs/pull/22#issuecomment-3387307743)

* docs: remove ELECTRON_SKIP_BINARY_DOWNLOAD section

the env is redundant as of electron v42
so docs don't have to mention it anymore

* docs: add ELECTRON_SKIP_BINARY_DOWNLOAD to breaking changes
2026-03-24 09:42:15 -04:00
David Sanders
f4c4cd14ac ci: upload object change stats to Datadog (#50390)
* ci: upload object change stats to Datadog

Assisted-by: Claude Opus 4.6

* ci: bump actions/upload-artifact version

* chore: only output new object count if non-zero

* chore: skip object change tracking on ASan builds

* chore: handle pull requests as well

* chore: always set chromium-version-changed

* chore: remove npx usage
2026-03-23 18:51:02 -07:00
dependabot[bot]
3db3996102 build(deps): bump dsanders11/project-actions from 1.7.0 to 2.0.0 (#50448)
Bumps [dsanders11/project-actions](https://github.com/dsanders11/project-actions) from 1.7.0 to 2.0.0.
- [Release notes](https://github.com/dsanders11/project-actions/releases)
- [Commits](2134fe7cc7...5767984408)

---
updated-dependencies:
- dependency-name: dsanders11/project-actions
  dependency-version: 2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 21:42:24 -04:00
Samuel Attard
dbcf0fb5f0 fix: lazily initialize safeStorage async encryptor (#50419)
* fix: lazily initialize safeStorage async encryptor

The SafeStorage constructor previously registered a browser observer that
called os_crypt_async()->GetInstance() on app-ready. Because ESM named
imports (import { x } from 'electron') eagerly evaluate all electron
module getters, simply importing electron in an ESM entrypoint would
construct SafeStorage and touch the OS keychain on app-ready, even when
safeStorage was never used.

This showed up as a macOS CI hang: the esm-spec import-meta fixture
triggers a keychain access prompt that blocks the test runner until
timeout.

Now the async encryptor is requested lazily on the first call to
encryptStringAsync, decryptStringAsync, or isAsyncEncryptionAvailable.
isAsyncEncryptionAvailable now returns a Promise that resolves once
initialization completes, matching what the docs already stated.

* chore: lint

* fix: add HandleScope in OnOsCryptReady for pending operations

OnOsCryptReady fires asynchronously from a posted task without an active
V8 HandleScope. Previously this was harmless because eager init meant the
pending queues were always empty when it fired. With lazy init, operations
queue up first, then the callback processes them and needs to create V8
handles (Buffer::Copy, Dictionary::CreateEmpty, Promise::Resolve).
2026-03-23 10:47:14 -07:00
Samuel Attard
29750dda08 build: enable V8 builtins PGO (#50416)
* 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.

* 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.
2026-03-23 11:54:43 -04:00
electron-roller[bot]
6df6ec5f09 chore: bump chromium to 148.0.7741.0 (main) (#50336)
* chore: bump chromium in DEPS to 148.0.7739.0

* chore: bump chromium in DEPS to 148.0.7740.0

* 7654582: Delete obsolete kEnableServiceWorkersForChromeScheme feature flag.

https://chromium-review.googlesource.com/c/chromium/src/+/7654582

* chore: fixup patch indices

* chore: fixup patch indices

* 7664982: Move SharedModuleService to //extensions

https://chromium-review.googlesource.com/c/chromium/src/+/7664982

* chore: bump chromium in DEPS to 148.0.7741.0

* chore: fixup patch indices

* 7666060: [CodeHealth] Replace `RequestPermissions` with `RequestPermissionsFromCurrentDocument`

https://chromium-review.googlesource.com/c/chromium/src/+/7666060

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-23 10:23:55 +01:00
Samuel Attard
882a6b2cf9 build: speed up apply_all_patches by ~60% (#50417)
git am rewrites the index 2-3x per patch. In Chromium (~500K files,
70MB index) this dominated wall time: ~67 of 73 seconds were spent
rehashing and rewriting the index ~300 times for 150 patches.

- Add index.skipHash=true to skip recomputing the trailing SHA over
  the full index on every write
- Force index v4 before am so path-prefix compression roughly halves
  the on-disk index size (70MB -> 40MB)
- Disable core.fsync and gc.auto during am since a crashed apply is
  just re-run from a clean reset
- Apply patch targets in parallel (capped at ncpu-2); Chromium still
  dominates but this hides node/nan/etc behind it. Falls back to
  sequential on roller/ branches where conflict output needs to be
  readable.
- Prefix each output line with the target name so parallel output is
  attributable

Measured on a 13-target config with 238 total patches: 73s -> 28s.
2026-03-23 09:49:48 +01:00
Samuel Attard
b8fa540fd3 fix: use fresh LazyNow for OnEndWorkItemImpl to fix TimeKeeper DCHECK (#50418) 2026-03-22 19:54:31 -07:00
Robb Böhnke
dee8f5a0ff feat: add accessibilityDisplayShouldDifferentiateWithoutColor on macOS (#49912)
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.
2026-03-20 19:51:23 -04:00
dependabot[bot]
32f8e2ce45 build(deps-dev): bump eslint-plugin-n from 16.6.2 to 17.24.0 (#50310)
* build(deps-dev): bump eslint-plugin-n from 16.6.2 to 17.24.0

Bumps [eslint-plugin-n](https://github.com/eslint-community/eslint-plugin-n) from 16.6.2 to 17.24.0.
- [Release notes](https://github.com/eslint-community/eslint-plugin-n/releases)
- [Changelog](https://github.com/eslint-community/eslint-plugin-n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint-community/eslint-plugin-n/compare/16.6.2...v17.24.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-n
  dependency-version: 17.24.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: disable errors we still need these

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-20 17:38:44 -04:00
Anirudh Sevugan
4e6324e00b docs: remove postinstall lifecycle warning (#50359)
* docs: change postinstall lifecycle to changed from electron v42

* docs: remove postinstall lifecycle warning
2026-03-20 17:37:53 -04:00
Shelley Vohr
7f21d31498 feat: use Downloads folder as default path for file dialogs (#49868)
* fix: use Downloads folder as default path for file dialogs

Co-authored-by: Sourav Bera <sbera987654321@gmail.com>

* chore: improve breaking change description

---------

Co-authored-by: Sourav Bera <sbera987654321@gmail.com>
2026-03-20 17:28:53 -04:00
John Kleinschmidt
639d3b99b7 ci: update actions to node24 (#50373)
* ci: update actions to node24

* chore: fixup actions/cache to 5.0.4 everywhere
2026-03-20 15:33:48 -04:00
dodola
0c7bde54d4 feat: add copyVideoFrameAt and saveVideoFrameAs methods on webContents (#48149)
* feat: add copyVideoFrameAt and saveVideoFrameAs Method on Webcontent

chore: change the description of savevideoframe api

chore: add the description of the restrictive elements for using the APIs.

move to webframemain

fixed mediaPlayerAction to kSaveVideoFrameAs

Update spec/api-web-frame-main-spec.ts

Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>

Update spec/api-web-frame-main-spec.ts

Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>

fixed clipboard tests for video frame copying

fixed test for copying video frame to clipboard. check video loaded before copy video frame in test.

chore: try non-proprietary video format

Revert "chore: try non-proprietary video format"

This reverts commit ef085f88a1af53b6408a7af695cc60b8681398cf.

fix: format video as file url

* test: skip webFrameMain.copyVideoFrameAt on win32 CI due Chromium DCHECK
2026-03-20 15:32:09 -04:00
Noah Gregory
8a0c20431c fix: don't re-parse URL unnecessarily when handling dialogs (#50062)
* fix: fallback to opaque URL when needed inside dialog callback

* refactor: remove additional URL parsing entirely when showing dialogs

* test: add crash test case for URL-less dialogs

* refactor: exit on events instead of on timeout for dialog crash test

Co-authored-by: Robo <hop2deep@gmail.com>

* style: make linter happy

* style: make linter actually happy

* fix: address failing `safeDialogs` tests

---------

Co-authored-by: Robo <hop2deep@gmail.com>
2026-03-20 09:27:59 -04:00
dependabot[bot]
72797d7b42 build(deps): bump flatted from 3.2.7 to 3.4.1 in the npm_and_yarn group across 1 directory (#50376)
build(deps): bump flatted in the npm_and_yarn group across 1 directory

Bumps the npm_and_yarn group with 1 update in the / directory: [flatted](https://github.com/WebReflection/flatted).


Updates `flatted` from 3.2.7 to 3.4.1
- [Commits](https://github.com/WebReflection/flatted/compare/v3.2.7...v3.4.1)

---
updated-dependencies:
- dependency-name: flatted
  dependency-version: 3.4.1
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-19 19:18:55 -07:00
João Silva
9ccc752a43 fix: correct utility process exit code on Windows (#50256)
* 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

* fix: narrow HandleTermination and Shutdown to uint32_t, add tests
2026-03-19 16:58:14 -04:00
Calvin
6993eb3c78 chore: wordsmith non-maintainer dependency change bot message (#50345)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 15:44:59 -04:00
Shelley Vohr
d9649f9e16 feat: support notification priority on Windows (#50225)
* 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.

* chore: make linter happy

---------

Co-authored-by: Charles Kerr <charles@charleskerr.com>
2026-03-19 15:44:19 -04:00
John Kleinschmidt
5b2b9cdeff ci: don't run auto close for certain circumstances (#50372) 2026-03-19 14:48:09 -04:00
Shelley Vohr
e31a95b15f chore: remove macos hittest workaround patch (#50330)
build: remove macos hittest workaround patch

CL:6574464 changed BridgedContentView::hitTest: to use GetHitTestResult(), which
returns kRootView for any non-null, non-NativeViewHost view — causing
BridgedContentView to absorb all web content mouse events. In BrowserWindow,
content_view_ sits in front of the sibling WebContentsView and covers the full
client area, so it was always found first, breaking all loadURL page interaction.

Fix this by installing a ContentViewTargeterDelegate on content_view_ in
NativeWindowMac::SetContentView that returns nullptr (instead of the view itself)
when no children cover the target point. This makes GetHitTestResult return kOther,
allowing hitTest: to fall through to [super hitTest:] and find
RenderWidgetHostViewCocoa. This also removes the now-unnecessary chromium
partial-revert patch that worked around the same issue.
2026-03-19 11:04:17 -04:00
David Sanders
1ad832a4c1 ci: output build cache hit rate as GHA annotation (#50361) 2026-03-19 09:41:32 -04:00
John Kleinschmidt
8e077a09f3 ci: only run auto close on PRs targeting main branch (#50357) 2026-03-19 00:19:25 +00:00
John Kleinschmidt
95f0d8156b ci: test linux 64k (#49961) 2026-03-18 19:14:49 -04:00
Noah Gregory
b881f86c8f fix: always call the original impl in swizzled mousedown impls (#50096)
fix: always call the original implementation in swizzled mousedown implementations
2026-03-18 17:54:43 -04:00
John Kleinschmidt
5959ecc3ee ci: auto close PRs that do not fill out the required template (#50348) 2026-03-18 17:52:03 -04:00
John Kleinschmidt
a6a44692dc chore: Respect HTTP(S) proxy env variable for Yarn (#50322)
Respect HTTP(S) proxy env variable for Yarn

Co-authored-by: Filip Mösner <filip.mosner@seznam.cz>
2026-03-18 17:13:05 -04:00
John Beutner
12ea28c23e fix: ensure WebContents::WasShown runs when window is shown (#49421)
Avoids a freeze when failing to enter fullscreen on macOS.
2026-03-18 12:34:11 -04:00
Kyle Cutler
ade684dc35 fix: correctly track BaseWindow::IsActive() on MacOS (#49460)
fix: correctly set IsActive() in BaseWindow on MacOS
2026-03-18 11:47:19 -04:00
electron-roller[bot]
4ec6923898 chore: bump chromium to 148.0.7738.0 (main) (#50323)
* chore: bump chromium in DEPS to 148.0.7738.0

* chore: fixup patch indices

* 7664509: Migrate ServiceWorkerInfo to ChildProcessId

https://chromium-review.googlesource.com/c/chromium/src/+/7664509

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-18 11:45:24 -04:00
Ryan Zimmerman
e86cd9da96 docs: fix markdown formatting in fuses.md (#50318)
* docs: fix markdown formatting in fuses.md

* Use bulleted list (was being run together on one line)
* Wrap ASCII diagram in code block

* docs: apply suggestions from code review

Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
Co-authored-by: Erick Zhao <erick@hotmail.ca>

* docs: fix misapplied suggestion

---------

Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
Co-authored-by: Erick Zhao <erick@hotmail.ca>
2026-03-18 10:47:52 -04:00
reito
d6db1a27af feat: add nv12 osr format support. (#49799)
* feat: add nv12 osr output format.

* feat: add nv12 osr output format.
2026-03-17 17:14:01 -04:00
Shelley Vohr
76331f0564 refactor: replace CHILD_PLUGIN with CHILD_EMBEDDER_FIRST on macOS (#50278)
refactor: replace CHILD_PLUGIN with CHILD_EMBEDDER_FIRST on macOS

Chromium removed upstream support for child plugin processes without
library validation in https://crbug.com/461717105, which we patched
back via feat_restore_macos_child_plugin_process.patch.

Chromium's CHILD_EMBEDDER_FIRST mechanism already provides the right
extensibility point for this: values > CHILD_EMBEDDER_FIRST are reserved
for embedders and resolved via ContentBrowserClient::GetChildProcessSuffix().
Chrome itself uses this pattern for its Alerts helper process.

This commit replaces the Chromium patch with an Electron-native
implementation.
2026-03-17 14:41:15 -04:00
electron-roller[bot]
7cb6a737a9 chore: bump chromium to 148.0.7737.0 (main) (#50277)
* chore: bump chromium in DEPS to 148.0.7734.0

* chore: fixup patch indices

* chore: bump chromium in DEPS to 148.0.7736.0

* chore: fixup patch indices

* chore: bump chromium in DEPS to 148.0.7737.0

* chore: fixup patch indices

* 7666125: Migrate ServiceWorkerContext to ChildProcessId

https://chromium-review.googlesource.com/c/chromium/src/+/7666125

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-17 13:30:32 -04:00
dependabot[bot]
3659b97563 build(deps): bump dorny/paths-filter from 3.0.2 to 4.0.1 (#50306)
Bumps [dorny/paths-filter](https://github.com/dorny/paths-filter) from 3.0.2 to 4.0.1.
- [Release notes](https://github.com/dorny/paths-filter/releases)
- [Changelog](https://github.com/dorny/paths-filter/blob/master/CHANGELOG.md)
- [Commits](de90cc6fb3...fbd0ab8f3e)

---
updated-dependencies:
- dependency-name: dorny/paths-filter
  dependency-version: 4.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-17 12:30:14 -04:00
John Kleinschmidt
7d72eb809e ci: update test timeout to 60 minutes (#50305) 2026-03-17 10:06:42 -04:00
dependabot[bot]
8ba0ae7fa8 build(deps): bump actions/download-artifact from 8.0.0 to 8.0.1 (#50309)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 8.0.0 to 8.0.1.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](70fc10c6e5...3e5f45b2cf)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-17 14:42:11 +01:00
David Sanders
36350d78d0 chore: add missing timers-shim.ts to filenames.auto.gni (#50311) 2026-03-17 09:46:15 +01:00
dependabot[bot]
9b80324d7f build(deps): bump github/codeql-action from 4.32.6 to 4.33.0 (#50308)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.32.6 to 4.33.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](0d579ffd05...b1bff81932)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 22:15:03 -07:00
dependabot[bot]
a549c56faa build(deps): bump slackapi/slack-github-action from 2.1.1 to 3.0.1 (#50307)
Bumps [slackapi/slack-github-action](https://github.com/slackapi/slack-github-action) from 2.1.1 to 3.0.1.
- [Release notes](https://github.com/slackapi/slack-github-action/releases)
- [Commits](91efab103c...af78098f53)

---
updated-dependencies:
- dependency-name: slackapi/slack-github-action
  dependency-version: 3.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 22:14:43 -07:00
Keeley Hammond
958278c273 feat: add id and groupId options to macOS notifications (#50097)
* feat: add custom `id` property to Notification API (macOS only)

* feat: add `groupId` property to Notification API (macOS). Notifications with the same groupId will be visually grouped together in Notification Center

* fix: move validation to construction time, add empty string check, remove setters

* docs: clarify id/group id properties, make instance properties read-only

* test: update tests to reflect read-only properties
2026-03-16 21:24:29 +01:00
Shelley Vohr
b7e9bbed0c fix: restore sdk_inputs cross-toolchain deps for macOS (#50297)
fix: restore sdk_inputs cross-toolchain deps for macOS

The change in CL:7652975 restricted sdk_inputs public_deps
to iOS only, to avoid setting up Xcode symlinks for the Linux
toolchain when cross-building chrome/linux on Mac. However, this
also broke cross-arch macOS builds (e.g. ffmpeg with target_cpu=x64)
where the mig target in the clang_arm64 toolchain depends on
sdk_inputs from the default clang_x64 toolchain.

Add target_os == \"mac\" alongside the existing iOS check to preserve
the original intent while restoring the cross-toolchain dependency
for macOS builds.
2026-03-16 20:12:38 +00:00
Justin Mayfield
eec3fe967e fix: user resizable transparent windows on win32 (#49428)
test: revert win32 frameless and transparent resizable expectations
2026-03-16 15:31:07 -04:00
David Sanders
01714757e3 ci: ignore test timeouts in audit (#50259) 2026-03-16 14:33:37 -04:00
Shelley Vohr
ffad67222d test: fix esm issue in node-spec-runner (#50289)
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.
2026-03-16 12:55:03 -04:00
ZHUO Xu
078586fab0 docs: update the example of webContents.setWindowOpenHandler to cla… (#49379)
docs: reorganize the comments for clarifying `webContents.setWindowOpenHandler` example
2026-03-16 12:12:52 -04:00
Noah Gregory
a561dd97a6 fix: add ASAR support to additional copy methods (#50226)
* fix: add ASAR support for additional copy methods

* test: add tests for ASAR support for additional copy messages
2026-03-16 14:36:48 +01:00
Shelley Vohr
b9cbcde600 build: remove redundant bits of ncrypto node patch (#50252)
build: remove redundant ncrypto node patch
2026-03-16 12:13:47 +01:00
electron-roller[bot]
36b0709942 chore: bump chromium to 148.0.7733.0 (main) (#50197)
* chore: bump chromium in DEPS to 147.0.7727.2

* chore: bump chromium in DEPS to 148.0.7728.0

* chore: bump chromium in DEPS to 148.0.7729.0

* chore: bump chromium in DEPS to 148.0.7730.0

* chore: bump chromium in DEPS to 148.0.7732.0

* chore: update WrappablePointerTag patch
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7641766

* chore: update custom protocol patch for removed code
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7653454

* chore: update patches

* fix: cleanup removed CHILD_PLUGIN code
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7653455

* fix: move from int to ChildProcessId
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7621912

* fix: update extensions CreateTab signature
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7644389

* fix: draggable hit region test interface update for mac windows
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7655245

* chore: bump chromium in DEPS to 148.0.7733.0

* feat: restore macos child plugin process
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7653455

* fixup! chore: merge main

* chore: update patches

* fix: replace clipboard IsFormatAvailable with async GetAllAvailableFormats
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7631097

Async API pending RFC https://github.com/electron/rfcs/pull/19

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Samuel Maddock <samuelmaddock@electronjs.org>
2026-03-16 10:55:06 +01:00
Shelley Vohr
cf84efbbb9 fix: prefer browser runtime over node in DevTools HostRuntime detection (#50241)
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.
2026-03-16 10:29:35 +01:00
David Sanders
58cd1aba10 ci: fix unsupported major in release board automation (#50260) 2026-03-14 15:34:50 -07:00
dependabot[bot]
26a3a8679a build(deps-dev): bump folder-hash from 4.1.1 to 4.1.2 (#50258)
Bumps [folder-hash](https://github.com/marc136/node-folder-hash) from 4.1.1 to 4.1.2.
- [Release notes](https://github.com/marc136/node-folder-hash/releases)
- [Changelog](https://github.com/marc136/node-folder-hash/blob/v5/CHANGELOG.md)
- [Commits](https://github.com/marc136/node-folder-hash/compare/v4.1.1...v4.1.2)

---
updated-dependencies:
- dependency-name: folder-hash
  dependency-version: 4.1.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-13 22:46:05 -07:00
John Kleinschmidt
a1e4c260ea ci: create PR triage project automation (#50248)
* ci: create PR triage project automation

* chore: use ubuntu-slim

---------

Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2026-03-14 02:35:29 +00:00
Samuel Attard
f4a50a8fde build: skip archiving patch conflict fix artifact (#50251)
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: Claude <noreply@anthropic.com>
2026-03-13 21:49:05 +00:00
Erick Zhao
b35ed6346e docs: point pull requests guide to build tools (#50198)
* docs: point pull requests guide to build tools

* update for `--fork`
2026-03-13 16:01:41 -04:00
Samuel Attard
816e5964fb build: add patch conflict resolution workflow with CI artifacts (#50235)
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: Claude <noreply@anthropic.com>
2026-03-13 01:46:29 +00:00
Michaela Laurencin
3295d0d4b0 build(deps-dev): replace timers-browserify (#50203)
* build(deps-dev): replace timers-browserify

Co-Authored-By: Claude <noreply@anthropic.com>
Generated-By: GitHub Copilot

* update shim from js to ts

Co-Authored-By: Claude <noreply@anthropic.com>
Generated-By: GitHub Copilot

* remove timers-shim.js

* remove refs from package json and yarn lock

* update process in yarn lock

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-12 21:26:34 -04:00
John Kleinschmidt
3e72e2e8dd ci: update actions/cache to 5.0.3 (#50222)
chore: update actions/cache to 5.0.3

Needed due to https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
2026-03-12 20:45:01 -04:00
Erick Zhao
313e501454 feat: add ELECTRON_INSTALL_ env vars (#49981)
* feat: add `ELECTRON_INSTALL_` env vars

* add tip for available arches

* clarify!

* use `arm` instead of `armv7l`
2026-03-12 15:09:48 +01:00
Erick Zhao
1f6dbb0917 docs: add API history (G-I) (#50194) 2026-03-12 14:43:39 +01:00
Niklas Wenzel
378659c535 build: update NMV to 146 (#50214) 2026-03-11 23:32:42 +00:00
Samuel Attard
6be775ad83 fix: preserve staged update dir when pruning orphaned updates on macOS (#50210)
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
2026-03-11 15:42:23 -07:00
Mitchell Cohen
11f28ac3ac 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

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* removed inline destructors

---------

Co-authored-by: Charles Kerr <charles@charleskerr.com>
2026-03-11 15:42:09 -04:00
Erick Zhao
5ec589a1de chore: remove remark-cli from markdown linting (#50165)
* chore: remove stale `.remarkrc` file

* build(deps): remove unused deps

* cleanup again
2026-03-11 15:39:38 -04:00
Charles Kerr
4fe3752fae refactor: move electron::api::Tray to cppgc (#50187)
* refactor: migrate electron::api::tray to cppgc

* chore: add Tray to wrappable_pointer_tags.h patch

* fixup! refactor: migrate electron::api::tray to cppgc

clear keep_alive_ if error is thrown in constructor

* refactor: make Tray::menu_ a cppgc::Member<Menu>
2026-03-11 15:38:08 -04:00
Shelley Vohr
c8dd0b99ee fix: prevent traffic light buttons flashing on deminiaturize (#50183)
* 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`.

* chore: address feedback from review
2026-03-11 13:02:51 -04:00
John Kleinschmidt
55ebdfb26b ci: add timeout to test step (#50186)
Additionally, take a screenshot on timeout so that we can debug why there is a hang
2026-03-11 09:48:47 +01:00
electron-roller[bot]
d6e0c270d1 chore: bump chromium to 147.0.7727.0 (main) (#50115)
* chore: bump chromium in DEPS to 147.0.7724.0

* chore: bump chromium in DEPS to 147.0.7725.0

* chore: bump chromium in DEPS to 147.0.7727.0

* chore: update patches
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7633903

* fix: pass weak-ptr-bound callback to OnCommandsChanged
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7622614

* fix: add missing option to CSS corner smoothing property
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7646628

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Samuel Maddock <samuelmaddock@electronjs.org>
2026-03-10 23:14:36 -04:00
George Xu
c4c6195341 docs: document Wayland frameless window shadow behaviour (#50193)
docs: update linux frameless window docs to account for hasShadow:false
2026-03-10 18:37:38 -07:00
Noah Gregory
f1705eccf8 fix: don't call TaskDialogIndirect with disabled parent windows (#50078) 2026-03-10 14:51:07 -04:00
Brandon Fowler
44b12fbb7b fix: run webRequest handlers for URLs handled by ElectronURLLoaderFactory (#45915)
* fix: continue to run ProxyingURLLoaderFactory for intercepted protocols

* test: webRequest handlers when loading browser windows

* fix: wrap special URL loaders factories with ProxyingURLLoaderFactory

* test: webRequest handlers when using net.fetch

* refactor: remove redundant intercepted protocol handling

AsarURLLoaderFactory is now intercepted by ProxyingURLLoaderFactory, which already handles when the file:// scheme is intercepted.

* fix: check before using saved headers in OnReceiveResponse

* fix: run webRequest handlers when loading file service workers

* test: handlers when loading file service workers

* refactor: add shared CreateURLLoaderFactoryBuilder method

---------

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2026-03-10 12:27:00 -04:00
dependabot[bot]
3691451c71 build(deps): bump github/codeql-action from 4.32.5 to 4.32.6 (#50179)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.32.5 to 4.32.6.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](c793b717bc...0d579ffd05)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.32.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-10 09:52:19 +01:00
dependabot[bot]
b3e4547acd build(deps): bump fast-xml-parser from 4.5.3 to 4.5.4 in the npm_and_yarn group across 1 directory (#50182)
build(deps): bump fast-xml-parser

Bumps the npm_and_yarn group with 1 update in the / directory: [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser).


Updates `fast-xml-parser` from 4.5.3 to 4.5.4
- [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases)
- [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v4.5.3...v4.5.4)

---
updated-dependencies:
- dependency-name: fast-xml-parser
  dependency-version: 4.5.4
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-10 09:51:41 +01:00
dependabot[bot]
bda1becab0 build(deps): bump actions/setup-node from 6.2.0 to 6.3.0 (#50180)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.2.0 to 6.3.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](6044e13b5d...53b83947a5)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 6.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-10 09:42:58 +01:00
Michaela Laurencin
dda92fd53d ci: add workflow to remove 'needs-signed-commits' label (#50103) 2026-03-09 18:45:49 -07:00
Erick Zhao
d4cbd6cd7d docs: fix ipc highlight lines (#50169)
Co-authored-by: Dilukshan <65407969+dilukshann7@users.noreply.github.com>
2026-03-09 17:16:06 -07:00
Kyle Cutler
2ba4872d2c feat: WebContents.getOrCreateDevToolsTargetId() (#49733)
* Feat: support getDevToolsId() on WebContents

* Rename to `getOrCreateDevToolsTargetId`

* build: use spawn instead of spawnSync for build (#49774)

* Fix build

* formatting

---------

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2026-03-09 16:32:52 -04:00
Shelley Vohr
c264402766 fix: validate protocol scheme names in setAsDefaultProtocolClient (#50141)
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.
2026-03-09 18:16:34 +00:00
Shelley Vohr
2c6dd1156c fix: use requesting frame origin in permission helper and device choosers (#50052)
* 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.

* 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>
2026-03-09 09:20:22 -07:00
Shelley Vohr
eacec9a47e refactor: use WHATWG URL instead of url.parse (#48674)
refactor: use WHATWG URL instead of url.parse
2026-03-09 11:12:01 -04:00
David Sanders
0d869c2007 ci: calculate dates for release board automation (#50081) 2026-03-09 11:35:55 +01:00
Shelley Vohr
ccb2c77c17 fix: InspectorFrontendHost override in embedded windows (#49794)
fix: InspectorFrontendHost override in embedded windows
2026-03-09 10:53:02 +01:00
Samuel Attard
603679cb18 fix: read nodeIntegrationInWorker from per-frame WebPreferences (#50122)
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.
2026-03-09 00:50:01 -07:00
Samuel Attard
9b78d75b30 fix: validate response header names and values before AddHeader (#50123)
Matches the existing validation applied to request headers in
electron_api_url_loader.cc.
2026-03-08 15:40:48 -07:00
Samuel Attard
3a48fd5fbb build: pin diff.renames for deterministic patch export (#50121)
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.
2026-03-08 15:39:21 -07:00
Samuel Attard
fb13492c89 fix: correct parsing of second-instance additionalData (#50119)
- 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.
2026-03-08 15:39:12 -07:00
Samuel Attard
8bdae63036 fix: strictly validate sender for internal IPC reply channels (#50118)
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/.
2026-03-08 15:39:04 -07:00
dependabot[bot]
2a4909093e build(deps): bump the npm_and_yarn group across 1 directory with 2 updates (#50080)
Bumps the npm_and_yarn group with 2 updates in the / directory: [basic-ftp](https://github.com/patrickjuchli/basic-ftp) and [minimatch](https://github.com/isaacs/minimatch).


Updates `basic-ftp` from 5.1.0 to 5.2.0
- [Release notes](https://github.com/patrickjuchli/basic-ftp/releases)
- [Changelog](https://github.com/patrickjuchli/basic-ftp/blob/master/CHANGELOG.md)
- [Commits](https://github.com/patrickjuchli/basic-ftp/compare/v5.1.0...v5.2.0)

Updates `minimatch` from 3.1.3 to 3.1.5
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.1.3...v3.1.5)

---
updated-dependencies:
- dependency-name: basic-ftp
  dependency-version: 5.2.0
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: minimatch
  dependency-version: 3.1.5
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-08 19:20:52 +01:00
electron-roller[bot]
9f80b64617 chore: bump chromium to 147.0.7719.0 (main) (#50061)
* chore: bump chromium in DEPS to 147.0.7716.0

* chore: bump chromium in DEPS to 147.0.7717.0

* chore: bump chromium in DEPS to 147.0.7719.0

* chore: update patches

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7618634
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7622595

* [Extensions] Track service worker lifecycle more precisely

Refs https://chromium-review.googlesource.com/c/chromium/src/+/7567646

* Make Clipboard::ReadAsciiText|ReadData|ReadText|ReadAvailableTypes asynchronous

Refs
https://chromium-review.googlesource.com/c/chromium/src/+/7609958
https://chromium-review.googlesource.com/c/chromium/src/+/7600360
https://chromium-review.googlesource.com/c/chromium/src/+/7595942
https://chromium-review.googlesource.com/c/chromium/src/+/7594881

* fixup! Make Clipboard::ReadAsciiText|ReadData|ReadText|ReadAvailableTypes asynchronous

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
2026-03-08 06:22:11 +09:00
Keeley Hammond
3e0e1e4e84 test: fix flaky macOS dock tests (#50098)
* test: fix flaky mac dock & autofill tests

* fix: add null checks for the parent widget before calling IsVisible()

* test: remove autofill test change (failing on Linux), keep crash fix

* chore: autofill updates from code review
2026-03-06 13:35:16 -08:00
Michaela Laurencin
86f2c7cced docs: cleanup desktop-capturer doc after chromium audio capture additions (#50091)
* docs: cleanup desktop-capturer doc after chromium audio capture additions

* Apply suggestions from code review

Co-authored-by: Erick Zhao <erick@hotmail.ca>

* disable linter for list in note

---------

Co-authored-by: Erick Zhao <erick@hotmail.ca>
2026-03-06 15:27:00 -05:00
Calvin
73596cff9d fix: Revert "updated Alt detection to explicitly exclude AltGraph/AltGr (#49778)" (#50093)
Revert "fix: updated Alt detection to explicitly exclude AltGraph/AltGr (#49778)"

This reverts commit 90c9de70ac.

Ref: https://github.com/electron/electron/issues/50050
2026-03-06 15:25:36 -05:00
John Kleinschmidt
62c8db561c docs: remove release schedule in favor of https://releases.electronjs.org/schedule (#50094) 2026-03-06 15:25:00 -05:00
Charles Kerr
dc4ad2e932 fix: screen.getCursorScreenPoint() crash on Wayland (#50092)
* docs: document that getCursorScreenPoint() needs a Window on Wayland

* feat: add IsWayland() helper

* fix: Wayland crash in GetCursorScreenPoint()

fix: support Screen::GetCursorScreenPoint() on X11
2026-03-06 15:24:33 -05:00
418 changed files with 9516 additions and 4804 deletions

1
.github/CODEOWNERS vendored
View File

@@ -19,6 +19,7 @@ DEPS @electron/wg-upgrades
/lib/renderer/security-warnings.ts @electron/wg-security
# Infra WG
/.claude/ @electron/wg-infra
/.github/actions/ @electron/wg-infra
/.github/workflows/*-publish.yml @electron/wg-infra
/.github/workflows/build.yml @electron/wg-infra

View File

@@ -5,6 +5,8 @@ Thank you for your Pull Request. Please provide a description above and review
the requirements below.
Contributors guide: https://github.com/electron/electron/blob/main/CONTRIBUTING.md
NOTE: PRS submitted without this template will be automatically closed.
-->
#### Checklist

View File

@@ -47,6 +47,16 @@ runs:
- name: Add Clang problem matcher
shell: bash
run: echo "::add-matcher::src/electron/.github/problem-matchers/clang.json"
- name: Download previous object checksums
shell: bash
if: ${{ (github.event_name == 'push' || github.event_name == 'pull_request') && inputs.is-asan != 'true' }}
env:
GITHUB_TOKEN: ${{ github.token }}
ARTIFACT_NAME: object-checksums.${{ inputs.artifact-platform }}_${{ inputs.target-arch }}.json
SEARCH_BRANCH: ${{ case(github.event_name == 'push', github.ref_name, github.event.pull_request.base.ref) }}
REPO: ${{ github.repository }}
OUTPUT_PATH: src/previous-object-checksums.json
run: node src/electron/.github/actions/build-electron/download-previous-object-checksums.mjs
- name: Build Electron ${{ inputs.step-suffix }}
if: ${{ inputs.target-platform != 'win' }}
shell: bash
@@ -72,12 +82,17 @@ runs:
cp out/Default/.ninja_log out/electron_ninja_log
node electron/script/check-symlinks.js
# Upload build stats to Datadog
if ! [ -z $DD_API_KEY ]; then
npx node electron/script/build-stats.mjs out/Default/siso.INFO --upload-stats || true
# Build stats and object checksums
BUILD_STATS_ARGS="out/Default/siso.INFO --out-dir out/Default --output-object-checksums object-checksums.${{ inputs.artifact-platform }}_${{ inputs.target-arch }}.json"
if [ -f previous-object-checksums.json ]; then
BUILD_STATS_ARGS="$BUILD_STATS_ARGS --input-object-checksums previous-object-checksums.json"
fi
if ! [ -z "$DD_API_KEY" ]; then
BUILD_STATS_ARGS="$BUILD_STATS_ARGS --upload-stats"
else
echo "Skipping build-stats.mjs upload because DD_API_KEY is not set"
fi
node electron/script/build-stats.mjs $BUILD_STATS_ARGS || true
- name: Build Electron (Windows) ${{ inputs.step-suffix }}
if: ${{ inputs.target-platform == 'win' }}
shell: powershell
@@ -95,16 +110,21 @@ runs:
Copy-Item out\Default\.ninja_log out\electron_ninja_log
node electron\script\check-symlinks.js
# Upload build stats to Datadog
# Build stats and object checksums
$statsArgs = @("out\Default\siso.exe.INFO", "--out-dir", "out\Default", "--output-object-checksums", "object-checksums.${{ inputs.artifact-platform }}_${{ inputs.target-arch }}.json")
if (Test-Path previous-object-checksums.json) {
$statsArgs += @("--input-object-checksums", "previous-object-checksums.json")
}
if ($env:DD_API_KEY) {
try {
npx node electron\script\build-stats.mjs out\Default\siso.exe.INFO --upload-stats ; $LASTEXITCODE = 0
} catch {
Write-Host "Build stats upload failed, continuing..."
}
$statsArgs += "--upload-stats"
} else {
Write-Host "Skipping build-stats.mjs upload because DD_API_KEY is not set"
}
try {
& node electron\script\build-stats.mjs @statsArgs ; $LASTEXITCODE = 0
} catch {
Write-Host "Build stats failed, continuing..."
}
- name: Verify dist.zip ${{ inputs.step-suffix }}
shell: bash
run: |
@@ -128,6 +148,9 @@ runs:
fi
sed $SEDOPTION '/.*builtins-pgo/d' out/Default/mksnapshot_args
sed $SEDOPTION '/--turbo-profiling-input/d' out/Default/mksnapshot_args
sed $SEDOPTION '/--reorder-builtins/d' out/Default/mksnapshot_args
sed $SEDOPTION '/--warn-about-builtin-profile-data/d' out/Default/mksnapshot_args
sed $SEDOPTION '/--abort-on-bad-builtin-profile-data/d' out/Default/mksnapshot_args
if [ "${{ inputs.target-platform }}" = "win" ]; then
cd out/Default
@@ -274,18 +297,25 @@ runs:
run: ./src/electron/script/actions/move-artifacts.sh
- name: Upload Generated Artifacts ${{ inputs.step-suffix }}
if: always() && !cancelled()
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f #v7.0.0
with:
name: generated_artifacts_${{ env.ARTIFACT_KEY }}
path: ./generated_artifacts_${{ inputs.artifact-platform }}_${{ inputs.target-arch }}
- name: Upload Src Artifacts ${{ inputs.step-suffix }}
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f #v7.0.0
with:
name: src_artifacts_${{ env.ARTIFACT_KEY }}
path: ./src_artifacts_${{ inputs.artifact-platform }}_${{ inputs.target-arch }}
- name: Upload Out Gen Artifacts ${{ inputs.step-suffix }}
if: ${{ inputs.upload-out-gen-artifacts == 'true' }}
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f #v7.0.0
with:
name: out_gen_artifacts_${{ env.ARTIFACT_KEY }}
path: ./src/out/Default/gen
- name: Upload Object Checksums ${{ inputs.step-suffix }}
if: ${{ always() && !cancelled() && inputs.is-asan != 'true' }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: object_checksums_${{ inputs.artifact-platform }}_${{ inputs.target-arch }}
path: ./src/object-checksums.${{ inputs.artifact-platform }}_${{ inputs.target-arch }}.json
archive: false

View File

@@ -0,0 +1,82 @@
import { Octokit } from '@octokit/rest';
import { writeFileSync } from 'node:fs';
const token = process.env.GITHUB_TOKEN;
const repo = process.env.REPO;
const artifactName = process.env.ARTIFACT_NAME;
const branch = process.env.SEARCH_BRANCH;
const outputPath = process.env.OUTPUT_PATH;
const required = { GITHUB_TOKEN: token, REPO: repo, ARTIFACT_NAME: artifactName, SEARCH_BRANCH: branch, OUTPUT_PATH: outputPath };
const missing = Object.entries(required).filter(([, v]) => !v).map(([k]) => k);
if (missing.length > 0) {
console.error(`Missing required environment variables: ${missing.join(', ')}`);
process.exit(1);
}
const [owner, repoName] = repo.split('/');
const octokit = new Octokit({ auth: token });
async function main () {
console.log(`Searching for artifact '${artifactName}' on branch '${branch}'...`);
// Resolve the "Build" workflow name to an ID, mirroring how `gh run list --workflow` works
// under the hood (it uses /repos/{owner}/{repo}/actions/workflows/{id}/runs).
const { data: workflows } = await octokit.actions.listRepoWorkflows({ owner, repo: repoName });
const buildWorkflow = workflows.workflows.find((w) => w.name === 'Build');
if (!buildWorkflow) {
console.log('Could not find "Build" workflow, continuing without previous checksums');
return;
}
const { data: runs } = await octokit.actions.listWorkflowRuns({
owner,
repo: repoName,
workflow_id: buildWorkflow.id,
branch,
status: 'completed',
event: 'push',
per_page: 20,
exclude_pull_requests: true
});
for (const run of runs.workflow_runs) {
const { data: artifacts } = await octokit.actions.listWorkflowRunArtifacts({
owner,
repo: repoName,
run_id: run.id,
name: artifactName
});
if (artifacts.artifacts.length > 0) {
const artifact = artifacts.artifacts[0];
console.log(`Found artifact in run ${run.id} (artifact ID: ${artifact.id}), downloading...`);
// Non-archived artifacts are still downloaded from the /zip endpoint
const response = await octokit.actions.downloadArtifact({
owner,
repo: repoName,
artifact_id: artifact.id,
archive_format: 'zip'
});
if (response.headers['content-type'] !== 'application/json') {
console.error(`Unexpected content type for artifact download: ${response.headers['content-type']}`);
console.error('Expected application/json, continuing without previous checksums');
return;
}
writeFileSync(outputPath, JSON.stringify(response.data));
console.log('Downloaded previous object checksums successfully');
return;
}
}
console.log(`No previous object checksums found in last ${runs.workflow_runs.length} runs, continuing without them`);
}
main().catch((err) => {
console.error('Failed to download previous object checksums, continuing without them:', err.message);
process.exit(0);
});

View File

@@ -43,7 +43,7 @@ runs:
curl --unix-socket /var/run/sas/sas.sock --fail "http://foo/$CACHE_FILE?platform=${{ inputs.target-platform }}&getAccountName=true" > sas-token
- name: Save SAS Key
if: ${{ inputs.generate-sas-token == 'true' }}
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: sas-token
key: sas-key-${{ inputs.target-platform }}-${{ github.run_number }}-${{ github.run_attempt }}

View File

@@ -22,30 +22,50 @@ runs:
steps:
- name: Delete wrong ${{ inputs.dependency }}
shell: bash
env:
CIPD_ROOT_PREFIX: ${{ inputs.cipd-root-prefix-path }}
INSTALLATION_DIR: ${{ inputs.installation-dir }}
run : |
rm -rf ${{ inputs.cipd-root-prefix-path }}${{ inputs.installation-dir }}
rm -rf "${CIPD_ROOT_PREFIX}${INSTALLATION_DIR}"
- name: Create ensure file for ${{ inputs.dependency }}
if: ${{ inputs.dependency-version == '' }}
shell: bash
env:
PACKAGE: ${{ inputs.package }}
DEPS_FILE: ${{ inputs.deps-file }}
INSTALLATION_DIR: ${{ inputs.installation-dir }}
DEPENDENCY: ${{ inputs.dependency }}
run: |
echo '${{ inputs.package }}' `e d gclient getdep --deps-file=${{ inputs.deps-file }} -r '${{ inputs.installation-dir }}:${{ inputs.package }}'` > ${{ inputs.dependency }}_ensure_file
cat ${{ inputs.dependency }}_ensure_file
echo "$PACKAGE" $(e d gclient getdep --deps-file="$DEPS_FILE" -r "${INSTALLATION_DIR}:${PACKAGE}") > "${DEPENDENCY}_ensure_file"
cat "${DEPENDENCY}_ensure_file"
- name: Create ensure file for ${{ inputs.dependency }} from dependency-version
if: ${{ inputs.dependency-version != '' }}
shell: bash
env:
PACKAGE: ${{ inputs.package }}
DEPENDENCY_VERSION: ${{ inputs.dependency-version }}
DEPENDENCY: ${{ inputs.dependency }}
run: |
echo '${{ inputs.package }} ${{ inputs.dependency-version }}' > ${{ inputs.dependency }}_ensure_file
cat ${{ inputs.dependency }}_ensure_file
echo "$PACKAGE $DEPENDENCY_VERSION" > "${DEPENDENCY}_ensure_file"
cat "${DEPENDENCY}_ensure_file"
- name: CIPD installation of ${{ inputs.dependency }} (macOS)
if: ${{ inputs.target-platform != 'win' }}
shell: bash
env:
CIPD_ROOT_PREFIX: ${{ inputs.cipd-root-prefix-path }}
INSTALLATION_DIR: ${{ inputs.installation-dir }}
DEPENDENCY: ${{ inputs.dependency }}
run: |
echo "ensuring ${{ inputs.dependency }}"
e d cipd ensure --root ${{ inputs.cipd-root-prefix-path }}${{ inputs.installation-dir }} -ensure-file ${{ inputs.dependency }}_ensure_file
echo "ensuring $DEPENDENCY"
e d cipd ensure --root "${CIPD_ROOT_PREFIX}${INSTALLATION_DIR}" -ensure-file "${DEPENDENCY}_ensure_file"
- name: CIPD installation of ${{ inputs.dependency }} (Windows)
if: ${{ inputs.target-platform == 'win' }}
shell: powershell
env:
CIPD_ROOT_PREFIX: ${{ inputs.cipd-root-prefix-path }}
INSTALLATION_DIR: ${{ inputs.installation-dir }}
DEPENDENCY: ${{ inputs.dependency }}
run: |
echo "ensuring ${{ inputs.dependency }} on Windows"
e d cipd ensure --root ${{ inputs.cipd-root-prefix-path }}${{ inputs.installation-dir }} -ensure-file ${{ inputs.dependency }}_ensure_file
echo "ensuring $env:DEPENDENCY on Windows"
e d cipd ensure --root "$env:CIPD_ROOT_PREFIX$env:INSTALLATION_DIR" -ensure-file "$($env:DEPENDENCY)_ensure_file"

View File

@@ -7,7 +7,7 @@ runs:
shell: bash
id: yarn-cache-dir-path
run: echo "dir=$(node src/electron/script/yarn.js config get cacheFolder)" >> $GITHUB_OUTPUT
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
- uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}

View File

@@ -8,14 +8,14 @@ runs:
steps:
- name: Obtain SAS Key
continue-on-error: true
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: sas-token
key: sas-key-${{ inputs.target-platform }}-${{ github.run_number }}-1
enableCrossOsArchive: true
- name: Obtain SAS Key
continue-on-error: true
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: sas-token
key: sas-key-${{ inputs.target-platform }}-${{ github.run_number }}-${{ github.run_attempt }}
@@ -24,7 +24,7 @@ runs:
# The cache will always exist here as a result of the checkout job
# Either it was uploaded to Azure in the checkout job for this commit
# or it was uploaded in the checkout job for a previous commit.
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
with:
timeout_minutes: 30
max_attempts: 3
@@ -101,7 +101,7 @@ runs:
- name: Move Src Cache (Windows)
if: ${{ inputs.target-platform == 'win' }}
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
with:
timeout_minutes: 30
max_attempts: 3

View File

@@ -7,7 +7,7 @@ runs:
if: ${{ runner.os != 'Windows' }}
shell: bash
run: |
if [[ -z "${{ env.CHROMIUM_GIT_COOKIE }}" ]]; then
if [[ -z "$CHROMIUM_GIT_COOKIE" ]]; then
echo "CHROMIUM_GIT_COOKIE is not set - cannot authenticate."
exit 0
fi
@@ -18,9 +18,7 @@ runs:
git config --global http.cookiefile ~/.gitcookies
tr , \\t <<\__END__ >>~/.gitcookies
${{ env.CHROMIUM_GIT_COOKIE }}
__END__
echo "$CHROMIUM_GIT_COOKIE" | tr , \\t >>~/.gitcookies
eval 'set -o history' 2>/dev/null || unsetopt HIST_IGNORE_SPACE 2>/dev/null
RESPONSE=$(curl -s -b ~/.gitcookies https://chromium-review.googlesource.com/a/accounts/self)
@@ -42,7 +40,7 @@ runs:
)
git config --global http.cookiefile "%USERPROFILE%\.gitcookies"
powershell -noprofile -nologo -command Write-Output "${{ env.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }}" >>"%USERPROFILE%\.gitcookies"
powershell -noprofile -nologo -command Write-Output $env:CHROMIUM_GIT_COOKIE_WINDOWS_STRING >>"%USERPROFILE%\.gitcookies"
curl -s -b "%USERPROFILE%\.gitcookies" https://chromium-review.googlesource.com/a/accounts/self > response.txt

View File

@@ -26,7 +26,7 @@ jobs:
# Use dorny/paths-filter instead of the path filter under the on: pull_request: block
# so that the output can be used to conditionally run the apply-patches job, which lets
# the job be marked as a required status check (conditional skip counts as a success).
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
id: filter
with:
filters: |
@@ -71,3 +71,11 @@ jobs:
uses: ./src/electron/.github/actions/checkout
with:
target-platform: linux
- name: Upload Patch Conflict Fix
if: ${{ failure() }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: update-patches
path: patches/update-patches.patch
if-no-files-found: ignore
archive: false

View File

@@ -17,21 +17,25 @@ jobs:
with:
fetch-depth: 0
- name: Setup Node.js/npm
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version: 24.12.x
- name: Setting Up Dig Site
env:
CLONE_URL: ${{ github.event.pull_request.head.repo.clone_url }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
BASE_REF: ${{ github.event.pull_request.base.ref }}
run: |
echo "remote: ${{ github.event.pull_request.head.repo.clone_url }}"
echo "sha ${{ github.event.pull_request.head.sha }}"
echo "base ref ${{ github.event.pull_request.base.ref }}"
git clone https://github.com/electron/electron.git electron
echo "remote: $CLONE_URL"
echo "sha $HEAD_SHA"
echo "base ref $BASE_REF"
git clone https://github.com/electron/electron.git electron
cd electron
mkdir -p artifacts
git remote add fork ${{ github.event.pull_request.head.repo.clone_url }} && git fetch fork
git checkout ${{ github.event.pull_request.head.sha }}
git merge-base origin/${{ github.event.pull_request.base.ref }} HEAD > .dig-old
echo ${{ github.event.pull_request.head.sha }} > .dig-new
git remote add fork "$CLONE_URL" && git fetch fork
git checkout "$HEAD_SHA"
git merge-base "origin/$BASE_REF" HEAD > .dig-old
echo "$HEAD_SHA" > .dig-new
cp .dig-old artifacts
- name: Generating Types for SHA in .dig-new

View File

@@ -17,7 +17,7 @@ jobs:
contents: read
steps:
- name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.17.x
- name: Sparse checkout repository
@@ -86,6 +86,7 @@ jobs:
!message.startsWith("Response status code does not indicate success") &&
!message.startsWith("The hosted runner lost communication with the server") &&
!message.startsWith("Dependabot encountered an error performing the update") &&
!message.startsWith("The action 'Run Electron Tests' has timed out") &&
!/Unable to make request/.test(message) &&
!/The requested URL returned error/.test(message),
)
@@ -154,7 +155,7 @@ jobs:
await core.summary.write();
- name: Send Slack message if errors
if: ${{ always() && steps.audit-errors.outputs.errorsFound && github.ref == 'refs/heads/main' }}
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 # v3.0.1
with:
payload: |
link: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"

View File

@@ -31,16 +31,46 @@ jobs:
else
echo "Not a release branch: $BRANCH_NAME"
fi
- name: Determine Next Unsupported Major Version
id: determine-next-unsupported-major
if: ${{ steps.check-major-version.outputs.MAJOR }}
env:
MAJOR: ${{ steps.check-major-version.outputs.MAJOR }}
run: |
# Fetch the release schedule
SCHEDULE=$(curl -s https://releases.electronjs.org/schedule.json)
# Get the stableDate for the current major version
STABLE_DATE=$(echo "$SCHEDULE" | jq -r --arg major "${MAJOR}.0.0" '.[] | select(.version == $major) | .stableDate')
if [[ -z "$STABLE_DATE" || "$STABLE_DATE" == "null" ]]; then
echo "Could not find stableDate for version $MAJOR"
exit 1
fi
# Find the oldest version where eolDate >= stableDate of the new major
# This gives us the oldest supported version when the new major goes stable
NEXT_UNSUPPORTED_MAJOR=$(echo "$SCHEDULE" | jq -r --arg stableDate "$STABLE_DATE" '
[.[] | select(.eolDate != null and .eolDate >= $stableDate)] | sort_by(.version | split(".")[0] | tonumber) | first | .version | split(".")[0]
')
if [[ -z "$NEXT_UNSUPPORTED_MAJOR" || "$NEXT_UNSUPPORTED_MAJOR" == "null" ]]; then
echo "Could not determine oldest supported version"
exit 1
fi
echo "SCHEDULE=$SCHEDULE" >> "$GITHUB_OUTPUT"
echo "NEXT_UNSUPPORTED_MAJOR=$NEXT_UNSUPPORTED_MAJOR" >> "$GITHUB_OUTPUT"
- name: New Release Branch Tasks
if: ${{ steps.check-major-version.outputs.MAJOR }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: electron/electron
MAJOR: ${{ steps.check-major-version.outputs.MAJOR }}
NUM_SUPPORTED_VERSIONS: 3
NEXT_UNSUPPORTED_MAJOR: ${{ steps.determine-next-unsupported-major.outputs.NEXT_UNSUPPORTED_MAJOR }}
run: |
PREVIOUS_MAJOR=$((MAJOR - 1))
UNSUPPORTED_MAJOR=$((MAJOR - NUM_SUPPORTED_VERSIONS - 1))
UNSUPPORTED_MAJOR=$((NEXT_UNSUPPORTED_MAJOR - 1))
# Create new labels
gh label create $MAJOR-x-y --color 8d9ee8 || true
@@ -77,12 +107,36 @@ jobs:
if: ${{ steps.check-major-version.outputs.MAJOR }}
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
id: generate-project-metadata
env:
MAJOR: ${{ steps.check-major-version.outputs.MAJOR }}
NEXT_UNSUPPORTED_MAJOR: ${{ steps.determine-next-unsupported-major.outputs.NEXT_UNSUPPORTED_MAJOR }}
SCHEDULE: ${{ steps.determine-next-unsupported-major.outputs.SCHEDULE }}
with:
script: |
const major = ${{ steps.check-major-version.outputs.MAJOR }}
const schedule = JSON.parse(process.env.SCHEDULE)
const major = parseInt(process.env.MAJOR)
const nextMajor = major + 1
const prevMajor = major - 1
const { betaDate, stableDate } = schedule.find(v => v.version === `${major}.0.0`)
const betaPrepWeek = new Date(betaDate)
betaPrepWeek.setDate(betaPrepWeek.getDate() - 8)
const betaPrepWeekEnd = new Date(betaPrepWeek)
betaPrepWeekEnd.setDate(betaPrepWeekEnd.getDate() + 4)
const stablePrepWeek = new Date(stableDate)
stablePrepWeek.setDate(stablePrepWeek.getDate() - 8)
const stablePrepWeekEnd = new Date(stablePrepWeek)
stablePrepWeekEnd.setDate(stablePrepWeekEnd.getDate() + 4)
const stableWeek = new Date(stableDate)
stableWeek.setDate(stableWeek.getDate() - 1)
const nextAlphaDate = new Date(stableDate)
nextAlphaDate.setDate(nextAlphaDate.getDate() + 2)
core.setOutput("major", major)
core.setOutput("next-major", nextMajor)
core.setOutput("prev-major", prevMajor)
@@ -91,10 +145,19 @@ jobs:
major,
"next-major": nextMajor,
"prev-major": prevMajor,
"ending-support-major": parseInt(process.env.NEXT_UNSUPPORTED_MAJOR),
"beta-date": betaDate,
"beta-prep-week": betaPrepWeek.toISOString().split('T')[0],
"beta-prep-week-end": betaPrepWeekEnd.toISOString().split('T')[0],
"stable-week": stableWeek.toISOString().split('T')[0],
"stable-prep-week": stablePrepWeek.toISOString().split('T')[0],
"stable-prep-week-end": stablePrepWeekEnd.toISOString().split('T')[0],
"stable-date": stableDate,
"next-alpha-date": nextAlphaDate.toISOString().split('T')[0],
}))
- name: Create Release Project Board
if: ${{ steps.check-major-version.outputs.MAJOR }}
uses: dsanders11/project-actions/copy-project@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
uses: dsanders11/project-actions/copy-project@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
id: create-release-board
with:
drafts: true
@@ -114,7 +177,7 @@ jobs:
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
- name: Find Previous Release Project Board
if: ${{ steps.check-major-version.outputs.MAJOR }}
uses: dsanders11/project-actions/find-project@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
uses: dsanders11/project-actions/find-project@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
id: find-prev-release-board
with:
fail-if-project-not-found: false
@@ -122,7 +185,7 @@ jobs:
token: ${{ steps.generate-token.outputs.token }}
- name: Close Previous Release Project Board
if: ${{ steps.find-prev-release-board.outputs.number }}
uses: dsanders11/project-actions/close-project@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
uses: dsanders11/project-actions/close-project@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
with:
project-number: ${{ steps.find-prev-release-board.outputs.number }}
token: ${{ steps.generate-token.outputs.token }}

View File

@@ -61,7 +61,7 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
ref: ${{ github.event.pull_request.head.sha }}
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
id: filter
with:
filters: |
@@ -365,6 +365,18 @@ jobs:
generate-symbols: false
upload-to-storage: '0'
secrets: inherit
test-linux-arm64-64k:
uses: ./.github/workflows/pipeline-segment-electron-test-64k.yml
permissions:
contents: read
issues: read
pull-requests: read
needs: [checkout-linux, linux-arm64]
with:
test-runs-on: ubuntu-22.04-arm
test-container: '{"image":"ghcr.io/electron/test:arm64v8-${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root --privileged --init"}'
secrets: inherit
windows-x64:
permissions:
@@ -434,3 +446,30 @@ jobs:
- name: GitHub Actions Jobs Done
run: |
echo "All GitHub Actions Jobs are done"
check-signed-commits:
name: Check signed commits in green PR
needs: gha-done
if: ${{ contains(github.event.pull_request.labels.*.name, 'needs-signed-commits')}}
runs-on: ubuntu-slim
permissions:
contents: read
pull-requests: write
steps:
- name: Check signed commits in PR
uses: 1Password/check-signed-commits-action@ed2885f3ed2577a4f5d3c3fe895432a557d23d52 # v1
with:
comment: |
⚠️ 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).
- name: Remove needs-signed-commits label
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_URL: ${{ github.event.pull_request.html_url }}
run: |
gh pr edit $PR_URL --remove-label needs-signed-commits

View File

@@ -7,6 +7,7 @@ name: Clean Source Cache
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
permissions: {}
@@ -16,6 +17,8 @@ jobs:
runs-on: electron-arc-centralus-linux-amd64-32core
permissions:
contents: read
env:
DD_API_KEY: ${{ secrets.DD_API_KEY }}
container:
image: ghcr.io/electron/build:bc2f48b2415a670de18d13605b1cf0eb5fdbaae1
options: --user root
@@ -23,12 +26,130 @@ jobs:
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
- /mnt/win-cache:/mnt/win-cache
steps:
- name: Get Disk Space Before Cleanup
id: disk-before
shell: bash
run: |
echo "Disk space before cleanup:"
df -h /mnt/cross-instance-cache
df -h /mnt/win-cache
CROSS_FREE_BEFORE=$(df -k /mnt/cross-instance-cache | tail -1 | awk '{print $4}')
CROSS_TOTAL=$(df -k /mnt/cross-instance-cache | tail -1 | awk '{print $2}')
WIN_FREE_BEFORE=$(df -k /mnt/win-cache | tail -1 | awk '{print $4}')
WIN_TOTAL=$(df -k /mnt/win-cache | tail -1 | awk '{print $2}')
echo "cross_free_kb=$CROSS_FREE_BEFORE" >> $GITHUB_OUTPUT
echo "cross_total_kb=$CROSS_TOTAL" >> $GITHUB_OUTPUT
echo "win_free_kb=$WIN_FREE_BEFORE" >> $GITHUB_OUTPUT
echo "win_total_kb=$WIN_TOTAL" >> $GITHUB_OUTPUT
- name: Cleanup Source Cache
shell: bash
run: |
df -h /mnt/cross-instance-cache
find /mnt/cross-instance-cache -type f -mtime +15 -delete
find /mnt/win-cache -type f -mtime +15 -delete
- name: Get Disk Space After Cleanup
id: disk-after
shell: bash
run: |
echo "Disk space after cleanup:"
df -h /mnt/cross-instance-cache
df -h /mnt/win-cache
find /mnt/win-cache -type f -mtime +15 -delete
df -h /mnt/win-cache
CROSS_FREE_AFTER=$(df -k /mnt/cross-instance-cache | tail -1 | awk '{print $4}')
WIN_FREE_AFTER=$(df -k /mnt/win-cache | tail -1 | awk '{print $4}')
echo "cross_free_kb=$CROSS_FREE_AFTER" >> $GITHUB_OUTPUT
echo "win_free_kb=$WIN_FREE_AFTER" >> $GITHUB_OUTPUT
- name: Log Disk Space to Datadog
if: ${{ env.DD_API_KEY != '' }}
shell: bash
env:
CROSS_FREE_BEFORE: ${{ steps.disk-before.outputs.cross_free_kb }}
CROSS_FREE_AFTER: ${{ steps.disk-after.outputs.cross_free_kb }}
CROSS_TOTAL: ${{ steps.disk-before.outputs.cross_total_kb }}
WIN_FREE_BEFORE: ${{ steps.disk-before.outputs.win_free_kb }}
WIN_FREE_AFTER: ${{ steps.disk-after.outputs.win_free_kb }}
WIN_TOTAL: ${{ steps.disk-before.outputs.win_total_kb }}
run: |
TIMESTAMP=$(date +%s)
CROSS_FREE_BEFORE_GB=$(awk "BEGIN {printf \"%.2f\", $CROSS_FREE_BEFORE / 1024 / 1024}")
CROSS_FREE_AFTER_GB=$(awk "BEGIN {printf \"%.2f\", $CROSS_FREE_AFTER / 1024 / 1024}")
CROSS_FREED_GB=$(awk "BEGIN {printf \"%.2f\", ($CROSS_FREE_AFTER - $CROSS_FREE_BEFORE) / 1024 / 1024}")
CROSS_TOTAL_GB=$(awk "BEGIN {printf \"%.2f\", $CROSS_TOTAL / 1024 / 1024}")
WIN_FREE_BEFORE_GB=$(awk "BEGIN {printf \"%.2f\", $WIN_FREE_BEFORE / 1024 / 1024}")
WIN_FREE_AFTER_GB=$(awk "BEGIN {printf \"%.2f\", $WIN_FREE_AFTER / 1024 / 1024}")
WIN_FREED_GB=$(awk "BEGIN {printf \"%.2f\", ($WIN_FREE_AFTER - $WIN_FREE_BEFORE) / 1024 / 1024}")
WIN_TOTAL_GB=$(awk "BEGIN {printf \"%.2f\", $WIN_TOTAL / 1024 / 1024}")
echo "cross-instance-cache: free before=${CROSS_FREE_BEFORE_GB}GB, after=${CROSS_FREE_AFTER_GB}GB, freed=${CROSS_FREED_GB}GB, total=${CROSS_TOTAL_GB}GB"
echo "win-cache: free before=${WIN_FREE_BEFORE_GB}GB, after=${WIN_FREE_AFTER_GB}GB, freed=${WIN_FREED_GB}GB, total=${WIN_TOTAL_GB}GB"
curl -s -X POST "https://api.datadoghq.com/api/v2/series" \
-H "Content-Type: application/json" \
-H "DD-API-KEY: ${DD_API_KEY}" \
-d @- << EOF
{
"series": [
{
"metric": "electron.src_cache.disk.free_space_before_cleanup_gb",
"points": [{"timestamp": ${TIMESTAMP}, "value": ${CROSS_FREE_BEFORE_GB}}],
"type": 3,
"unit": "gigabyte",
"tags": ["volume:cross-instance-cache", "platform:linux"]
},
{
"metric": "electron.src_cache.disk.free_space_after_cleanup_gb",
"points": [{"timestamp": ${TIMESTAMP}, "value": ${CROSS_FREE_AFTER_GB}}],
"type": 3,
"unit": "gigabyte",
"tags": ["volume:cross-instance-cache", "platform:linux"]
},
{
"metric": "electron.src_cache.disk.space_freed_gb",
"points": [{"timestamp": ${TIMESTAMP}, "value": ${CROSS_FREED_GB}}],
"type": 3,
"unit": "gigabyte",
"tags": ["volume:cross-instance-cache", "platform:linux"]
},
{
"metric": "electron.src_cache.disk.total_space_gb",
"points": [{"timestamp": ${TIMESTAMP}, "value": ${CROSS_TOTAL_GB}}],
"type": 3,
"unit": "gigabyte",
"tags": ["volume:cross-instance-cache", "platform:linux"]
},
{
"metric": "electron.src_cache.disk.free_space_before_cleanup_gb",
"points": [{"timestamp": ${TIMESTAMP}, "value": ${WIN_FREE_BEFORE_GB}}],
"type": 3,
"unit": "gigabyte",
"tags": ["volume:win-cache", "platform:linux"]
},
{
"metric": "electron.src_cache.disk.free_space_after_cleanup_gb",
"points": [{"timestamp": ${TIMESTAMP}, "value": ${WIN_FREE_AFTER_GB}}],
"type": 3,
"unit": "gigabyte",
"tags": ["volume:win-cache", "platform:linux"]
},
{
"metric": "electron.src_cache.disk.space_freed_gb",
"points": [{"timestamp": ${TIMESTAMP}, "value": ${WIN_FREED_GB}}],
"type": 3,
"unit": "gigabyte",
"tags": ["volume:win-cache", "platform:linux"]
},
{
"metric": "electron.src_cache.disk.total_space_gb",
"points": [{"timestamp": ${TIMESTAMP}, "value": ${WIN_TOTAL_GB}}],
"type": 3,
"unit": "gigabyte",
"tags": ["volume:win-cache", "platform:linux"]
}
]
}
EOF
echo "Disk space metrics logged to Datadog"

View File

@@ -33,7 +33,7 @@ jobs:
ISSUE_URL: ${{ github.event.issue.html_url }}
run: |
gh issue edit $ISSUE_URL --remove-label 'blocked/need-repro','blocked/need-info ❌'
pr-reviewer-requested:
name: Maintainer requested reviewer on PR
if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '/request-review') && github.event.comment.user.type != 'Bot' }}

View File

@@ -21,7 +21,7 @@ jobs:
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
org: electron
- name: Set status
uses: dsanders11/project-actions/edit-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
uses: dsanders11/project-actions/edit-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
with:
token: ${{ steps.generate-token.outputs.token }}
project-number: 90
@@ -42,7 +42,7 @@ jobs:
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
org: electron
- name: Set status
uses: dsanders11/project-actions/edit-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
uses: dsanders11/project-actions/edit-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
with:
token: ${{ steps.generate-token.outputs.token }}
project-number: 90
@@ -61,9 +61,10 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: electron/electron
ISSUE_NUMBER: ${{ github.event.issue.number }}
run: |
set -eo pipefail
COMMENT_COUNT=$(gh issue view ${{ github.event.issue.number }} --comments --json comments | jq '[ .comments[] | select(.author.login == "electron-issue-triage" or .authorAssociation == "OWNER" or .authorAssociation == "MEMBER") | select(.body | startswith("<!-- blocked/need-repro -->")) ] | length')
COMMENT_COUNT=$(gh issue view "$ISSUE_NUMBER" --comments --json comments | jq '[ .comments[] | select(.author.login == "electron-issue-triage" or .authorAssociation == "OWNER" or .authorAssociation == "MEMBER") | select(.body | startswith("<!-- blocked/need-repro -->")) ] | length')
if [[ $COMMENT_COUNT -eq 0 ]]; then
echo "SHOULD_COMMENT=1" >> "$GITHUB_OUTPUT"
fi
@@ -75,7 +76,7 @@ jobs:
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
- name: Create comment
if: ${{ steps.check-for-comment.outputs.SHOULD_COMMENT }}
uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6
uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3.8.0
with:
actions: 'create-comment'
token: ${{ steps.generate-token.outputs.token }}

View File

@@ -20,7 +20,7 @@ jobs:
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
org: electron
- name: Add to Issue Triage
uses: dsanders11/project-actions/add-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
uses: dsanders11/project-actions/add-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
with:
field: Reporter
field-value: ${{ github.event.issue.user.login }}
@@ -146,7 +146,7 @@ jobs:
}
- name: Create unsupported major comment
if: ${{ steps.add-labels.outputs.unsupportedMajor }}
uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6
uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3.8.0
with:
actions: 'create-comment'
token: ${{ steps.generate-token.outputs.token }}

View File

@@ -20,7 +20,7 @@ jobs:
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
org: electron
- name: Remove from issue triage
uses: dsanders11/project-actions/delete-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
uses: dsanders11/project-actions/delete-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
with:
token: ${{ steps.generate-token.outputs.token }}
project-number: 90

View File

@@ -16,9 +16,11 @@ jobs:
steps:
- name: Check for any blocked labels
id: check-for-blocked-labels
env:
LABELS_JSON: ${{ toJSON(github.event.issue.labels.*.name) }}
run: |
set -eo pipefail
BLOCKED_LABEL_COUNT=$(echo '${{ toJSON(github.event.issue.labels.*.name) }}' | jq '[ .[] | select(startswith("blocked/")) ] | length')
BLOCKED_LABEL_COUNT=$(echo "$LABELS_JSON" | jq '[ .[] | select(startswith("blocked/")) ] | length')
if [[ $BLOCKED_LABEL_COUNT -eq 0 ]]; then
echo "NOT_BLOCKED=1" >> "$GITHUB_OUTPUT"
fi
@@ -31,7 +33,7 @@ jobs:
org: electron
- name: Set status
if: ${{ steps.check-for-blocked-labels.outputs.NOT_BLOCKED }}
uses: dsanders11/project-actions/edit-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
uses: dsanders11/project-actions/edit-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
with:
token: ${{ steps.generate-token.outputs.token }}
project-number: 90

View File

@@ -10,6 +10,10 @@ on:
- '.yarn/**'
- '.yarnrc.yml'
# SECURITY: This workflow uses pull_request_target and has access to secrets.
# Do NOT checkout or run code from the PR head. All code execution must use
# the base branch only. Adding a ref to PR head would expose secrets to
# untrusted code.
permissions: {}
jobs:
@@ -45,5 +49,23 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_URL: ${{ github.event.pull_request.html_url }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
run: |
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=-
cat <<'REVIEW_EOF' | sed "s/%AUTHOR%/$PR_AUTHOR/g" | gh pr review $PR_URL -r --body-file=-
<!-- disallowed-non-maintainer-change -->
Hello @%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.
To move this PR forward, please:
1. Revert the dependency/CI file changes from your branch. (e.g. `yarn.lock`, `.yarn/`, `.yarnrc.yml`, `.github/workflows/`, `.github/actions/`)
2. Ensure your branch [allows maintainer commits](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) so a maintainer can push the necessary dependency changes on your behalf.
3. Leave a comment letting reviewers know the dependency change is still needed.
<details>
<summary>For maintainers</summary>
To land this PR, push a verified commit to the contributor's branch with the required dependency/CI changes, then dismiss this review.
</details>
REVIEW_EOF

View File

@@ -46,6 +46,10 @@ jobs:
shell: bash
run: |
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
if [[ ! "$chromium_revision" =~ ^[a-zA-Z0-9._-]+$ ]]; then
echo "::error::Invalid chromium_revision: $chromium_revision"
exit 1
fi
gn_version="$(curl -sL -b ~/.gitcookies "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep gn_version | head -n1 | cut -d\' -f4)"
cipd ensure -ensure-file - -root . <<-CIPD
@@ -60,6 +64,10 @@ jobs:
shell: bash
run: |
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
if [[ ! "$chromium_revision" =~ ^[a-zA-Z0-9._-]+$ ]]; then
echo "::error::Invalid chromium_revision: $chromium_revision"
exit 1
fi
mkdir -p src/buildtools
curl -sL -b ~/.gitcookies "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/buildtools/DEPS?format=TEXT" | base64 -d > src/buildtools/DEPS

View File

@@ -124,7 +124,7 @@ jobs:
run: df -h
- name: Setup Node.js/npm
if: ${{ inputs.target-platform == 'macos' }}
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version: 22.21.x
cache: yarn

View File

@@ -126,7 +126,7 @@ jobs:
cd src/electron
git pack-refs
- name: Download Out Gen Artifacts
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: out_gen_artifacts_${{ env.ARTIFACT_KEY }}
path: ./src/out/${{ env.ELECTRON_OUT_DIR }}/gen

View File

@@ -132,7 +132,7 @@ jobs:
run: df -h
- name: Setup Node.js/npm
if: ${{ inputs.target-platform == 'macos' }}
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version: 22.21.x
cache: yarn

View File

@@ -0,0 +1,67 @@
name: Pipeline Segment - Electron Test on Linux ARM64 64k
on:
workflow_call:
inputs:
test-runs-on:
type: string
description: 'What host to run the tests on'
required: true
test-container:
type: string
description: 'JSON container information for aks runs-on'
required: false
default: '{"image":null}'
concurrency:
group: electron-test-linux-64k-${{ github.ref_protected == true && github.run_id || github.ref }}
cancel-in-progress: ${{ github.ref_protected != true }}
permissions: {}
env:
ELECTRON_OUT_DIR: Default
jobs:
test-linux-arm64-64k:
env:
BUILD_TYPE: linux
TARGET_ARCH: arm64
defaults:
run:
shell: bash
runs-on: ${{ inputs.test-runs-on }}
permissions:
contents: read
issues: read
pull-requests: read
steps:
- name: Checkout Electron
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: Download Generated Artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: generated_artifacts_linux_arm64
path: ./generated_artifacts_linux_arm64
- name: Restore Generated Artifacts
run: ./src/electron/script/actions/restore-artifacts.sh
- name: Unzip Dist
run: |
cd src/out/Default
unzip -:o dist.zip
- name: Run Electron Tests in QEMU 64k Container
shell: bash
env:
MOCHA_REPORTER: mocha-multi-reporters
MOCHA_MULTI_REPORTERS: mocha-junit-reporter, tap
ELECTRON_DISABLE_SECURITY_WARNINGS: 1
DISPLAY: ':99.0'
run: |
container=$(echo '${{ inputs.test-container }}' | jq -r '.image')
src/electron/script/run-qemu-64k.sh --container $container --testfiles "`pwd`/src"

View File

@@ -48,6 +48,8 @@ env:
ELECTRON_OUT_DIR: Default
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
ACTIONS_STEP_DEBUG: ${{ secrets.ACTIONS_STEP_DEBUG }}
# @sentry/cli is only needed by release upload-symbols.py; skip the ~17MB CDN download on test jobs
SENTRYCLI_SKIP_DOWNLOAD: 1
jobs:
test:
@@ -77,7 +79,7 @@ jobs:
cp $(which node) /mnt/runner-externals/node24/bin/
- name: Setup Node.js/npm
if: ${{ inputs.target-platform == 'win' }}
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version: 22.21.x
- name: Add TCC permissions on macOS
@@ -173,12 +175,12 @@ jobs:
echo "DISABLE_CRASH_REPORTER_TESTS=true" >> $GITHUB_ENV
echo "IS_ASAN=true" >> $GITHUB_ENV
- name: Download Generated Artifacts
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: generated_artifacts_${{ env.ARTIFACT_KEY }}
path: ./generated_artifacts_${{ matrix.build-type }}_${{ inputs.target-arch }}
- name: Download Src Artifacts
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: src_artifacts_${{ env.ARTIFACT_KEY }}
path: ./src_artifacts_${{ matrix.build-type }}_${{ inputs.target-arch }}
@@ -214,6 +216,7 @@ jobs:
- name: Run Electron Tests
shell: bash
timeout-minutes: 60
env:
MOCHA_REPORTER: mocha-multi-reporters
MOCHA_MULTI_REPORTERS: mocha-junit-reporter, tap
@@ -283,6 +286,19 @@ jobs:
fi
fi
- name: Take screenshot on timeout or cancellation
if: ${{ inputs.target-platform != 'linux' && (cancelled() || failure()) }}
shell: bash
run: |
screenshot_dir="src/electron/spec/artifacts"
mkdir -p "$screenshot_dir"
screenshot_file="$screenshot_dir/screenshot-timeout-$(date +%Y%m%d%H%M%S).png"
if [ "${{ inputs.target-platform }}" = "macos" ]; then
screencapture -x "$screenshot_file" || true
elif [ "${{ inputs.target-platform }}" = "win" ]; then
powershell -command "Add-Type -AssemblyName System.Windows.Forms; \$screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds; \$bitmap = New-Object System.Drawing.Bitmap(\$screen.Width, \$screen.Height); \$graphics = [System.Drawing.Graphics]::FromImage(\$bitmap); \$graphics.CopyFromScreen(\$screen.Location, [System.Drawing.Point]::Empty, \$screen.Size); \$bitmap.Save('$screenshot_file')" || true
fi
- name: Upload Test results to Datadog
env:
DD_ENV: ci
@@ -298,8 +314,8 @@ jobs:
fi
if: always() && !cancelled()
- name: Upload Test Artifacts
if: always() && !cancelled()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f #v7.0.0
with:
name: ${{ inputs.target-platform == 'linux' && format('test_artifacts_{0}_{1}_{2}', env.ARTIFACT_KEY, inputs.display-server, matrix.shard) || format('test_artifacts_{0}_{1}', env.ARTIFACT_KEY, matrix.shard) }}
path: src/electron/spec/artifacts

View File

@@ -36,6 +36,8 @@ env:
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
ELECTRON_OUT_DIR: Default
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
# @sentry/cli is only needed by release upload-symbols.py; skip the ~17MB CDN download on test jobs
SENTRYCLI_SKIP_DOWNLOAD: 1
jobs:
node-tests:
@@ -65,12 +67,12 @@ jobs:
- name: Install Dependencies
uses: ./src/electron/.github/actions/install-dependencies
- name: Download Generated Artifacts
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }}
path: ./generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }}
- name: Download Src Artifacts
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: src_artifacts_linux_${{ env.TARGET_ARCH }}
path: ./src_artifacts_linux_${{ env.TARGET_ARCH }}
@@ -121,12 +123,12 @@ jobs:
- name: Install Dependencies
uses: ./src/electron/.github/actions/install-dependencies
- name: Download Generated Artifacts
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }}
path: ./generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }}
- name: Download Src Artifacts
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: src_artifacts_linux_${{ env.TARGET_ARCH }}
path: ./src_artifacts_linux_${{ env.TARGET_ARCH }}

58
.github/workflows/pr-template-check.yml vendored Normal file
View File

@@ -0,0 +1,58 @@
name: PR Template Check
on:
pull_request_target:
types: [opened, ready_for_review]
# SECURITY: This workflow uses pull_request_target and has access to secrets.
# Do NOT checkout or run code from the PR head. All code execution must use
# the base branch only. Adding a ref to PR head would expose secrets to
# untrusted code.
permissions: {}
jobs:
check-pr-template:
if: ${{ github.event.pull_request.head.repo.fork && !github.event.pull_request.draft && !startsWith(github.head_ref, 'roller/') }}
name: Check PR Template
runs-on: ubuntu-slim
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
sparse-checkout: .github/PULL_REQUEST_TEMPLATE.md
sparse-checkout-cone-mode: false
- name: Check for required sections
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with:
script: |
const fs = require('fs');
const template = fs.readFileSync('.github/PULL_REQUEST_TEMPLATE.md', 'utf8');
const requiredSections = [...template.matchAll(/^(#{1,4} .+)$/gm)].map(
(m) => m[1],
);
if (requiredSections.length === 0) {
console.log('No heading sections found in PR template');
return;
}
const body = context.payload.pull_request.body || '';
const missingSections = requiredSections.filter(
(section) => !body.includes(section),
);
if (missingSections.length > 0) {
const list = missingSections.map((s) => `- \`${s}\``).join('\n');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: `This PR was automatically closed because the PR template was not properly filled out. The following required sections are missing:\n\n${list}\n\nPlease update your PR description to include all required sections and reopen the PR.`,
});
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
state: 'closed',
});
}

View File

@@ -0,0 +1,44 @@
name: PR Triage Automation
on:
pull_request_target:
types: [synchronize, review_requested]
issue_comment:
types: [created]
# SECURITY: This workflow uses pull_request_target and has access to secrets.
# Do NOT checkout or run code from the PR head. All code execution must use
# the base branch only. Adding a ref to PR head would expose secrets to
# untrusted code.
permissions: {}
jobs:
set-needs-review:
name: Set status to Needs Review
if: >-
(github.event_name == 'pull_request_target'
&& github.event.pull_request.draft != true
&& !contains(github.event.pull_request.labels.*.name, 'wip ⚒')
&& (github.event.action == 'synchronize' || github.event.action == 'review_requested'))
|| (github.event_name == 'issue_comment'
&& github.event.issue.pull_request
&& !contains(github.event.issue.labels.*.name, 'wip ⚒')
&& github.event.comment.user.login == github.event.issue.user.login)
runs-on: ubuntu-slim
permissions:
contents: read
steps:
- name: Generate GitHub App token
uses: electron/github-app-auth-action@e14e47722ed120360649d0789e25b9baece12725 # v2.0.0
id: generate-token
with:
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
org: electron
- name: Set status to Needs Review
uses: dsanders11/project-actions/edit-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
with:
token: ${{ steps.generate-token.outputs.token }}
project-number: 118
field: Status
field-value: 🌀 Needs Review
fail-if-item-not-found: false

View File

@@ -4,6 +4,10 @@ on:
pull_request_target:
types: [labeled]
# SECURITY: This workflow uses pull_request_target and has access to secrets.
# Do NOT checkout or run code from the PR head. All code execution must use
# the base branch only. Adding a ref to PR head would expose secrets to
# untrusted code.
permissions: {}
jobs:
@@ -14,7 +18,7 @@ jobs:
permissions: {}
steps:
- name: Trigger Slack workflow
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 # v3.0.1
with:
webhook: ${{ secrets.BACKPORT_REQUESTED_SLACK_WEBHOOK_URL }}
webhook-type: webhook-trigger
@@ -38,7 +42,7 @@ jobs:
creds: ${{ secrets.RELEASE_BOARD_GH_APP_CREDS }}
org: electron
- name: Set status
uses: dsanders11/project-actions/edit-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
uses: dsanders11/project-actions/edit-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
with:
token: ${{ steps.generate-token.outputs.token }}
project-number: 94
@@ -56,7 +60,7 @@ jobs:
with:
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
- name: Create comment
uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6
uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3.8.0
with:
actions: 'create-comment'
token: ${{ steps.generate-token.outputs.token }}
@@ -68,7 +72,7 @@ jobs:
Hello @${{ github.event.pull_request.user.login }}. Due to the high amount of AI spam PRs we receive, if a PR is detected to be majority AI-generated without disclosure and untested, we will automatically close the PR.
We welcome the use of AI tools, as long as the PR meets our quality standards and has clearly been built and tested. If you believe your PR was closed in error, we welcome you to resubmit. However, please read our [CONTRIBUTING.md](http://contributing.md/) carefully before reopening. Thanks for your contribution.
We welcome the use of AI tools, as long as the PR meets our quality standards and has clearly been built and tested. If you believe your PR was closed in error, we welcome you to resubmit. However, please read our [CONTRIBUTING.md](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) and [AI Tool Policy](https://github.com/electron/governance/blob/main/policy/ai.md) carefully before reopening. Thanks for your contribution.
- name: Close the pull request
env:
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}

View File

@@ -0,0 +1,39 @@
name: Pull Request Opened/Synchronized
on:
pull_request_target:
types: [opened, synchronize]
# SECURITY: This workflow uses pull_request_target and has access to secrets.
# Do NOT checkout or run code from the PR head. All code execution must use
# the base branch only. Adding a ref to PR head would expose secrets to
# untrusted code.
permissions: {}
jobs:
check-signed-commits:
name: Check signed commits in PR
if: ${{ !contains(github.event.pull_request.labels.*.name, 'needs-signed-commits')}}
runs-on: ubuntu-slim
permissions:
contents: read
pull-requests: write
steps:
- name: Check signed commits in PR
uses: 1Password/check-signed-commits-action@ed2885f3ed2577a4f5d3c3fe895432a557d23d52 # v1
with:
comment: |
⚠️ 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).
- name: Add needs-signed-commits label
if: ${{ failure() }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_URL: ${{ github.event.pull_request.html_url }}
run: |
gh pr edit $PR_URL --add-label needs-signed-commits

View File

@@ -51,6 +51,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@c793b717bc78562f491db7b0e93a3a178b099162 # v3.29.5
uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v3.29.5
with:
sarif_file: results.sarif

View File

@@ -29,7 +29,7 @@ jobs:
PROJECT_NUMBER=$(gh project list --owner electron --format json | jq -r '.projects | map(select(.title | test("^[0-9]+-x-y$"))) | max_by(.number) | .number')
echo "PROJECT_NUMBER=$PROJECT_NUMBER" >> "$GITHUB_OUTPUT"
- name: Update Completed Stable Prep Items
uses: dsanders11/project-actions/completed-by@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
uses: dsanders11/project-actions/completed-by@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
with:
field: Prep Status
field-value: ✅ Complete

1
.gitignore vendored
View File

@@ -42,6 +42,7 @@ spec/.hash
# Generated native addon files
/spec/fixtures/native-addon/echo/build/
/spec/fixtures/native-addon/dialog-helper/build/
# If someone runs tsc this is where stuff will end up
ts-gen

View File

@@ -1,6 +0,0 @@
{
"plugins": [
["remark-lint-code-block-style", "fenced"],
["remark-lint-fenced-code-flag"]
]
}

View File

@@ -9,4 +9,8 @@ npmMinimalAgeGate: 10080
npmPreapprovedPackages:
- "@electron/*"
httpProxy: "${HTTP_PROXY:-}"
httpsProxy: "${HTTPS_PROXY:-}"
yarnPath: .yarn/releases/yarn-4.12.0.cjs

View File

@@ -1017,7 +1017,17 @@ if (is_mac) {
}
}
foreach(helper_params, content_mac_helpers) {
# Electron defines its own plugin helper (using CHILD_EMBEDDER_FIRST + 1) to
# allow loading of unsigned or third-party-signed libraries.
_electron_plugin_helper_params = [
"plugin",
".plugin",
" (Plugin)",
]
electron_mac_helpers =
content_mac_helpers + [ _electron_plugin_helper_params ]
foreach(helper_params, electron_mac_helpers) {
_helper_target = helper_params[0]
_helper_bundle_id = helper_params[1]
_helper_suffix = helper_params[2]
@@ -1070,7 +1080,7 @@ if (is_mac) {
":stripped_squirrel_framework",
]
foreach(helper_params, content_mac_helpers) {
foreach(helper_params, electron_mac_helpers) {
sources +=
[ "$root_out_dir/${electron_helper_name}${helper_params[2]}.app" ]
public_deps += [ ":electron_helper_app_${helper_params[0]}" ]
@@ -1174,7 +1184,7 @@ if (is_mac) {
deps = [ ":electron_framework" ]
}
foreach(helper_params, content_mac_helpers) {
foreach(helper_params, electron_mac_helpers) {
_helper_target = helper_params[0]
_helper_bundle_id = helper_params[1]
_helper_suffix = helper_params[2]
@@ -1226,7 +1236,7 @@ if (is_mac) {
deps += [ ":crashpad_handler_syms" ]
}
foreach(helper_params, content_mac_helpers) {
foreach(helper_params, electron_mac_helpers) {
_helper_target = helper_params[0]
deps += [ ":electron_helper_syms_${_helper_target}" ]
}

View File

@@ -127,6 +127,22 @@ patches/{target}/*.patch → [e sync --3] → target repo commits
2. Create a git commit
3. Run `e patches <target>` to export
**Fixing patch conflicts on an existing PR:**
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
@@ -192,6 +208,7 @@ gh label list --repo electron/electron --search target/ --json name,color --jq '
```bash
npm run lint # Run all linters
npm run lint:clang-format # C++ formatting
npm run lint:api-history # Validate API history YAML blocks in docs
```
## Key Files

4
DEPS
View File

@@ -2,9 +2,9 @@ gclient_gn_args_from = 'src'
vars = {
'chromium_version':
'147.0.7714.0',
'148.0.7763.0',
'node_version':
'v24.14.0',
'v24.14.1',
'nan_version':
'675cefebca42410733da8a454c8d9391fcebfbc2',
'squirrel.mac_version':

View File

@@ -2,7 +2,7 @@ is_electron_build = true
root_extra_deps = [ "//electron" ]
# Registry of NMVs --> https://github.com/nodejs/node/blob/main/doc/abi_version_registry.json
node_module_version = 145
node_module_version = 146
v8_promise_internal_field_count = 1
v8_embedder_string = "-electron.0"
@@ -51,9 +51,6 @@ is_cfi = false
use_qt5 = false
use_qt6 = false
# Disables the builtins PGO for V8
v8_builtins_profiling_log_file = ""
# https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr.md
# TODO(vertedinde): hunt down dangling pointers on Linux
enable_dangling_raw_ptr_checks = false

View File

@@ -122,8 +122,8 @@ if ((globalThis.process || binding.process).argv.includes("--profile-electron-in
'electron/renderer$': electronAPIFile,
'electron/common$': electronAPIFile,
'electron/utility$': electronAPIFile,
// Force timers to resolve to our dependency that doesn't use window.postMessage
timers: path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
// Force timers to resolve to our own shim that doesn't use window.postMessage
timers: path.resolve(electronRoot, 'lib', 'common', 'timers-shim.ts')
},
extensions: ['.ts', '.js'],
fallback: {

View File

@@ -245,6 +245,10 @@ static_library("chrome") {
"//chrome/browser/ui/views/dark_mode_manager_linux.cc",
"//chrome/browser/ui/views/dark_mode_manager_linux.h",
]
sources += [
"//chrome/browser/ui/views/frame/browser_frame_view_paint_utils_linux.cc",
"//chrome/browser/ui/views/frame/browser_frame_view_paint_utils_linux.h",
]
public_deps += [ "//components/dbus" ]
}

View File

@@ -256,7 +256,7 @@ async function startRepl () {
if (option.file && !option.webdriver) {
const file = option.file;
// eslint-disable-next-line n/no-deprecated-api
const protocol = url.parse(file).protocol;
const protocol = URL.canParse(file) ? new URL(file).protocol : null;
const extension = path.extname(file);
if (protocol === 'http:' || protocol === 'https:' || protocol === 'file:' || protocol === 'chrome:') {
await loadApplicationByURL(file);

58
docs/CLAUDE.md Normal file
View File

@@ -0,0 +1,58 @@
# Electron Documentation Guide
## API History Migration
Guide: `docs/development/api-history-migration-guide.md`
Style rules: `docs/development/style-guide.md` (see "API History" section)
Schema: `docs/api-history.schema.json`
Lint: `npm run lint:api-history`
### Format
Place YAML history block directly after the Markdown header, before parameters:
````md
### `module.method(args)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/XXXXX
```
-->
* `arg` type - Description.
````
### Finding when an API was added
- `git log --all --reverse --oneline -S "methodName" -- docs/api/file.md` — find first commit adding a method name
- `git log --reverse -L :FunctionName:path/to/source.cc` — trace C++ implementation history
- `git log --grep="keyword" --oneline` — find merge commits referencing PRs
- `gh pr view <number> --repo electron/electron --json baseRefName` — verify PR targets main (not a backport)
- Always use the main-branch PR URL in history blocks, not backport PRs
### Cross-referencing breaking changes
- Search `docs/breaking-changes.md` for the API name to find deprecations/removals
- Use `git blame` on the breaking-changes entry to find the associated PR
- Add `breaking-changes-header` field using the heading ID from breaking-changes.md
### Placement rules
- Only add blocks to actual API entries (methods, events, properties with backtick signatures)
- Do NOT add blocks to section headers like `## Methods`, `### Instance Methods`, `## Events`
- Module-level blocks go after the `# moduleName` heading, before the module description quote
- For changes affecting multiple APIs, add a block under each affected top-level heading (see style guide "Change affecting multiple APIs")
### Key details
- `added` and `deprecated` arrays have `maxItems: 1`; `changes` can have multiple items
- `changes` entries require a `description` field; `added`/`deprecated` do not
- Wrap descriptions in double quotes to avoid YAML parsing issues with special characters
- Early Electron APIs (pre-2015) use merge-commit PRs (e.g., `Merge pull request #534`)
- Very early APIs (2013-2014, e.g., `ipcMain.on`, `ipcRenderer.send`) predate GitHub PRs — skip history blocks for these
- When multiple APIs were added in the same PR, they all reference the same PR URL
- Promisification PRs (e.g., #17355) count as `changes` entries with a description
- These PRs are breaking changes and should have their notes as "This method now returns a Promise instead of using a callback function."
- APIs that were deprecated and then removed from docs don't need history blocks (the removal is in `breaking-changes.md`)

View File

@@ -615,7 +615,11 @@ Returns `string` - The current application directory.
by default is the `appData` directory appended with your app's name. By
convention files storing user data should be written to this directory, and
it is not recommended to write large files here because some environments
may backup this directory to cloud storage.
may backup this directory to cloud storage. It is recommended to store
app-specific files within a subdirectory of `userData` (e.g.,
`path.join(app.getPath('userData'), 'my-app-data')`) rather than directly
in `userData` itself, to avoid naming conflicts with Chromium's own
subdirectories (such as `Cache`, `GPUCache`, and `Local Storage`).
* `sessionData` The directory for storing data generated by `Session`, such
as localStorage, cookies, disk cache, downloaded dictionaries, network
state, DevTools files. By default this points to `userData`. Chromium may

View File

@@ -105,7 +105,7 @@ changes:
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]
<!-- 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`][].
@@ -120,30 +120,41 @@ Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [`Desktop
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.
---
### macOS versions 14.2 or higher
### MacOS versions 14.2 or higher
`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.
`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.
> 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.
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:
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)
app.commandLine.appendSwitch('disable-features', 'MacCatapLoopbackAudioForScreenShare')
```
---
### macOS versions 12.7.6 or lower
### MacOS versions 12.7.6 or lower
`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.
`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 with `navigator.mediaDevices.getUserMedia`.
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
with `navigator.mediaDevices.getUserMedia`.

View File

@@ -28,7 +28,10 @@ added:
* `window` [BaseWindow](base-window.md) (optional)
* `options` Object
* `title` string (optional)
* `defaultPath` string (optional)
* `defaultPath` string (optional) - Absolute directory path, absolute file
path, or file name to use by default. If not provided, the dialog will
default to the user's Downloads folder, or their home directory if Downloads
doesn't exist.
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
left empty the default label will be used.
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
@@ -109,7 +112,10 @@ changes:
* `window` [BaseWindow](base-window.md) (optional)
* `options` Object
* `title` string (optional)
* `defaultPath` string (optional)
* `defaultPath` string (optional) - Absolute directory path, absolute file
path, or file name to use by default. If not provided, the dialog will
default to the user's Downloads folder, or their home directory if Downloads
doesn't exist.
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
left empty the default label will be used.
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
@@ -198,7 +204,9 @@ added:
* `options` Object
* `title` string (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
* `defaultPath` string (optional) - Absolute directory path, absolute file
path, or file name to use by default.
path, or file name to use by default. If not provided, the dialog will
default to the user's Downloads folder, or their home directory if Downloads
doesn't exist.
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
left empty the default label will be used.
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
@@ -238,7 +246,9 @@ changes:
* `options` Object
* `title` string (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
* `defaultPath` string (optional) - Absolute directory path, absolute file
path, or file name to use by default.
path, or file name to use by default. If not provided, the dialog will
default to the user's Downloads folder, or their home directory if Downloads
doesn't exist.
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
left empty the default label will be used.
* `filters` [FileFilter[]](structures/file-filter.md) (optional)

View File

@@ -56,6 +56,9 @@ Returns `string` - The badge string of the dock.
Hides the dock icon.
> [!IMPORTANT]
> **Known issue:** Calling `dock.hide()` within one second of a previous call will have no effect. As a workaround, ensure at least one second has elapsed between calls — for example, by deferring with a `setTimeout` of 1100ms or more after a previous call.
#### `dock.show()` _macOS_
Returns `Promise<void>` - Resolves when the dock icon is shown.

View File

@@ -55,6 +55,13 @@ The `globalShortcut` module has the following methods:
### `globalShortcut.register(accelerator, callback)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/534
```
-->
* `accelerator` string - An [accelerator](../tutorial/keyboard-shortcuts.md#accelerators) shortcut.
* `callback` Function
@@ -77,6 +84,13 @@ the app has been authorized as a [trusted accessibility client](https://develope
### `globalShortcut.registerAll(accelerators, callback)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/15542
```
-->
* `accelerators` string[] - An array of [accelerator](../tutorial/keyboard-shortcuts.md#accelerators) shortcuts.
* `callback` Function
@@ -96,6 +110,13 @@ the app has been authorized as a [trusted accessibility client](https://develope
### `globalShortcut.isRegistered(accelerator)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/534
```
-->
* `accelerator` string - An [accelerator](../tutorial/keyboard-shortcuts.md#accelerators) shortcut.
Returns `boolean` - Whether this application has registered `accelerator`.
@@ -106,10 +127,24 @@ don't want applications to fight for global shortcuts.
### `globalShortcut.unregister(accelerator)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/534
```
-->
* `accelerator` string - An [accelerator](../tutorial/keyboard-shortcuts.md#accelerators) shortcut.
Unregisters the global shortcut of `accelerator`.
### `globalShortcut.unregisterAll()`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/534
```
-->
Unregisters all of the global shortcuts.

View File

@@ -35,6 +35,13 @@ webContentsView.webContents.loadURL('https://electronjs.org')
## Class: ImageView extends `View`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/46760
```
-->
> A View that displays an image.
Process: [Main](../glossary.md#main-process)
@@ -49,6 +56,13 @@ Process: [Main](../glossary.md#main-process)
### `new ImageView()` _Experimental_
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/46760
```
-->
Creates an ImageView.
### Instance Methods
@@ -58,6 +72,13 @@ addition to those inherited from [View](view.md):
#### `image.setImage(image)` _Experimental_
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/46760
```
-->
* `image` NativeImage
Sets the image for this `ImageView`. Note that only image formats supported by

View File

@@ -1,5 +1,12 @@
# inAppPurchase
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/11292
```
-->
> In-app purchases on Mac App Store.
Process: [Main](../glossary.md#main-process)
@@ -10,6 +17,13 @@ The `inAppPurchase` module emits the following events:
### Event: 'transactions-updated'
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/11292
```
-->
Returns:
* `event` Event
@@ -23,6 +37,19 @@ The `inAppPurchase` module has the following methods:
### `inAppPurchase.purchaseProduct(productID[, opts])`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/11292
changes:
- pr-url: https://github.com/electron/electron/pull/17355
description: "This method now returns a Promise instead of using a callback function."
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
- pr-url: https://github.com/electron/electron/pull/35902
description: "Added `username` option to `opts` parameter."
```
-->
* `productID` string
* `opts` Integer | Object (optional) - If specified as an integer, defines the quantity.
* `quantity` Integer (optional) - The number of items the user wants to purchase.
@@ -34,6 +61,17 @@ You should listen for the `transactions-updated` event as soon as possible and c
### `inAppPurchase.getProducts(productIDs)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/12464
changes:
- pr-url: https://github.com/electron/electron/pull/17355
description: "This method now returns a Promise instead of using a callback function."
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
```
-->
* `productIDs` string[] - The identifiers of the products to get.
Returns `Promise<Product[]>` - Resolves with an array of [`Product`](structures/product.md) objects.
@@ -42,24 +80,59 @@ Retrieves the product descriptions.
### `inAppPurchase.canMakePayments()`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/11292
```
-->
Returns `boolean` - whether a user can make a payment.
### `inAppPurchase.restoreCompletedTransactions()`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/21461
```
-->
Restores finished transactions. This method can be called either to install purchases on additional devices, or to restore purchases for an application that the user deleted and reinstalled.
[The payment queue](https://developer.apple.com/documentation/storekit/skpaymentqueue?language=objc) delivers a new transaction for each previously completed transaction that can be restored. Each transaction includes a copy of the original transaction.
### `inAppPurchase.getReceiptURL()`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/11292
```
-->
Returns `string` - the path to the receipt.
### `inAppPurchase.finishAllTransactions()`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/12464
```
-->
Completes all pending transactions.
### `inAppPurchase.finishTransactionByDate(date)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/12464
```
-->
* `date` string - The ISO formatted date of the transaction to finish.
Completes the pending transactions corresponding to the date.

View File

@@ -46,6 +46,13 @@ Listens to `channel`, when a new message arrives `listener` would be called with
### `ipcMain.off(channel, listener)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/44651
```
-->
* `channel` string
* `listener` Function
* `event` [IpcMainEvent][ipc-main-event]
@@ -89,6 +96,13 @@ Removes all listeners from the specified `channel`. Removes all listeners from a
### `ipcMain.handle(channel, listener)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/18449
```
-->
* `channel` string
* `listener` Function\<Promise\<any\> | any\>
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
@@ -126,6 +140,13 @@ provided to the renderer process. Please refer to
### `ipcMain.handleOnce(channel, listener)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/18449
```
-->
* `channel` string
* `listener` Function\<Promise\<any\> | any\>
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
@@ -136,6 +157,13 @@ Handles a single `invoke`able IPC message, then removes the listener. See
### `ipcMain.removeHandler(channel)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/18449
```
-->
* `channel` string
Removes any handler for `channel`, if present.

View File

@@ -59,6 +59,13 @@ for more info.
### `ipcRenderer.off(channel, listener)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/39816
```
-->
* `channel` string
* `listener` Function
* `event` [IpcRendererEvent][ipc-renderer-event]
@@ -79,6 +86,13 @@ only the next time a message is sent to `channel`, after which it is removed.
### `ipcRenderer.addListener(channel, listener)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/39816
```
-->
* `channel` string
* `listener` Function
* `event` [IpcRendererEvent][ipc-renderer-event]
@@ -129,6 +143,13 @@ If you want to receive a single response from the main process, like the result
### `ipcRenderer.invoke(channel, ...args)`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/18449
```
-->
* `channel` string
* `...args` any[]
@@ -209,6 +230,13 @@ and replies by setting `event.returnValue`.
### `ipcRenderer.postMessage(channel, message, [transfer])`
<!--
```YAML history
added:
- pr-url: https://github.com/electron/electron/pull/22404
```
-->
* `channel` string
* `message` any
* `transfer` MessagePort[] (optional)

View File

@@ -84,3 +84,7 @@ Currently, Windows high contrast is the only system setting that triggers forced
### `nativeTheme.prefersReducedTransparency` _Readonly_
A `boolean` that indicates whether the user has chosen via system accessibility settings to reduce transparency at the OS level.
### `nativeTheme.shouldDifferentiateWithoutColor` _macOS_ _Readonly_
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).

View File

@@ -79,20 +79,26 @@ app.whenReady().then(() => {
### `new Notification([options])`
* `options` Object (optional)
* `id` string (optional) _macOS_ - A unique identifier for the notification, mapping to `UNNotificationRequest`'s [`identifier`](https://developer.apple.com/documentation/usernotifications/unnotificationrequest/identifier) property. Defaults to a random UUID if not provided or if an empty string is passed. This can be used to remove or update previously delivered notifications.
* `groupId` string (optional) _macOS_ - A string identifier used to visually group notifications together in Notification Center. Maps to `UNNotificationContent`'s [`threadIdentifier`](https://developer.apple.com/documentation/usernotifications/unnotificationcontent/threadidentifier) property.
* `title` string (optional) - A title for the notification, which will be displayed at the top of the notification window when it is shown.
* `subtitle` string (optional) _macOS_ - A subtitle for the notification, which will be displayed below the title.
* `body` string (optional) - The body text of the notification, which will be displayed below the title or subtitle.
* `silent` boolean (optional) - Whether or not to suppress the OS notification noise when showing the notification.
* `icon` (string | [NativeImage](native-image.md)) (optional) - An icon to use in the notification. If a string is passed, it must be a valid path to a local icon file.
* `hasReply` boolean (optional) _macOS_ - Whether or not to add an inline reply option to the notification.
* `hasReply` boolean (optional) _macOS_ _Windows_ - Whether or not to add an inline reply option to the notification.
* `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.
* `replyPlaceholder` string (optional) _macOS_ _Windows_ - 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'.
* `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.
* `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_ _Windows_ - 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:
@@ -323,6 +329,14 @@ app.whenReady().then(() => {
### Instance Properties
#### `notification.id` _macOS_ _Readonly_
A `string` property representing the unique identifier of the notification. This is set at construction time — either from the `id` option or as a generated UUID if none was provided.
#### `notification.groupId` _macOS_ _Readonly_
A `string` property representing the group identifier of the notification. Notifications with the same `groupId` will be visually grouped together in Notification Center.
#### `notification.title`
A `string` property representing the title of the notification.

View File

@@ -56,6 +56,15 @@ app.whenReady().then(() => {
})
```
## Protocol names
[RFC 3986](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) defines what a valid
protocol name is:
> Scheme names consist of a sequence of characters beginning with a letter and followed
> by any combination of letters, digits, plus ("+"), period ("."), or hyphen ("-").
> Although schemes are case-insensitive, the canonical form is lowercase […].
## Methods
The `protocol` module has the following methods:

View File

@@ -59,7 +59,12 @@ On Windows, returns true once the app has emitted the `ready` event.
### `safeStorage.isAsyncEncryptionAvailable()`
Returns `Promise<Boolean>` - Whether encryption is available for asynchronous safeStorage operations.
Returns `Promise<boolean>` - Resolves with whether encryption is available for
asynchronous safeStorage operations.
The asynchronous encryptor is initialized lazily the first time this method,
`encryptStringAsync`, or `decryptStringAsync` is called after the app is ready.
The returned promise resolves once initialization completes.
### `safeStorage.encryptString(plainText)`

View File

@@ -110,6 +110,8 @@ Returns [`Point`](structures/point.md)
The current absolute position of the mouse pointer.
Not supported on Wayland (Linux).
> [!NOTE]
> The return value is a DIP point, not a screen physical point.

View File

@@ -11,3 +11,5 @@
* `stream` boolean (optional) - Default false.
* `codeCache` boolean (optional) - Enable V8 code cache for the scheme, only
works when `standard` is also set to true. Default false.
* `allowExtensions` boolean (optional) - Allow Chrome extensions to be used
on pages served over this protocol. Default false.

View File

@@ -94,6 +94,7 @@
The actual output pixel format and color space of the texture should refer to [`OffscreenSharedTexture`](../structures/offscreen-shared-texture.md) object in the `paint` event.
* `argb` - The requested output texture format is 8-bit unorm RGBA, with SRGB SDR color space.
* `rgbaf16` - The requested output texture format is 16-bit float RGBA, with scRGB HDR color space.
* `nv12` - The requested output texture format is 12bpp with Y plane followed by a 2x2 interleaved UV plane, with REC709 color space.
* `deviceScaleFactor` number (optional) _Experimental_ - The device scale factor of the offscreen rendering output. If not set, will use `1` as default.
* `contextIsolation` boolean (optional) - Whether to run Electron APIs and
the specified `preload` script in a separate JavaScript context. Defaults

View File

@@ -1485,6 +1485,11 @@ mainWindow.webContents.setWindowOpenHandler((details) => {
const browserView = new BrowserView(options)
mainWindow.addBrowserView(browserView)
browserView.setBounds({ x: 0, y: 0, width: 640, height: 480 })
// 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
}
}
@@ -1580,6 +1585,20 @@ Centers the current text selection in web page.
Copy the image at the given position to the clipboard.
#### `contents.copyVideoFrameAt(x, y)`
* `x` Integer
* `y` Integer
When executed on a video media element, copies the frame at (x, y) to the clipboard.
#### `contents.saveVideoFrameAs(x, y)`
* `x` Integer
* `y` Integer
When executed on a video media element, shows a save dialog and saves the frame at (x, y) to disk.
#### `contents.paste()`
Executes the editing command `paste` in web page.
@@ -2235,6 +2254,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.
#### `contents.getOrCreateDevToolsTargetId()`
Returns `string` - The Chrome DevTools Protocol
[TargetID](https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetID)
associated with this WebContents. This is the reverse of
[`webContents.fromDevToolsTargetId()`](#webcontentsfromdevtoolstargetidtargetid).
> [!NOTE]
> This method creates a new DevTools agent for this WebContents if one does not already exist.
#### `contents.getOSProcessId()`
Returns `Integer` - The operating system `pid` of the associated renderer

View File

@@ -175,6 +175,20 @@ app.on('web-contents-created', (_, webContents) => {
})
```
#### `frame.copyVideoFrameAt(x, y)`
* `x` Integer
* `y` Integer
When executed on a video media element, copies the frame at (x, y) to the clipboard.
#### `frame.saveVideoFrameAs(x, y)`
* `x` Integer
* `y` Integer
When executed on a video media element, shows a save dialog and saves the frame at (x, y) to disk.
### Instance Properties
#### `frame.ipc` _Readonly_

View File

@@ -12,6 +12,34 @@ This document uses the following convention to categorize breaking changes:
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
* **Removed:** An API or feature was removed, and is no longer supported by Electron.
## Planned Breaking API Changes (43.0)
### Behavior Changed: Dialog methods default to Downloads directory
The `defaultPath` option for the following methods now defaults to the user's Downloads folder (or their home directory if Downloads doesn't exist) when not explicitly provided:
* `dialog.showOpenDialog`
* `dialog.showOpenDialogSync`
* `dialog.showSaveDialog`
* `dialog.showSaveDialogSync`
Previously, when no `defaultPath` was provided, the underlying OS file dialog would determine the initial directory — typically remembering the last directory the user navigated to, or falling back to an OS-specific default. Now, Electron explicitly sets the initial directory to Downloads, which also means the OS will no longer track and restore the last-used directory between dialog invocations.
To preserve the old behavior, you can track the last-used directory yourself and pass it as `defaultPath`:
```js
const path = require('node:path')
let lastUsedPath
const result = await dialog.showOpenDialog({
defaultPath: lastUsedPath
})
if (!result.canceled && result.filePaths.length > 0) {
lastUsedPath = path.dirname(result.filePaths[0])
}
```
## Planned Breaking API Changes (42.0)
### Behavior Changed: macOS notifications now use `UNNotification` API
@@ -59,6 +87,20 @@ npm install electron --save-dev --ignore-scripts
npx install-electron --no
```
If you need to test changes across platforms or architectures, you should now use the
`ELECTRON_INSTALL_ARCH` and `ELECTRON_INSTALL_PLATFORM` environment variables.
```sh
# before: pass npm config flag on install command
npm install --platform=mas electron --save-dev
# after: add env var when you first run the Electron command
npm install electron --save-dev
ELECTRON_INSTALL_PLATFORM=mas npx electron . --no
```
This also means the `ELECTRON_SKIP_BINARY_DOWNLOAD` environment variable is no
longer supported, as its primary purpose was to prevent the `postinstall` script from running.
### Removed: `quotas` object from `Session.clearStorageData(options)`
When calling `Session.clearStorageData(options)`, the `options.quotas` object is no longer supported because it has been

View File

@@ -39,7 +39,7 @@ etc.
## Documentation
* Write [remark](https://github.com/remarkjs/remark) markdown style.
* Write prose according to our [documentation style guide](./style-guide.md).
You can run `npm run lint:docs` to ensure that your documentation changes are
formatted correctly.

View File

@@ -21,24 +21,33 @@
### Step 1: Fork
Fork the project [on GitHub](https://github.com/electron/electron) and clone your fork
locally.
```sh
$ git clone git@github.com:username/electron.git
$ cd electron
$ git remote add upstream https://github.com/electron/electron.git
$ git fetch upstream
```
Fork Electron's [GitHub repository](https://github.com/electron/electron).
### Step 2: Build
Build steps and dependencies differ slightly depending on your operating system.
See these detailed guides on building Electron locally:
We recommend using [`@electron/build-tools`](https://github.com/electron/build-tools) to build
Electron itself.
* [Building on macOS](build-instructions-macos.md)
* [Building on Linux](build-instructions-linux.md)
* [Building on Windows](build-instructions-windows.md)
```sh
# Install build-tools package globally:
npm install -g @electron/build-tools
# Run the init script where you want to clone the project and point it to your fork:
e init --fork my-org/electron --bootstrap testing
```
This will create a new `electron` folder in your working directory and initialize the project.
Once the build completes, navigate to `electron/src/electron`, where your fork is actually cloned.
> [!IMPORTANT]
> Your Electron project has a complex folder structure with nested repositories.
> See the [Build Instructions](./build-instructions-gn.md) docs for detailed Build Tools
> usage instructions (e.g. how to sync dependencies or how to recompile the binary)
> and platform-specific notices.
There, you should have two `remote` URLs in git:
* `origin` will point to `electron/electron`
* `fork` will point to your fork (`my-org/electron`)
Once you've built the project locally, you're ready to start making changes!
@@ -48,7 +57,7 @@ To keep your development environment organized, create local branches to
hold your work. These should be branched directly off of the `main` branch.
```sh
$ git checkout -b my-branch -t upstream/main
git checkout -b my-branch
```
## Making Changes
@@ -60,7 +69,7 @@ changes to either the C/C++ code in the `shell/` folder,
the JavaScript code in the `lib/` folder, the documentation in `docs/api/`
or tests in the `spec/` folder.
Please be sure to run `npm run lint` from time to time on any code changes
Please be sure to run `yarn lint` from time to time on any code changes
to ensure that they follow the project's code style.
See [coding style](coding-style.md) for
@@ -75,8 +84,8 @@ across multiple commits. There is no limit to the number of commits in a
pull request.
```sh
$ git add my/changed/files
$ git commit
git add my/changed/files
git commit
```
Note that multiple commits get squashed when they are landed.
@@ -138,8 +147,8 @@ Once you have committed your changes, it is a good idea to use `git rebase`
(not `git merge`) to synchronize your work with the main repository.
```sh
$ git fetch upstream
$ git rebase upstream/main
git fetch origin
git rebase origin/main
```
This ensures that your working branch has the latest changes from `electron/electron`
@@ -156,7 +165,7 @@ Before submitting your changes in a pull request, always run the full
test suite. To run the tests:
```sh
$ npm run test
yarn test
```
Make sure the linter does not report any issues and that all tests pass.
@@ -165,7 +174,7 @@ Please do not submit patches that fail either check.
If you are updating tests and want to run a single spec to check it:
```sh
$ npm run test -match=menu
yarn test -match=menu
```
The above would only run spec modules matching `menu`, which is useful for
@@ -179,7 +188,7 @@ begin the process of opening a pull request by pushing your working branch
to your fork on GitHub.
```sh
$ git push origin my-branch
git push fork my-branch
```
### Step 9: Opening the Pull Request
@@ -203,9 +212,9 @@ branch, add a new commit with those changes, and push those to your fork.
GitHub will automatically update the pull request.
```sh
$ git add my/changed/files
$ git commit
$ git push origin my-branch
git add my/changed/files
git commit
git push fork my-branch
```
There are a number of more advanced mechanisms for managing commits using
@@ -213,8 +222,8 @@ There are a number of more advanced mechanisms for managing commits using
Feel free to post a comment in the pull request to ping reviewers if you are
awaiting an answer on something. If you encounter words or acronyms that
seem unfamiliar, refer to this
[glossary](https://sites.google.com/a/chromium.org/dev/glossary).
seem unfamiliar, refer to the
[Chromium glossary](https://sites.google.com/a/chromium.org/dev/glossary).
#### Approval and Request Changes Workflow

View File

@@ -12,6 +12,10 @@ To create a frameless window, set the [`BaseWindowContructorOptions`][] `frame`
```
On Wayland (Linux), frameless windows have GTK drop shadows and extended
resize boundaries by default. To create a fully frameless window with no
decorations, set `hasShadow: false` in the window constructor options.
## Transparent windows
![Transparent Window](../images/transparent-window.png)

View File

@@ -7,47 +7,7 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
## Timeline
| Electron | Alpha | Beta | Stable | EOL | Chrome | Node | Supported |
| ------- | ----- | ------- | ------ | ------ | ---- | ---- | ---- |
| 40.0.0 | 2025-Oct-30 | 2025-Dec-03 | 2026-Jan-13 | 2026-Jun-30 | M144 | TBD | ✅ |
| 39.0.0 | 2025-Sep-04 | 2025-Oct-01 | 2025-Oct-28 | 2026-May-05 | M142 | v22.20 | ✅ |
| 38.0.0 | 2025-Jun-26 | 2025-Aug-06 | 2025-Sep-02 | 2026-Mar-10 | M140 | v22.18 | ✅ |
| 37.0.0 | 2025-May-01 | 2025-May-28 | 2025-Jun-24 | 2026-Jan-13 | M138 | v22.16 | ✅ |
| 36.0.0 | 2025-Mar-06 | 2025-Apr-02 | 2025-Apr-29 | 2025-Oct-28 | M136 | v22.14 | 🚫 |
| 35.0.0 | 2025-Jan-16 | 2025-Feb-05 | 2025-Mar-04 | 2025-Sep-02 | M134 | v22.14 | 🚫 |
| 34.0.0 | 2024-Oct-17 | 2024-Nov-13 | 2025-Jan-14 | 2025-Jun-24 | M132 | v20.18 | 🚫 |
| 33.0.0 | 2024-Aug-22 | 2024-Sep-18 | 2024-Oct-15 | 2025-Apr-29 | M130 | v20.18 | 🚫 |
| 32.0.0 | 2024-Jun-14 | 2024-Jul-24 | 2024-Aug-20 | 2025-Mar-04 | M128 | v20.16 | 🚫 |
| 31.0.0 | 2024-Apr-18 | 2024-May-15 | 2024-Jun-11 | 2025-Jan-14 | M126 | v20.14 | 🚫 |
| 30.0.0 | 2024-Feb-22 | 2024-Mar-20 | 2024-Apr-16 | 2024-Oct-15 | M124 | v20.11 | 🚫 |
| 29.0.0 | 2023-Dec-07 | 2024-Jan-24 | 2024-Feb-20 | 2024-Aug-20 | M122 | v20.9 | 🚫 |
| 28.0.0 | 2023-Oct-11 | 2023-Nov-06 | 2023-Dec-05 | 2024-Jun-11 | M120 | v18.18 | 🚫 |
| 27.0.0 | 2023-Aug-17 | 2023-Sep-13 | 2023-Oct-10 | 2024-Apr-16 | M118 | v18.17 | 🚫 |
| 26.0.0 | 2023-Jun-01 | 2023-Jun-27 | 2023-Aug-15 | 2024-Feb-20 | M116 | v18.16 | 🚫 |
| 25.0.0 | 2023-Apr-10 | 2023-May-02 | 2023-May-30 | 2023-Dec-05 | M114 | v18.15 | 🚫 |
| 24.0.0 | 2023-Feb-09 | 2023-Mar-07 | 2023-Apr-04 | 2023-Oct-10 | M112 | v18.14 | 🚫 |
| 23.0.0 | 2022-Dec-01 | 2023-Jan-10 | 2023-Feb-07 | 2023-Aug-15 | M110 | v18.12 | 🚫 |
| 22.0.0 | 2022-Sep-29 | 2022-Oct-25 | 2022-Nov-29 | 2023-Oct-10 | M108 | v16.17 | 🚫 |
| 21.0.0 | 2022-Aug-04 | 2022-Aug-30 | 2022-Sep-27 | 2023-Apr-04 | M106 | v16.16 | 🚫 |
| 20.0.0 | 2022-May-26 | 2022-Jun-21 | 2022-Aug-02 | 2023-Feb-07 | M104 | v16.15 | 🚫 |
| 19.0.0 | 2022-Mar-31 | 2022-Apr-26 | 2022-May-24 | 2022-Nov-29 | M102 | v16.14 | 🚫 |
| 18.0.0 | 2022-Feb-03 | 2022-Mar-03 | 2022-Mar-29 | 2022-Sep-27 | M100 | v16.13 | 🚫 |
| 17.0.0 | 2021-Nov-18 | 2022-Jan-06 | 2022-Feb-01 | 2022-Aug-02 | M98 | v16.13 | 🚫 |
| 16.0.0 | 2021-Sep-23 | 2021-Oct-20 | 2021-Nov-16 | 2022-May-24 | M96 | v16.9 | 🚫 |
| 15.0.0 | 2021-Jul-20 | 2021-Sep-01 | 2021-Sep-21 | 2022-May-24 | M94 | v16.5 | 🚫 |
| 14.0.0 | -- | 2021-May-27 | 2021-Aug-31 | 2022-Mar-29 | M93 | v14.17 | 🚫 |
| 13.0.0 | -- | 2021-Mar-04 | 2021-May-25 | 2022-Feb-01 | M91 | v14.16 | 🚫 |
| 12.0.0 | -- | 2020-Nov-19 | 2021-Mar-02 | 2021-Nov-16 | M89 | v14.16 | 🚫 |
| 11.0.0 | -- | 2020-Aug-27 | 2020-Nov-17 | 2021-Aug-31 | M87 | v12.18 | 🚫 |
| 10.0.0 | -- | 2020-May-21 | 2020-Aug-25 | 2021-May-25 | M85 | v12.16 | 🚫 |
| 9.0.0 | -- | 2020-Feb-06 | 2020-May-19 | 2021-Mar-02 | M83 | v12.14 | 🚫 |
| 8.0.0 | -- | 2019-Oct-24 | 2020-Feb-04 | 2020-Nov-17 | M80 | v12.13 | 🚫 |
| 7.0.0 | -- | 2019-Aug-01 | 2019-Oct-22 | 2020-Aug-25 | M78 | v12.8 | 🚫 |
| 6.0.0 | -- | 2019-Apr-25 | 2019-Jul-30 | 2020-May-19 | M76 | v12.14.0 | 🚫 |
| 5.0.0 | -- | 2019-Jan-22 | 2019-Apr-23 | 2020-Feb-04 | M73 | v12.0 | 🚫 |
| 4.0.0 | -- | 2018-Oct-11 | 2018-Dec-20 | 2019-Oct-22 | M69 | v10.11 | 🚫 |
| 3.0.0 | -- | 2018-Jun-21 | 2018-Sep-18 | 2019-Jul-30 | M66 | v10.2 | 🚫 |
| 2.0.0 | -- | 2018-Feb-21 | 2018-May-01 | 2019-Apr-23 | M61 | v8.9 | 🚫 |
[Electron's Release Schedule](https://releases.electronjs.org/schedule) lists a schedule of Electron major releases showing key milestones including alpha, beta, and stable release dates, as well as end-of-life dates and dependency versions.
:::info Official support dates may change

View File

@@ -146,13 +146,15 @@ The extra privileges granted to the `file://` protocol by this fuse are incomple
The `wasmTrapHandlers` fuse controls whether V8 will use signal handlers to trap Out of Bounds memory
access from WebAssembly. The feature works by surrounding the WebAssembly memory with large guard regions
and then installing a signal handler that traps attempt to access memory in the guard region. The feature
is only supported on the following 64-bit systems.
is only supported on the following 64-bit systems:
Linux. MacOS, Windows - x86_64
Linux, MacOS - aarch64
* Linux, macOS, Windows - x86_64
* Linux, macOS - aarch64
```text
| Guard Pages | WASM heap | Guard Pages |
|-----8GB-----| |-----8GB-----|
```
When the fuse is disabled V8 will use explicit bound checks in the generated WebAssembly code to ensure
memory safety. However, this method has some downsides

View File

@@ -25,16 +25,6 @@ included in the `electron` package:
npx install-electron --no
```
If you want to install your project's dependencies but don't need to use
Electron functionality, you can set the `ELECTRON_SKIP_BINARY_DOWNLOAD` environment
variable to prevent the binary from being downloaded. For instance, this feature can
be useful in continuous integration environments when running unit tests that mock
out the `electron` module.
```sh
ELECTRON_SKIP_BINARY_DOWNLOAD=1 npm install
```
## Running Electron ad-hoc
If you're in a pinch and would prefer to not use `npm install` in your local
@@ -51,20 +41,40 @@ any dependencies in your app will not be installed.
## Customization
If you want to change the architecture that is downloaded (e.g., `x64` on an
`arm64` machine), you can use the `--arch` flag with npm install or set the
`npm_config_arch` environment variable:
`arm64` machine), you can set the `ELECTRON_INSTALL_ARCH` environment variable:
```shell
npm install --arch=x64 electron
```sh
# Inside an npm script or with npx
ELECTRON_INSTALL_ARCH=x64 electron .
```
Supported architectures are a subset of Node.js [`process.arch`](https://nodejs.org/api/process.html#processarch)
values, and include:
* `x64` (Intel Mac and 64-bit Windows)
* `ia32` (32-bit Windows)
* `arm64` (Apple silicon, Windows on ARM, ARM64 Linux)
* `arm` (32-bit ARM)
In addition to changing the architecture, you can also specify the platform
(e.g., `win32`, `linux`, etc.) using the `--platform` flag:
```shell
npm install --platform=win32 electron
```sh
# Inside an npm script or with npx
ELECTRON_INSTALL_PLATFORM=mas electron .
```
Supported platforms are Node-like [platform strings](https://nodejs.org/api/process.html#processplatform):
* `darwin`
* `mas` ([Mac App Store](./mac-app-store-submission-guide.md))
* `win32`
* `linux`
> [!TIP]
> To see all available platform/architecture combinations for a particular release, see the artifacts
> on [Electron's GitHub Releases](https://github.com/electron/electron/releases).
## Proxies
If you need to use an HTTP proxy, you need to set the `ELECTRON_GET_USE_PROXY` variable to any

View File

@@ -50,7 +50,7 @@ sections.
In the main process, set an IPC listener on the `set-title` channel with the `ipcMain.on` API:
```js {6-10,22} title='main.js (Main Process)'
```js {7-11,23} title='main.js (Main Process)'
const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('node:path')

View File

@@ -87,6 +87,13 @@ if (!gotTheLock) {
// Create mainWindow, load the rest of the app, etc...
app.whenReady().then(() => {
createWindow()
// Check for deep link on cold start
if (process.argv.length >= 2) {
const lastArg = process.argv[process.argv.length - 1]
if (lastArg.startsWith('electron-fiddle://')) {
dialog.showErrorBox('Welcome Back', `You arrived from: ${lastArg}`)
}
}
})
}
```

View File

@@ -1097,7 +1097,8 @@ public:
Napi::Function func = DefineClass(env, "CppLinuxAddon", {
InstanceMethod("helloWorld", &CppAddon::HelloWorld),
InstanceMethod("helloGui", &CppAddon::HelloGui),
InstanceMethod("on", &CppAddon::On)
InstanceMethod("on", &CppAddon::On),
InstanceMethod("destroy", &CppAddon::Destroy)
});
Napi::FunctionReference *constructor = new Napi::FunctionReference();
@@ -1139,11 +1140,12 @@ private:
Here, we create a C++ class that inherits from `Napi::ObjectWrap<CppAddon>`:
`static Napi::Object Init` defines our JavaScript interface with three methods:
`static Napi::Object Init` defines our JavaScript interface with four methods:
* `helloWorld`: A simple function to test the bridge
* `helloGui`: The function to launch our GTK3 UI
* `on`: A method to register event callbacks
* `destroy`: A method to release all persistent references before app quit
The constructor initializes:
@@ -1354,7 +1356,8 @@ public:
Napi::Function func = DefineClass(env, "CppLinuxAddon", {
InstanceMethod("helloWorld", &CppAddon::HelloWorld),
InstanceMethod("helloGui", &CppAddon::HelloGui),
InstanceMethod("on", &CppAddon::On)
InstanceMethod("on", &CppAddon::On),
InstanceMethod("destroy", &CppAddon::Destroy)
});
Napi::FunctionReference *constructor = new Napi::FunctionReference();
@@ -1497,6 +1500,20 @@ private:
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo &info)
{
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr)
{
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
};
Napi::Object Init(Napi::Env env, Napi::Object exports)
@@ -1547,6 +1564,10 @@ class CppLinuxAddon extends EventEmitter {
return this.addon.helloGui()
}
destroy() {
this.addon.destroy()
}
// Parse JSON and convert date to JavaScript Date object
parse(payload) {
const parsed = JSON.parse(payload)
@@ -1569,8 +1590,12 @@ This wrapper:
* Only loads on Linux platforms
* Forwards events from C++ to JavaScript
* Provides clean methods to call into C++
* Provides a `destroy()` method to release native resources
* Converts JSON data into proper JavaScript objects
> [!IMPORTANT]
> You must call `destroy()` before the app quits (e.g. in the `will-quit` or `before-quit` event handler). Without this, persistent references to callbacks and the threadsafe function will prevent the native addon's destructor from running, causing Electron to hang on quit.
## 7) Building and testing the addon
With all files in place, you can build the addon:

View File

@@ -1099,7 +1099,8 @@ static Napi::Object Init(Napi::Env env, Napi::Object exports) {
Napi::Function func = DefineClass(env, "CppWin32Addon", {
InstanceMethod("helloWorld", &CppAddon::HelloWorld),
InstanceMethod("helloGui", &CppAddon::HelloGui),
InstanceMethod("on", &CppAddon::On)
InstanceMethod("on", &CppAddon::On),
InstanceMethod("destroy", &CppAddon::Destroy)
});
// ... rest of Init function
@@ -1117,9 +1118,21 @@ Napi::Value On(const Napi::CallbackInfo& info) {
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo& info) {
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr) {
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
```
This allows JavaScript to register callbacks for specific event types.
This allows JavaScript to register callbacks for specific event types. The `Destroy` method releases all persistent references and aborts the threadsafe function, which must be called before the app quits to prevent the process from hanging.
### Putting the bridge together
@@ -1261,6 +1274,18 @@ private:
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo& info) {
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr) {
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
};
Napi::Object Init(Napi::Env env, Napi::Object exports) {
@@ -1309,6 +1334,10 @@ class CppWin32Addon extends EventEmitter {
this.addon.helloGui()
}
destroy() {
this.addon.destroy()
}
#parse(payload) {
const parsed = JSON.parse(payload)
@@ -1323,6 +1352,9 @@ if (process.platform === 'win32') {
}
```
> [!IMPORTANT]
> You must call `destroy()` before the app quits (e.g. in the `will-quit` or `before-quit` event handler). Without this, persistent references to callbacks and the threadsafe function will prevent the native addon's destructor from running, causing Electron to hang on quit.
## 7) Building and Testing the Addon
With all files in place, you can build the addon:

View File

@@ -753,7 +753,8 @@ public:
Napi::Function func = DefineClass(env, "ObjcMacosAddon", {
InstanceMethod("helloWorld", &ObjcAddon::HelloWorld),
InstanceMethod("helloGui", &ObjcAddon::HelloGui),
InstanceMethod("on", &ObjcAddon::On)
InstanceMethod("on", &ObjcAddon::On),
InstanceMethod("destroy", &ObjcAddon::Destroy)
});
Napi::FunctionReference* constructor = new Napi::FunctionReference();
@@ -915,6 +916,18 @@ Napi::Value On(const Napi::CallbackInfo& info) {
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo& info) {
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr) {
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
```
Let's take a look at what we've added in this step:
@@ -922,10 +935,11 @@ Let's take a look at what we've added in this step:
* `HelloWorld()`: Takes a string input, calls our Objective-C function, and returns the result
* `HelloGui()`: A simple wrapper around the Objective-C `hello_gui` function
* `On`: Allows JavaScript to register event listeners that will be called when native events occur
* `Destroy`: Releases all persistent references (callbacks and emitter) and aborts the threadsafe function, allowing the addon to be properly cleaned up on quit
The `On` method is particularly important as it creates the event system that our JavaScript code will use to receive notifications from the native UI.
Together, these three components form a complete bridge between our Objective-C code and the JavaScript world, allowing bidirectional communication. Here's what the finished file should look like:
Together, these four components form a complete bridge between our Objective-C code and the JavaScript world, allowing bidirectional communication. Here's what the finished file should look like:
```objc title='src/objc_addon.mm'
#include <napi.h>
@@ -938,7 +952,8 @@ public:
Napi::Function func = DefineClass(env, "ObjcMacosAddon", {
InstanceMethod("helloWorld", &ObjcAddon::HelloWorld),
InstanceMethod("helloGui", &ObjcAddon::HelloGui),
InstanceMethod("on", &ObjcAddon::On)
InstanceMethod("on", &ObjcAddon::On),
InstanceMethod("destroy", &ObjcAddon::Destroy)
});
Napi::FunctionReference* constructor = new Napi::FunctionReference();
@@ -1061,6 +1076,18 @@ private:
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo& info) {
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr) {
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
};
Napi::Object Init(Napi::Env env, Napi::Object exports) {
@@ -1101,6 +1128,10 @@ class ObjcMacosAddon extends EventEmitter {
this.addon.helloGui()
}
destroy () {
this.addon.destroy()
}
parse (payload) {
const parsed = JSON.parse(payload)
@@ -1122,7 +1153,11 @@ This wrapper:
3. Loads the native addon
4. Sets up event listeners and forwards them
5. Provides a clean API for our functions
6. Parses JSON payloads and converts timestamps to JavaScript Date objects
6. Provides a `destroy()` method to release native resources
7. Parses JSON payloads and converts timestamps to JavaScript Date objects
> [!IMPORTANT]
> You must call `destroy()` before the app quits (e.g. in the `will-quit` or `before-quit` event handler). Without this, persistent references to callbacks and the threadsafe function will prevent the native addon's destructor from running, causing Electron to hang on quit.
## 7) Building and Testing the Addon

View File

@@ -752,7 +752,8 @@ public:
Napi::Function func = DefineClass(env, "SwiftAddon", {
InstanceMethod("helloWorld", &SwiftAddon::HelloWorld),
InstanceMethod("helloGui", &SwiftAddon::HelloGui),
InstanceMethod("on", &SwiftAddon::On)
InstanceMethod("on", &SwiftAddon::On),
InstanceMethod("destroy", &SwiftAddon::Destroy)
});
Napi::FunctionReference* constructor = new Napi::FunctionReference();
@@ -770,7 +771,7 @@ This first part:
1. Defines a C++ class that inherits from `Napi::ObjectWrap`
2. Creates a static `Init` method to register our class with Node.js
3. Defines three methods: `helloWorld`, `helloGui`, and `on`
3. Defines four methods: `helloWorld`, `helloGui`, `on`, and `destroy`
### Callback Mechanism
@@ -919,6 +920,18 @@ private:
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo& info) {
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr) {
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
};
Napi::Object Init(Napi::Env env, Napi::Object exports) {
@@ -934,7 +947,8 @@ This final part does multiple things:
2. The HelloWorld method implementation takes a string input from JavaScript, passes it to the Swift code, and returns the processed result back to the JavaScript environment.
3. The `HelloGui` method implementation provides a simple wrapper that calls the Swift UI creation function to display the native macOS window.
4. The `On` method implementation allows JavaScript code to register callback functions that will be invoked when specific events occur in the native Swift code.
5. The code sets up the module initialization process that registers the addon with Node.js and makes its functionality available to JavaScript.
5. The `Destroy` method releases all persistent references (callbacks and emitter) and aborts the threadsafe function. This must be called before the app quits to allow the destructor to run and prevent the process from hanging.
6. The code sets up the module initialization process that registers the addon with Node.js and makes its functionality available to JavaScript.
The final and full `src/swift_addon.mm` should look like:
@@ -949,7 +963,8 @@ public:
Napi::Function func = DefineClass(env, "SwiftAddon", {
InstanceMethod("helloWorld", &SwiftAddon::HelloWorld),
InstanceMethod("helloGui", &SwiftAddon::HelloGui),
InstanceMethod("on", &SwiftAddon::On)
InstanceMethod("on", &SwiftAddon::On),
InstanceMethod("destroy", &SwiftAddon::Destroy)
});
Napi::FunctionReference* constructor = new Napi::FunctionReference();
@@ -1074,6 +1089,18 @@ private:
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo& info) {
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr) {
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
};
Napi::Object Init(Napi::Env env, Napi::Object exports) {
@@ -1122,6 +1149,10 @@ class SwiftAddon extends EventEmitter {
this.addon.helloGui()
}
destroy () {
this.addon.destroy()
}
parse (payload) {
const parsed = JSON.parse(payload)
@@ -1143,7 +1174,11 @@ This wrapper:
3. Loads the native addon
4. Sets up event listeners and forwards them
5. Provides a clean API for our functions
6. Parses JSON payloads and converts timestamps to JavaScript Date objects
6. Provides a `destroy()` method to release native resources
7. Parses JSON payloads and converts timestamps to JavaScript Date objects
> [!IMPORTANT]
> You must call `destroy()` before the app quits (e.g. in the `will-quit` or `before-quit` event handler). Without this, persistent references to callbacks and the threadsafe function will prevent the native addon's destructor from running, causing Electron to hang on quit.
## 7) Building and Testing the Addon

View File

@@ -83,17 +83,6 @@ dependency.
npm install electron --save-dev
```
:::warning
In order to correctly install Electron, you need to ensure that its `postinstall` lifecycle
script is able to run. This means avoiding the `--ignore-scripts` flag on npm and allowlisting
`electron` to run build scripts on other package managers.
This is likely to change in a future version of Electron. See
[electron/rfcs#22](https://github.com/electron/rfcs/pull/22) for more details.
:::
Your package.json file should look something like this after initializing your package
and installing Electron. You should also now have a `node_modules` folder containing
the Electron executable, as well as a `package-lock.json` lockfile that specifies

View File

@@ -78,6 +78,7 @@ auto_filenames = {
"docs/api/web-utils.md",
"docs/api/webview-tag.md",
"docs/api/window-open.md",
"docs/api/structures/activation-arguments.md",
"docs/api/structures/base-window-options.md",
"docs/api/structures/bluetooth-device.md",
"docs/api/structures/browser-window-options.md",
@@ -178,6 +179,7 @@ auto_filenames = {
"lib/common/define-properties.ts",
"lib/common/deprecate.ts",
"lib/common/ipc-messages.ts",
"lib/common/timers-shim.ts",
"lib/common/web-view-methods.ts",
"lib/common/webpack-globals-provider.ts",
"lib/renderer/api/context-bridge.ts",

View File

@@ -793,8 +793,6 @@ filenames = {
"shell/browser/extensions/electron_kiosk_delegate.h",
"shell/browser/extensions/electron_messaging_delegate.cc",
"shell/browser/extensions/electron_messaging_delegate.h",
"shell/browser/extensions/electron_navigation_ui_data.cc",
"shell/browser/extensions/electron_navigation_ui_data.h",
"shell/browser/extensions/electron_process_manager_delegate.cc",
"shell/browser/extensions/electron_process_manager_delegate.h",
"shell/common/extensions/electron_extensions_api_provider.cc",

View File

@@ -437,6 +437,14 @@ WebContents.prototype.loadURL = function (url, options) {
return p;
};
WebContents.prototype.copyVideoFrameAt = function (x: number, y: number) {
this.mainFrame.copyVideoFrameAt(x, y);
};
WebContents.prototype.saveVideoFrameAs = function (x: number, y: number) {
this.mainFrame.saveVideoFrameAs(x, y);
};
WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electron.HandlerDetails) => Electron.WindowOpenHandlerResponse) {
this._windowOpenHandler = handler;
};
@@ -782,8 +790,7 @@ WebContents.prototype._init = function () {
const originCounts = new Map<string, number>();
const openDialogs = new Set<AbortController>();
this.on('-run-dialog', async (info, callback) => {
const originUrl = new URL(info.frame.url);
const origin = originUrl.protocol === 'file:' ? originUrl.href : originUrl.origin;
const origin = info.frame.origin === 'file://' ? info.frame.url : info.frame.origin;
if ((originCounts.get(origin) ?? 0) < 0) return callback(false, '');
const prefs = this.getLastWebPreferences();

View File

@@ -17,11 +17,6 @@ export type WindowOpenArgs = {
features: string,
}
const frameNamesToWindow = new Map<string, WebContents>();
const registerFrameNameToGuestWindow = (name: string, webContents: WebContents) => frameNamesToWindow.set(name, webContents);
const unregisterFrameName = (name: string) => frameNamesToWindow.delete(name);
const getGuestWebContentsByFrameName = (name: string) => frameNamesToWindow.get(name);
/**
* `openGuestWindow` is called to create and setup event handling for the new
* window.
@@ -47,20 +42,6 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
...overrideBrowserWindowOptions
};
// To spec, subsequent window.open calls with the same frame name (`target` in
// spec parlance) will reuse the previous window.
// https://html.spec.whatwg.org/multipage/window-object.html#apis-for-creating-and-navigating-browsing-contexts-by-name
const existingWebContents = getGuestWebContentsByFrameName(frameName);
if (existingWebContents) {
if (existingWebContents.isDestroyed()) {
// FIXME(t57ser): The webContents is destroyed for some reason, unregister the frame name
unregisterFrameName(frameName);
} else {
existingWebContents.loadURL(url);
return;
}
}
if (createWindow) {
const webContents = createWindow({
webContents: guest,
@@ -72,7 +53,7 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
throw new Error('Invalid webContents. Created window should be connected to webContents passed with options object.');
}
handleWindowLifecycleEvents({ embedder, frameName, guest, outlivesOpener });
handleWindowLifecycleEvents({ embedder, guest, outlivesOpener });
}
return;
@@ -96,7 +77,7 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
});
}
handleWindowLifecycleEvents({ embedder, frameName, guest: window.webContents, outlivesOpener });
handleWindowLifecycleEvents({ embedder, guest: window.webContents, outlivesOpener });
embedder.emit('did-create-window', window, { url, frameName, options: browserWindowOptions, disposition, referrer, postData });
}
@@ -107,10 +88,9 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
* too is the guest destroyed; this is Electron convention and isn't based in
* browser behavior.
*/
const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, outlivesOpener }: {
const handleWindowLifecycleEvents = function ({ embedder, guest, outlivesOpener }: {
embedder: WebContents,
guest: WebContents,
frameName: string,
outlivesOpener: boolean
}) {
const closedByEmbedder = function () {
@@ -128,13 +108,6 @@ const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, outl
embedder.once('current-render-view-deleted' as any, closedByEmbedder);
}
guest.once('destroyed', closedByUser);
if (frameName) {
registerFrameNameToGuestWindow(frameName, guest);
guest.once('destroyed', function () {
unregisterFrameName(frameName);
});
}
};
// Security options that child windows will always inherit from parent windows

View File

@@ -19,8 +19,8 @@ export function invokeInWebContents<T> (sender: Electron.WebContents, command: s
const requestId = ++nextId;
const channel = `${command}_RESPONSE_${requestId}`;
ipcMainInternal.on(channel, function handler (event, error: Error, result: any) {
if (event.type === 'frame' && event.sender !== sender) {
console.error(`Reply to ${command} sent by unexpected WebContents (${event.sender.id})`);
if (event.type !== 'frame' || event.sender !== sender) {
console.error(`Reply to ${command} sent by unexpected sender`);
return;
}
@@ -43,8 +43,8 @@ export function invokeInWebFrameMain<T> (sender: Electron.WebFrameMain, command:
const channel = `${command}_RESPONSE_${requestId}`;
const frameTreeNodeId = sender.frameTreeNodeId;
ipcMainInternal.on(channel, function handler (event, error: Error, result: any) {
if (event.type === 'frame' && event.frameTreeNodeId !== frameTreeNodeId) {
console.error(`Reply to ${command} sent by unexpected WebFrameMain (${event.frameTreeNodeId})`);
if (event.type !== 'frame' || event.frameTreeNodeId !== frameTreeNodeId) {
console.error(`Reply to ${command} sent by unexpected sender`);
return;
}

View File

@@ -227,10 +227,9 @@ function validateHeader (name: any, value: any): void {
}
function parseOptions (optionsIn: ClientRequestConstructorOptions | string): NodeJS.CreateURLLoaderOptions & ExtraURLLoaderOptions {
// eslint-disable-next-line n/no-deprecated-api
const options: any = typeof optionsIn === 'string' ? url.parse(optionsIn) : { ...optionsIn };
const options: any = typeof optionsIn === 'string' ? new URL(optionsIn) : { ...optionsIn };
let urlStr: string = options.url;
let urlStr: string = options.url || options.href;
if (!urlStr) {
const urlObj: url.UrlObject = {};
@@ -260,8 +259,8 @@ function parseOptions (optionsIn: ClientRequestConstructorOptions | string): Nod
// an invalid request.
throw new TypeError('Request path contains unescaped characters');
}
// eslint-disable-next-line n/no-deprecated-api
const pathObj = url.parse(options.path || '/');
const pathObj = new URL(options.path || '/', 'http://localhost');
urlObj.pathname = pathObj.pathname;
urlObj.search = pathObj.search;
urlObj.hash = pathObj.hash;

102
lib/common/timers-shim.ts Normal file
View File

@@ -0,0 +1,102 @@
// Drop-in replacement for timers-browserify@1.4.2.
// Provides the Node.js 'timers' API surface for renderer/web webpack bundles
// without relying on window.postMessage (which the newer timers-browserify 2.x
// polyfill uses and can interfere with Electron IPC).
const immediateIds: Record<number, boolean> = {};
let nextImmediateId = 0;
// --- DOM timer wrappers ------------------------------------------------
// Wrap the global setTimeout/setInterval so we return Timeout objects that
// expose ref/unref/close matching the Node.js API shape.
class Timeout {
_id: ReturnType<typeof globalThis.setTimeout>;
_clearFn: (id: ReturnType<typeof globalThis.setTimeout>) => void;
constructor (id: ReturnType<typeof globalThis.setTimeout>, clearFn: (id: ReturnType<typeof globalThis.setTimeout>) => void) {
this._id = id;
this._clearFn = clearFn;
}
unref () {}
ref () {}
close () {
this._clearFn.call(globalThis, this._id);
}
}
export const setTimeout = function (...args: Parameters<typeof globalThis.setTimeout>): Timeout {
return new Timeout(globalThis.setTimeout(...args), globalThis.clearTimeout);
};
export const setInterval = function (...args: Parameters<typeof globalThis.setInterval>): Timeout {
return new Timeout(globalThis.setInterval(...args), globalThis.clearInterval);
};
export const clearTimeout = function (timeout: Timeout | undefined) {
if (timeout) timeout.close();
};
export const clearInterval = clearTimeout;
// --- Legacy enroll/unenroll (Node < 11 API, preserved for compatibility) ------
interface EnrollableItem {
_idleTimeoutId?: ReturnType<typeof setTimeout>;
_idleTimeout?: number;
_onTimeout?: () => void;
}
export const enroll = function (item: EnrollableItem, msecs: number) {
clearTimeout(item._idleTimeoutId);
item._idleTimeout = msecs;
};
export const unenroll = function (item: EnrollableItem) {
clearTimeout(item._idleTimeoutId);
item._idleTimeout = -1;
};
export const active = function (item: EnrollableItem) {
clearTimeout(item._idleTimeoutId);
const msecs = item._idleTimeout;
if (msecs !== undefined && msecs >= 0) {
item._idleTimeoutId = setTimeout(function onTimeout () {
if (item._onTimeout) item._onTimeout();
}, msecs);
}
};
export const _unrefActive = active;
// --- setImmediate / clearImmediate -------------------------------------
// Prefer the native implementations when available. Fall back to a
// nextTick-based shim that avoids window.postMessage.
const clearImmediateFallback = function (id: number) {
delete immediateIds[id];
};
export const setImmediate = typeof globalThis.setImmediate === 'function'
? globalThis.setImmediate
: function (fn: (...args: unknown[]) => void, ...rest: unknown[]) {
const id = nextImmediateId++;
immediateIds[id] = true;
Promise.resolve().then(function onMicrotask () {
if (immediateIds[id]) {
fn(...rest);
clearImmediateFallback(id);
}
});
return id;
};
export const clearImmediate = typeof globalThis.clearImmediate === 'function'
? globalThis.clearImmediate
: clearImmediateFallback;

View File

@@ -1232,6 +1232,8 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
// has filesystem caching.
overrideAPI(fs, 'copyFile');
overrideAPISync(fs, 'copyFileSync');
overrideAPI(fs, 'cp');
overrideAPISync(fs, 'cpSync');
overrideAPI(fs, 'open');
overrideAPISync(process, 'dlopen', 1);

View File

@@ -23,11 +23,14 @@ export default contextBridge;
export const internalContextBridge = {
contextIsolationEnabled: process.contextIsolated,
tryOverrideGlobalValueFromIsolatedWorld: (keys: string[], value: any) => {
return binding._overrideGlobalValueFromIsolatedWorld(keys, value, true, true);
},
overrideGlobalValueFromIsolatedWorld: (keys: string[], value: any) => {
return binding._overrideGlobalValueFromIsolatedWorld(keys, value, false);
return binding._overrideGlobalValueFromIsolatedWorld(keys, value, false, false);
},
overrideGlobalValueWithDynamicPropsFromIsolatedWorld: (keys: string[], value: any) => {
return binding._overrideGlobalValueFromIsolatedWorld(keys, value, true);
return binding._overrideGlobalValueFromIsolatedWorld(keys, value, true, false);
},
overrideGlobalPropertyFromIsolatedWorld: (keys: string[], getter: Function, setter?: Function) => {
return binding._overrideGlobalPropertyFromIsolatedWorld(keys, getter, setter || null);

View File

@@ -124,7 +124,9 @@ if (nodeIntegration) {
delete (global as any).setImmediate;
delete (global as any).clearImmediate;
delete (global as any).global;
// eslint-disable-next-line n/no-deprecated-api
delete (global as any).root;
// eslint-disable-next-line n/no-deprecated-api
delete (global as any).GLOBAL;
});
}

View File

@@ -11,14 +11,12 @@ const { contextIsolationEnabled } = internalContextBridge;
* 1) Use menu API to show context menu.
*/
window.onload = function () {
if (window.InspectorFrontendHost) {
if (contextIsolationEnabled) {
internalContextBridge.overrideGlobalValueFromIsolatedWorld([
'InspectorFrontendHost', 'showContextMenuAtPoint'
], createMenu);
} else {
window.InspectorFrontendHost.showContextMenuAtPoint = createMenu;
}
if (contextIsolationEnabled) {
internalContextBridge.tryOverrideGlobalValueFromIsolatedWorld([
'InspectorFrontendHost', 'showContextMenuAtPoint'
], createMenu);
} else {
window.InspectorFrontendHost!.showContextMenuAtPoint = createMenu;
}
};

View File

@@ -11,18 +11,17 @@ const path = require('path');
const { version } = require('./package');
if (process.env.ELECTRON_SKIP_BINARY_DOWNLOAD) {
process.exit(0);
}
const platformPath = getPlatformPath();
if (isInstalled()) {
process.exit(0);
}
const platform = process.env.npm_config_platform || process.platform;
let arch = process.env.npm_config_arch || process.arch;
const platform = process.env.ELECTRON_INSTALL_PLATFORM || process.env.npm_config_platform || process.platform;
let arch =
process.env.ELECTRON_INSTALL_ARCH ||
process.env.npm_config_arch ||
process.arch;
if (platform === 'darwin' && process.platform === 'darwin' && arch === 'x64' &&
process.env.npm_config_arch === undefined) {

View File

@@ -5,7 +5,7 @@
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {
"@azure/storage-blob": "^12.28.0",
"@datadog/datadog-ci": "^4.1.2",
"@datadog/datadog-ci": "^5.9.1",
"@electron/asar": "^4.0.1",
"@electron/docs-parser": "^2.0.0",
"@electron/fiddle-core": "^1.3.4",
@@ -15,6 +15,7 @@
"@hurdlegroup/robotjs": "^0.12.3",
"@octokit/rest": "^20.1.2",
"@primer/octicons": "^10.0.0",
"@sentry/cli": "1.72.0",
"@types/minimist": "^1.2.5",
"@types/node": "^24.9.0",
"@types/semver": "^7.5.8",
@@ -31,11 +32,11 @@
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-markdown": "^5.1.0",
"eslint-plugin-mocha": "^10.5.0",
"eslint-plugin-n": "^16.6.2",
"eslint-plugin-n": "^17.24.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.6.0",
"events": "^3.2.0",
"folder-hash": "^4.1.1",
"folder-hash": "^4.1.2",
"got": "^11.8.5",
"husky": "^9.1.7",
"lint-staged": "^16.1.0",
@@ -45,13 +46,10 @@
"null-loader": "^4.0.1",
"pre-flight": "^2.0.0",
"process": "^0.11.10",
"remark-cli": "^12.0.1",
"remark-preset-lint-markdown-style-guide": "^6.0.1",
"semver": "^7.6.3",
"stream-json": "^1.9.1",
"tap-xunit": "^2.4.1",
"temp": "^0.9.4",
"timers-browserify": "1.4.2",
"ts-loader": "^8.0.2",
"ts-node": "6.2.0",
"typescript": "^5.8.3",
@@ -73,7 +71,7 @@
"lint:objc": "node ./script/lint.js --objc",
"lint:py": "node ./script/lint.js --py",
"lint:gn": "node ./script/lint.js --gn",
"lint:docs": "remark docs -qf && npm run lint:js-in-markdown && npm run create-typescript-definitions && npm run lint:ts-check-js-in-markdown && npm run lint:docs-fiddles && npm run lint:docs-relative-links && npm run lint:markdown && npm run lint:api-history",
"lint:docs": "npm run lint:js-in-markdown && npm run create-typescript-definitions && npm run lint:ts-check-js-in-markdown && npm run lint:docs-fiddles && npm run lint:docs-relative-links && npm run lint:markdown && npm run lint:api-history",
"lint:docs-fiddles": "standard \"docs/fiddles/**/*.js\"",
"lint:docs-relative-links": "lint-roller-markdown-links --resource-root . --root docs \"**/*.md\"",
"lint:markdown": "node ./script/lint.js --md",
@@ -156,6 +154,9 @@
"spec/fixtures/native-addon/*"
],
"dependenciesMeta": {
"@sentry/cli": {
"built": true
},
"abstract-socket": {
"built": true
}

View File

@@ -52,7 +52,6 @@ adjust_accessibility_ui_for_electron.patch
worker_feat_add_hook_to_notify_script_ready.patch
chore_provide_iswebcontentscreationoverridden_with_full_params.patch
fix_properly_honor_printing_page_ranges.patch
export_gin_v8platform_pageallocator_for_usage_outside_of_the_gin.patch
fix_export_zlib_symbols.patch
web_contents.patch
webview_fullscreen.patch
@@ -104,7 +103,6 @@ chore_remove_check_is_test_on_script_injection_tracker.patch
fix_restore_original_resize_performance_on_macos.patch
feat_allow_code_cache_in_custom_schemes.patch
build_run_reclient_cfg_generator_after_chrome.patch
fix_getcursorscreenpoint_wrongly_returns_0_0.patch
fix_add_support_for_skipping_first_2_no-op_refreshes_in_thumb_cap.patch
refactor_expose_file_system_access_blocklist.patch
feat_add_support_for_missing_dialog_features_to_shell_dialogs.patch
@@ -121,14 +119,13 @@ build_disable_thin_lto_mac.patch
feat_corner_smoothing_css_rule_and_blink_painting.patch
build_add_public_config_simdutf_config.patch
fix_multiple_scopedpumpmessagesinprivatemodes_instances.patch
revert_code_health_clean_up_stale_macwebcontentsocclusion.patch
fix_handle_embedder_windows_shown_after_webcontentsviewcocoa_attach.patch
feat_add_signals_when_embedder_cleanup_callbacks_run_for.patch
feat_separate_content_settings_callback_for_sync_and_async_clipboard.patch
fix_win32_synchronous_spellcheck.patch
chore_grandfather_in_electron_views_and_delegates.patch
refactor_patch_electron_permissiontypes_into_blink.patch
revert_views_remove_desktopwindowtreehostwin_window_enlargement.patch
build_partial_revert_mac_fullscreen_top_chrome_mouse_events.patch
fix_add_macos_memory_query_fallback_to_avoid_crash.patch
fix_resolve_dynamic_background_material_update_issue_on_windows_11.patch
feat_add_support_for_embedder_snapshot_validation.patch
@@ -147,3 +144,9 @@ refactor_allow_customizing_config_in_freedesktopsecretkeyprovider.patch
fix_wayland_test_crash_on_teardown.patch
fix_set_correct_app_id_on_linux.patch
fix_pass_trigger_for_global_shortcuts_on_wayland.patch
feat_plumb_node_integration_in_worker_through_workersettings.patch
fix_restore_sdk_inputs_cross-toolchain_deps_for_macos.patch
fix_use_fresh_lazynow_for_onendworkitemimpl_after_didruntask.patch
fix_pulseaudio_stream_and_icon_names.patch
fix_fire_menu_popup_start_for_dynamically_created_aria_menus.patch
feat_allow_enabling_extensions_on_custom_protocols.patch

View File

@@ -10,10 +10,10 @@ Allows Electron to restore WER when ELECTRON_DEFAULT_ERROR_MODE is set.
This should be upstreamed.
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index 7265019647734154f64108efd7e6376b7a9fc1ba..398aaff3af5bff791f114e4023d0e07be86dd79a 100644
index 26619daf25f3cc455d2dba7b5f16c9449e6103c1..387fca1b54b818a5af435e96bf8f435e2963fe39 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -272,6 +272,10 @@ int GpuMain(MainFunctionParams parameters) {
@@ -277,6 +277,10 @@ int GpuMain(MainFunctionParams parameters) {
// to the GpuProcessHost once the GpuServiceImpl has started.
viz::GpuLogMessageManager::GetInstance()->InstallPreInitializeLogHandler();
@@ -24,7 +24,7 @@ index 7265019647734154f64108efd7e6376b7a9fc1ba..398aaff3af5bff791f114e4023d0e07b
// We are experiencing what appear to be memory-stomp issues in the GPU
// process. These issues seem to be impacting the task executor and listeners
// registered to it. Create the task executor on the heap to guard against
@@ -380,7 +384,6 @@ int GpuMain(MainFunctionParams parameters) {
@@ -385,7 +389,6 @@ int GpuMain(MainFunctionParams parameters) {
#endif
const bool dead_on_arrival = !init_success;

View File

@@ -10,7 +10,7 @@ DidCreateScriptContext is called, not all JS APIs are available in the
context, which can cause some preload scripts to trip.
diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h
index 8077ed85e45e56d6cccb691223216c1f6a94b5ee..dd4cee346f16df703d414bf206bbe6c9f4b1f796 100644
index 3f8cf4edc7448e6b584adae8fcbb872d27377126..1d03dc809d4c18f24314d94811e0bf527aa7b5b4 100644
--- a/content/public/renderer/render_frame_observer.h
+++ b/content/public/renderer/render_frame_observer.h
@@ -141,6 +141,8 @@ class CONTENT_EXPORT RenderFrameObserver {
@@ -23,10 +23,10 @@ index 8077ed85e45e56d6cccb691223216c1f6a94b5ee..dd4cee346f16df703d414bf206bbe6c9
int32_t world_id) {}
virtual void DidClearWindowObject() {}
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 415b2bf329db639e4d3732c290b055aa6b5825de..1b841c1df51abb0e0ec1b86a237dd73283083a37 100644
index 0e64b0a0ac8387ab15b201a9fc0f0fd36cd5ab29..f28214d369138eb854a556165f0a946c07cfdb9c 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4762,6 +4762,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
@@ -4731,6 +4731,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
observer.DidCreateScriptContext(context, world_id);
}
@@ -40,10 +40,10 @@ index 415b2bf329db639e4d3732c290b055aa6b5825de..1b841c1df51abb0e0ec1b86a237dd732
int world_id) {
for (auto& observer : observers_)
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index c803bf1d93bb9aabf0f9098c4d58aa7528d18d79..ced097d57cec93b3d3062a6d7d9f7d037a355e6c 100644
index 1733f28e69b331b33f36084391f1d3ddb47c8e14..2ce05bce0a02338aba018c18f0a808a4eb392ff4 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -606,6 +606,8 @@ class CONTENT_EXPORT RenderFrameImpl
@@ -607,6 +607,8 @@ class CONTENT_EXPORT RenderFrameImpl
void DidObserveLayoutShift(double score, bool after_input_or_scroll) override;
void DidCreateScriptContext(v8::Local<v8::Context> context,
int world_id) override;
@@ -53,10 +53,10 @@ index c803bf1d93bb9aabf0f9098c4d58aa7528d18d79..ced097d57cec93b3d3062a6d7d9f7d03
int world_id) override;
void DidChangeScrollOffset() override;
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
index 675791f9db1320ee9b3c915f4595eef2183802d5..1ce4e9a1e7b5d5cfbb6201c000eada80b3b3d174 100644
index 0f218d3f96f0c3a3a5773937e50ba9e8d7df0498..27b21f02d2dbfd60cb64f09be393b0e50928756f 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -673,6 +673,9 @@ class BLINK_EXPORT WebLocalFrameClient {
@@ -675,6 +675,9 @@ class BLINK_EXPORT WebLocalFrameClient {
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) {}
@@ -67,7 +67,7 @@ index 675791f9db1320ee9b3c915f4595eef2183802d5..1ce4e9a1e7b5d5cfbb6201c000eada80
virtual void WillReleaseScriptContext(v8::Local<v8::Context>,
int32_t world_id) {}
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
index 851e792c6c6f26b6074ffe8b0ba39a5813fabacc..8bd06f4c155cc0ed8afaf89347f9fc9728bb1e41 100644
index d293c49e6774de889fa9959234c82b41a4b1efe1..0787bc8a602c60e5b42933813baa6b9d923c9823 100644
--- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
+++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
@@ -216,6 +216,7 @@ void LocalWindowProxy::Initialize() {
@@ -79,10 +79,10 @@ index 851e792c6c6f26b6074ffe8b0ba39a5813fabacc..8bd06f4c155cc0ed8afaf89347f9fc97
if (World().IsMainWorld()) {
probe::DidCreateMainWorldContext(GetFrame());
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
index 47dd48bd495f89f2dd3528053d9b6446df264c7c..ee43008b2bec7ea013cbbe7a782aa0a38e1acd02 100644
index a68832975b5d359f7eddaf2326bd47ff1e7e18df..ae565a4d3fdc2d02e2c7a27312d8296bbdf61e0b 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -311,6 +311,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
@@ -310,6 +310,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) = 0;
@@ -92,7 +92,7 @@ index 47dd48bd495f89f2dd3528053d9b6446df264c7c..ee43008b2bec7ea013cbbe7a782aa0a3
int32_t world_id) = 0;
virtual bool AllowScriptExtensions() = 0;
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
index 294c9ec4bfb788235be8047eb3174d7dcc97bdfb..6ab8ec1924a76f51d6e390d9457c596f9b0d8453 100644
index 5e5e43e204f006989a859a6077dcb56c81a08e60..aaf03855e53d5529bb51d70cd9b4355d68fed48c 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
@@ -301,6 +301,13 @@ void LocalFrameClientImpl::DidCreateScriptContext(
@@ -110,10 +110,10 @@ index 294c9ec4bfb788235be8047eb3174d7dcc97bdfb..6ab8ec1924a76f51d6e390d9457c596f
v8::Local<v8::Context> context,
int32_t world_id) {
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
index e7b822d45d608a78009576c2a299201014dd93ec..54be144d5b24b369e12d551e6c15d2d85fa8b8c3 100644
index b00211cf215fb820b3fe49139b8ef95be6a10d21..cc593168947e469b599794260692e1deb9b5f1a5 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
@@ -80,6 +80,8 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
@@ -78,6 +78,8 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) override;
@@ -123,7 +123,7 @@ index e7b822d45d608a78009576c2a299201014dd93ec..54be144d5b24b369e12d551e6c15d2d8
int32_t world_id) override;
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
index ea958f895ca355680a44ed1257c2c9918be361f9..6e8016c02930af2751d6e9b6ed00b8026f6c3b20 100644
index bcdcc5f04edaf06d89375b05eb2d5f6bfa3d3237..5a0f42b4b7e5eb67d476c948caa201ee6fc7b3ca 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -425,6 +425,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {

View File

@@ -7,10 +7,10 @@ Ensure that licenses for the dependencies introduced by Electron
are included in `LICENSES.chromium.html`
diff --git a/tools/licenses/licenses.py b/tools/licenses/licenses.py
index f87d1ffc90ba5bd6da87a90c6dd904c01ae42e23..9987b33124cfec689502f991b92c0b05d0433106 100755
index 4272e2ab96c64b1970e1cf035a3385893b1f2f0c..387fa19ca4ea8aace08bfef67d4b7c0870ad1d23 100755
--- a/tools/licenses/licenses.py
+++ b/tools/licenses/licenses.py
@@ -355,6 +355,31 @@ SPECIAL_CASES = {
@@ -354,6 +354,31 @@ SPECIAL_CASES = {
"License": "Apache 2.0",
"License File": ["//third_party/sample3/the_license"],
},

View File

@@ -8,10 +8,10 @@ was removed as part of the Raw Clipboard API scrubbing.
https://bugs.chromium.org/p/chromium/issues/detail?id=1217643
diff --git a/ui/base/clipboard/scoped_clipboard_writer.cc b/ui/base/clipboard/scoped_clipboard_writer.cc
index bafc8421e14071a926a48bee1958a44d266a9a0b..4463080e08f7a0635ef240794deae1ea8d90e148 100644
index 12695bb8f3d2cc3f498e5c6e37e4729d9586962f..6bd7b6f2908d3c8316191e3106e50b2137068a0f 100644
--- a/ui/base/clipboard/scoped_clipboard_writer.cc
+++ b/ui/base/clipboard/scoped_clipboard_writer.cc
@@ -244,6 +244,16 @@ void ScopedClipboardWriter::WriteData(std::u16string_view format,
@@ -239,6 +239,16 @@ void ScopedClipboardWriter::WriteData(std::u16string_view format,
}
}
@@ -29,7 +29,7 @@ index bafc8421e14071a926a48bee1958a44d266a9a0b..4463080e08f7a0635ef240794deae1ea
objects_.clear();
raw_objects_.clear();
diff --git a/ui/base/clipboard/scoped_clipboard_writer.h b/ui/base/clipboard/scoped_clipboard_writer.h
index 8c2be540757856a3e704764fe56003205b24812f..e31fbc01f68c0e92284a72298cac878d7247e7fb 100644
index 7d7d015f9725ef39b7d5e82b83ac5195e2cfe309..83565b6d73cbe30e3c24913468862173cfd3a83e 100644
--- a/ui/base/clipboard/scoped_clipboard_writer.h
+++ b/ui/base/clipboard/scoped_clipboard_writer.h
@@ -91,6 +91,10 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter {

View File

@@ -10,7 +10,7 @@ usage of BrowserList and Browser as we subclass related methods and use our
WindowList.
diff --git a/chrome/browser/ui/webui/accessibility/accessibility_ui.cc b/chrome/browser/ui/webui/accessibility/accessibility_ui.cc
index 9b22efa07e43b60a8bd8bb6288792846709fae87..cf60a541720ffbcdaa5163d727a7761dcb30f131 100644
index 1322a7c5f9b3baca837488de2e5323ee5c49800c..cb1895f2be25d210f7508433a352bc1e93369f4a 100644
--- a/chrome/browser/ui/webui/accessibility/accessibility_ui.cc
+++ b/chrome/browser/ui/webui/accessibility/accessibility_ui.cc
@@ -48,6 +48,7 @@
@@ -64,7 +64,7 @@ index 9b22efa07e43b60a8bd8bb6288792846709fae87..cf60a541720ffbcdaa5163d727a7761d
data.Set(kBrowsersField, std::move(browser_list));
#if BUILDFLAG(IS_WIN)
@@ -847,7 +848,8 @@ void AccessibilityUIMessageHandler::SetGlobalString(
@@ -870,7 +871,8 @@ void AccessibilityUIMessageHandler::HandleSetGlobalString(
const std::string value = CheckJSValue(data.FindString(kValueField));
if (string_name == kApiTypeField) {
@@ -74,7 +74,7 @@ index 9b22efa07e43b60a8bd8bb6288792846709fae87..cf60a541720ffbcdaa5163d727a7761d
pref->SetString(prefs::kShownAccessibilityApiType, value);
}
}
@@ -901,7 +903,8 @@ void AccessibilityUIMessageHandler::RequestWebContentsTree(
@@ -924,7 +926,8 @@ void AccessibilityUIMessageHandler::HandleRequestWebContentsTree(
AXPropertyFilter::ALLOW_EMPTY);
AddPropertyFilters(property_filters, deny, AXPropertyFilter::DENY);
@@ -84,7 +84,7 @@ index 9b22efa07e43b60a8bd8bb6288792846709fae87..cf60a541720ffbcdaa5163d727a7761d
ui::AXApiType::Type api_type =
ui::AXApiType::From(pref->GetString(prefs::kShownAccessibilityApiType));
std::string accessibility_contents =
@@ -921,7 +924,7 @@ void AccessibilityUIMessageHandler::RequestNativeUITree(
@@ -944,7 +947,7 @@ void AccessibilityUIMessageHandler::HandleRequestNativeUITree(
AllowJavascript();
@@ -93,7 +93,7 @@ index 9b22efa07e43b60a8bd8bb6288792846709fae87..cf60a541720ffbcdaa5163d727a7761d
std::vector<AXPropertyFilter> property_filters;
AddPropertyFilters(property_filters, allow, AXPropertyFilter::ALLOW);
AddPropertyFilters(property_filters, allow_empty,
@@ -948,7 +951,7 @@ void AccessibilityUIMessageHandler::RequestNativeUITree(
@@ -971,7 +974,7 @@ void AccessibilityUIMessageHandler::HandleRequestNativeUITree(
if (found) {
return;
}
@@ -102,7 +102,7 @@ index 9b22efa07e43b60a8bd8bb6288792846709fae87..cf60a541720ffbcdaa5163d727a7761d
// No browser with the specified |session_id| was found.
base::DictValue result;
result.Set(kSessionIdField, session_id);
@@ -991,11 +994,13 @@ void AccessibilityUIMessageHandler::StopRecording(
@@ -1014,11 +1017,13 @@ void AccessibilityUIMessageHandler::StopRecording(
}
ui::AXApiType::Type AccessibilityUIMessageHandler::GetRecordingApiType() {
@@ -119,7 +119,7 @@ index 9b22efa07e43b60a8bd8bb6288792846709fae87..cf60a541720ffbcdaa5163d727a7761d
// Check to see if it is in the supported types list.
if (std::find(supported_types.begin(), supported_types.end(), api_type) ==
supported_types.end()) {
@@ -1065,10 +1070,13 @@ void AccessibilityUIMessageHandler::RequestAccessibilityEvents(
@@ -1088,10 +1093,13 @@ void AccessibilityUIMessageHandler::HandleRequestAccessibilityEvents(
// static
void AccessibilityUIMessageHandler::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
@@ -134,7 +134,7 @@ index 9b22efa07e43b60a8bd8bb6288792846709fae87..cf60a541720ffbcdaa5163d727a7761d
void AccessibilityUIMessageHandler::OnVisibilityChanged(
diff --git a/chrome/browser/ui/webui/accessibility/accessibility_ui.h b/chrome/browser/ui/webui/accessibility/accessibility_ui.h
index 67f7e34271994ff66da2a3c3b90c2f02797c2d14..8f786bc00dc4a7cc775ca3ff3fca4da680272682 100644
index 184a10239d7072572a043f2b4e29bcdb5344f3ec..77d3ca336eaa28b7c476861c8d4a43e45804ac7a 100644
--- a/chrome/browser/ui/webui/accessibility/accessibility_ui.h
+++ b/chrome/browser/ui/webui/accessibility/accessibility_ui.h
@@ -28,6 +28,8 @@ namespace content {
@@ -146,12 +146,12 @@ index 67f7e34271994ff66da2a3c3b90c2f02797c2d14..8f786bc00dc4a7cc775ca3ff3fca4da6
namespace user_prefs {
class PrefRegistrySyncable;
} // namespace user_prefs
@@ -79,6 +81,8 @@ class AccessibilityUIMessageHandler : public content::WebUIMessageHandler,
@@ -81,6 +83,8 @@ class AccessibilityUIMessageHandler : public content::WebUIMessageHandler,
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
private:
+ friend class ElectronAccessibilityUIMessageHandler;
+
void ToggleAccessibilityForWebContents(const base::ListValue& args);
void SetGlobalFlag(const base::ListValue& args);
void SetGlobalString(const base::ListValue& args);
void HandleInitialize(const base::ListValue& args);
void HandleToggleAccessibilityForWebContents(const base::ListValue& args);
void HandleSetGlobalFlag(const base::ListValue& args);

View File

@@ -6,7 +6,7 @@ Subject: allow disabling blink scheduler throttling per RenderView
This allows us to disable throttling for hidden windows.
diff --git a/content/browser/renderer_host/navigation_controller_impl_unittest.cc b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
index 497c23b182d9288950ff54b4c70bdb0fbe80f91b..7e2839bf619ce3c0b88b33b1df2032672292fe06 100644
index 29d5b174e122cbd140554687548106ead8f8e8d9..da74da96c3fe35a0f3838f04bca08846f7b41abe 100644
--- a/content/browser/renderer_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
@@ -168,6 +168,12 @@ class MockPageBroadcast : public blink::mojom::PageBroadcast {
@@ -23,10 +23,10 @@ index 497c23b182d9288950ff54b4c70bdb0fbe80f91b..7e2839bf619ce3c0b88b33b1df203267
return receiver_.BindNewEndpointAndPassDedicatedRemote();
}
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index b8193571d0a3b7609e89b284f57a9cbf36d593e0..0d42b04031006b844d5a2a2b73241d2b7e2fb93d 100644
index 6b881f610932eacd5412accd61431e6a59124e71..999022342a06592cc1bc7838b49afddaed1f9995 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -759,6 +759,11 @@ void RenderViewHostImpl::SetBackgroundOpaque(bool opaque) {
@@ -761,6 +761,11 @@ void RenderViewHostImpl::SetBackgroundOpaque(bool opaque) {
GetWidget()->GetAssociatedFrameWidget()->SetBackgroundOpaque(opaque);
}
@@ -39,7 +39,7 @@ index b8193571d0a3b7609e89b284f57a9cbf36d593e0..0d42b04031006b844d5a2a2b73241d2b
return is_active();
}
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index 2dddaff6c16c55288b6ea72cb8df0f8737971d71..dce9dae250ff2ac070752830df41cc45ed72823e 100644
index 89fed16c112d55c13a9f23695e2898d630f7d815..b7f486337f46daac015644525c9870f54e03bb46 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -134,6 +134,7 @@ class CONTENT_EXPORT RenderViewHostImpl
@@ -51,10 +51,10 @@ index 2dddaff6c16c55288b6ea72cb8df0f8737971d71..dce9dae250ff2ac070752830df41cc45
void SendRendererPreferencesToRenderer(
const blink::RendererPreferences& preferences);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 722eff1cf2e51fe628b873c67694764c99dae496..b16c96b5682846d897c2f0f4dd3881d386928b68 100644
index 79bd8d43a71731e5076196877448462656a04d48..b5d7f50817f503956f19fcea687b5b0751268b44 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -646,8 +646,8 @@ void RenderWidgetHostViewAura::ShowImpl(PageVisibilityState page_visibility) {
@@ -655,8 +655,8 @@ void RenderWidgetHostViewAura::ShowImpl(PageVisibilityState page_visibility) {
// OnShowWithPageVisibility will not call NotifyHostAndDelegateOnWasShown,
// which updates `visibility_`, unless the host is hidden. Make sure no update
// is needed.
@@ -116,10 +116,10 @@ index 932658273154ef2e022358e493a8e7c00c86e732..57bbfb5cde62c9496c351c861880a189
// Visibility -----------------------------------------------------------
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index f5bdcb8176a94705a3710ba5dbc536a96b35fed9..657a0e059f954a72d4f8654d1a8938ff255ec193 100644
index 611ecffa47703196dc40550b1e920afc4c1be716..be26284387dcfa4e72592862f313a2c7e9a81d1b 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -2502,6 +2502,10 @@ void WebViewImpl::SetPageLifecycleStateInternal(
@@ -2471,6 +2471,10 @@ void WebViewImpl::SetPageLifecycleStateInternal(
TRACE_EVENT2("navigation", "WebViewImpl::SetPageLifecycleStateInternal",
"old_state", old_state, "new_state", new_state);
@@ -130,7 +130,7 @@ index f5bdcb8176a94705a3710ba5dbc536a96b35fed9..657a0e059f954a72d4f8654d1a8938ff
bool storing_in_bfcache = new_state->is_in_back_forward_cache &&
!old_state->is_in_back_forward_cache;
bool restoring_from_bfcache = !new_state->is_in_back_forward_cache &&
@@ -4182,10 +4186,23 @@ PageScheduler* WebViewImpl::Scheduler() const {
@@ -4163,10 +4167,23 @@ PageScheduler* WebViewImpl::Scheduler() const {
return GetPage()->GetPageScheduler();
}
@@ -155,7 +155,7 @@ index f5bdcb8176a94705a3710ba5dbc536a96b35fed9..657a0e059f954a72d4f8654d1a8938ff
// Do not throttle if the page should be painting.
bool is_visible =
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h
index ff153875857fe718676389ee4f0096ca41407cf3..8b354c18c9d74432f85847d58e7aafc389c6b03c 100644
index 8d5c7349c360726778e37976fc54d660d7424f1f..96ee25c8ae4b50ab265bd698517efe15e2f1f44d 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.h
+++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -446,6 +446,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
@@ -166,7 +166,7 @@ index ff153875857fe718676389ee4f0096ca41407cf3..8b354c18c9d74432f85847d58e7aafc3
void SetVisibilityState(mojom::blink::PageVisibilityState visibility_state,
bool is_initial_state) override;
mojom::blink::PageVisibilityState GetVisibilityState() override;
@@ -955,6 +956,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
@@ -957,6 +958,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
// If true, we send IPC messages when |preferred_size_| changes.
bool send_preferred_size_changes_ = false;

View File

@@ -8,10 +8,10 @@ WebPreferences of in-process child windows, rather than relying on
process-level command line switches, as before.
diff --git a/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc b/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
index 23672617af41f1d88b551da7b4ad0a19e39a2092..df032abeeca76c0cd914cbefcb6ba1a9509e7f95 100644
index c6552b25ffba3bf8d806d8bf2410a89533c9bef1..9920c3146c6cf700414a679e80087c469395eee9 100644
--- a/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
+++ b/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
@@ -149,6 +149,19 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
@@ -150,6 +150,19 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
out->v8_cache_options = data.v8_cache_options();
out->record_whole_document = data.record_whole_document();
out->stylus_handwriting_enabled = data.stylus_handwriting_enabled();
@@ -32,18 +32,18 @@ index 23672617af41f1d88b551da7b4ad0a19e39a2092..df032abeeca76c0cd914cbefcb6ba1a9
out->accelerated_video_decode_enabled =
data.accelerated_video_decode_enabled();
diff --git a/third_party/blink/public/common/web_preferences/web_preferences.h b/third_party/blink/public/common/web_preferences/web_preferences.h
index c13ae7f9f49afc0f5355920453df0cebcd55bf3d..1e96abbeac5d466c1831e6687796a031c4cfa596 100644
index 1188e60da33c292febf45be4cd6055671c21b4aa..43a1e777536ce2079d81deb5c7f440a1ba9b43d9 100644
--- a/third_party/blink/public/common/web_preferences/web_preferences.h
+++ b/third_party/blink/public/common/web_preferences/web_preferences.h
@@ -9,6 +9,7 @@
#include <string>
@@ -10,6 +10,7 @@
#include <vector>
#include "base/time/time.h"
+#include "base/files/file_path.h"
#include "build/build_config.h"
#include "net/nqe/effective_connection_type.h"
#include "third_party/blink/public/common/common_export.h"
@@ -464,6 +465,19 @@ struct BLINK_COMMON_EXPORT WebPreferences {
@@ -481,6 +482,19 @@ struct BLINK_COMMON_EXPORT WebPreferences {
bool should_screenshot_on_mainframe_same_doc_navigation = true;
#endif // BUILDFLAG(IS_ANDROID)
@@ -64,7 +64,7 @@ index c13ae7f9f49afc0f5355920453df0cebcd55bf3d..1e96abbeac5d466c1831e6687796a031
// chrome, except for the cases where it would require lots of extra work for
// the embedder to use the same default value.
diff --git a/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h b/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
index 9bb06fb430cbf31b6fc1343229191565a62421a8..a69327c42d386390bafb29d89063dd91315de834 100644
index ac91e8bad952dad5fc6ff673ffd19b0edd30bdb2..0f1715711056c83bb53e03dd8b675cb40a0c42cc 100644
--- a/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
+++ b/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
@@ -8,6 +8,7 @@
@@ -129,7 +129,7 @@ index 9bb06fb430cbf31b6fc1343229191565a62421a8..a69327c42d386390bafb29d89063dd91
return r.cookie_enabled;
}
diff --git a/third_party/blink/public/mojom/webpreferences/web_preferences.mojom b/third_party/blink/public/mojom/webpreferences/web_preferences.mojom
index ec6f13d3924cf861c505ed6d3abde0371fd65475..4830affa94db76d7cf87482671b9e20a68bcc449 100644
index 0ed21e64a0b43580feb99166953babfb633d5af6..f06db564760e8f7e785bb3d6d4b80270a8783a23 100644
--- a/third_party/blink/public/mojom/webpreferences/web_preferences.mojom
+++ b/third_party/blink/public/mojom/webpreferences/web_preferences.mojom
@@ -4,6 +4,7 @@
@@ -138,9 +138,9 @@ index ec6f13d3924cf861c505ed6d3abde0371fd65475..4830affa94db76d7cf87482671b9e20a
+import "mojo/public/mojom/base/file_path.mojom";
import "mojo/public/mojom/base/string16.mojom";
import "mojo/public/mojom/base/time.mojom";
import "skia/public/mojom/skcolor.mojom";
import "third_party/blink/public/mojom/css/preferred_color_scheme.mojom";
@@ -221,6 +222,19 @@ struct WebPreferences {
@@ -222,6 +223,19 @@ struct WebPreferences {
// If true, stylus handwriting recognition to text input will be available in
// editable input fields which are non-password type.
bool stylus_handwriting_enabled;

View File

@@ -49,10 +49,10 @@ index 901b727ed898cdd840df5ff7e2380fbee5d7fde2..1caacaeed9ddf1162cfa393fe4a7c86a
// its owning reference back to our owning LocalFrame.
client_->Detached(type);
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index 841f86703907d2377345e14d4b5463545fe3709c..e3eb80fcc477d65cdd314328b8f85704d9aa1a66 100644
index 802c876dd85d8100fc3d6e634ad4e390fd48747f..abe5b3c6e5eadf30f3e00013fceddaa0ead36cb1 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -778,10 +778,6 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
@@ -758,10 +758,6 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
}
DCHECK(!view_ || !view_->IsAttached());
@@ -63,7 +63,7 @@ index 841f86703907d2377345e14d4b5463545fe3709c..e3eb80fcc477d65cdd314328b8f85704
if (!Client())
return false;
@@ -838,6 +834,11 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
@@ -817,6 +813,11 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
DCHECK(!view_->IsAttached());
Client()->WillBeDetached();

View File

@@ -6,7 +6,7 @@ Subject: boringssl BUILD.gn
Build BoringSSL with some extra functions that nodejs needs.
diff --git a/third_party/boringssl/BUILD.gn b/third_party/boringssl/BUILD.gn
index 31174ca1c75252b226af14548324d50744ac8c35..8469a37a4e50c76751160ab6ef484662c3626296 100644
index 708bb2066269b57ff54649638938a1719d657b6a..7485078ed7a4cfdc8bfecf2d3a4a009e10ca4893 100644
--- a/third_party/boringssl/BUILD.gn
+++ b/third_party/boringssl/BUILD.gn
@@ -48,6 +48,21 @@ all_sources = bcm_internal_headers + bcm_sources + crypto_internal_headers +

Some files were not shown because too many files have changed in this diff Show More