fix: dispatch toast action and reply events from WinRT activation path (#51286)
* fix: dispatch toast action and reply events from WinRT activation path
ToastEventHandler::Invoke previously returned S_OK without dispatching
whenever the activation arguments looked structured (type=action,
type=reply, or contained &tag=), on the assumption that the COM
INotificationActivationCallback::Activate path would deliver the event
instead. That assumption only holds when Windows actually invokes the
COM activator — which it does for MSIX-packaged apps launched cold, and
for unpackaged apps with a properly-registered CLSID when the app is
not already running. For non-MSIX apps with activationType="foreground"
while the app is running (the common case), Windows raises only the
in-process WinRT Activated event, so action and reply were silently
dropped.
Dispatch structured activations through the same HandleToastActivation
the COM path uses. User input (reply text, selection values) is pulled
from IToastActivatedEventArgs2::UserInput, which carries the data the
COM callback would otherwise have received via
NOTIFICATION_USER_INPUT_DATA.
Also drop the &tag= term from the structured-args check. Plain clicks
in Electron-generated XML don't carry tag=, and a custom toast_xml that
puts tag= on a click argument should now dispatch as a click rather
than being silently dropped.
* fix: release HSTRING out-params from toast activation
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
fix: use no-op header client for Fetch-intercepted requests (#50744)
* fix: use the non-pass-through path for Fetch-intercepted requests
* Revert "fix: use the non-pass-through path for Fetch-intercepted requests"
This reverts commit 395fb8bb8c.
* fix: use no-op header client for Fetch-intercepted requests
* fix: bring back `DCHECK` that was prematurely removed
* style: reformat code
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Noah Gregory <noahmgregory@gmail.com>
* fix: prevent crash when calling contentTracing APIs before app is ready
Added Browser::Get()->is_ready() guards to all contentTracing API functions (startRecording, stopRecording, getCategories, getTraceBufferUsage) so they reject their returned Promises with a clear error message instead of crashing when called before app.whenReady().
Added a crash-case fixture test that validates all four APIs reject properly before readiness and work normally after.
Co-authored-by: om-ghante <mr.omghante1@gmail.com>
* chore: fix linter error in `spec/fixtures/crash-cases/content-tracing-before-ready/` (#51356)
chore: fix linter error in spec/fixtures/crash-cases/content-tracing-before-ready/
introduced earlier today in 6f2e5cd4
* chore: make linter happy
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: om-ghante <mr.omghante1@gmail.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
fix: crash in AutofillPopup teardown (#51302)
Fix a crash in AutofillPopupView::Show() when the popup
tried to show itself after the parent's native view had
already gone away during teardown.
2026-04-23T20:44:32.7015810Z Received signal 11 SEGV_ACCERR 000000000160
2026-04-23T20:44:32.9322010Z 4 Electron Framework ... views::Widget::IsVisible() const + 28
2026-04-23T20:44:32.9528810Z 6 Electron Framework ... electron::AutofillPopupView::Show() + 200
2026-04-23T20:44:32.9632090Z 7 Electron Framework ... electron::AutofillPopup::CreateView(...) + 1380
2026-04-23T20:44:32.9749770Z 8 Electron Framework ... electron::AutofillDriver::ShowAutofillPopup(...) + 736
2026-04-23T20:44:33.0015220Z ✗ Electron tests failed with kill signal SIGSEGV.
fix: ensure corsEnabled: false protocol handlers do not work across protocols (#51152)
* fix: ensure corsEnabled: false protocol handlers do not work across protocols
Subresource requests for registered custom protocols are routed to
ElectronURLLoaderFactory via the renderer's per-scheme URLLoaderFactoryBundle
entry, which bypasses the network service's CorsURLLoaderFactory. This meant a
cross-origin page could fetch() a scheme registered with {supportFetchAPI: true}
and read the response body even when {corsEnabled: true} was not set.
Replicate CorsURLLoader::StartRequest's kCorsDisabledScheme gate in
ElectronURLLoaderFactory::CreateLoaderAndStart so cross-origin mode=cors
requests to such schemes fail before the JS handler runs, and tag cross-origin
mode=no-cors responses as opaque so the body is not script-readable while <img>
and similar subresource loads continue to work.
Re-enable the long-disabled "disallows CORS and fetch requests when only
supportFetchAPI is specified" test, add coverage for the opaque/no-cors,
same-origin, handler-not-invoked, corsEnabled-unaffected and net.fetch-unaffected
cases, and migrate spec helpers that were exercising a {supportFetchAPI: true}
scheme cross-origin to a corsEnabled scheme.
* chore: oxfmt
(cherry picked from commit 92f0993d94)
fix: ignore draggable regions in hidden WebContentsView
Hidden child WebContentsViews were still contributing their draggable
regions to the parent window's non-client hit test, so clicks in the
area where a hidden view's draggable element would render still dragged
the window. Early-return HTNOWHERE when the view is not visible.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
fix: FTBFS when pdf is disabled
pdf_features.h has a static_assert that pdf is enabled
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
After #49428 made `NativeWindowViews::CanResize()` return `resizable_`
for frameless windows (instead of `resizable_ && thick_frame_`),
`HWNDMessageHandler::SizeConstraintsChanged()` started adding
`WS_THICKFRAME` to the window style whenever `CanResize()` reported true.
`WS_THICKFRAME` is incompatible with layered (translucent) windows and
destroys their transparency.
`SetContentSizeConstraints` already guards against this by skipping
`OnSizeConstraintsChanged()` when `!thick_frame_`. `SetResizable` did
not, so toggling resizability on a transparent window (e.g.
`setResizable(false)` then `setResizable(true)`) caused the Chromium
path to add `WS_THICKFRAME` and strip transparency.
Apply the same guard in `SetResizable`. Min/max constraints are still
enforced — Chromium reads them from the widget delegate on every
`WM_GETMINMAXINFO`, independent of `SizeConstraintsChanged()`.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* fix: intermittent CI failure is-not-alwaysOnTop
Ensure that the `always-on-top-changed` event always fires with the
right 'alwaysOnTop' boolean, regardless of interaction between
SetZOrderLevel() and MoveBehindTaskBarIfNeeded(). We know what the
value will be when all of the HWND events settle, so use that value.
Co-authored-by: Charles Kerr <charles@charleskerr.com>
* test: temporary commit to torture-test the new change with 1000 iterations
Co-authored-by: Charles Kerr <charles@charleskerr.com>
* test: keep eventually-becomes-consistent test but do not loop 1000 times
Co-authored-by: Charles Kerr <charles@charleskerr.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
fix: prevent use-after-free when destroying guest WebContents during event emission
Multiple event emission sites in WebContents destroy the underlying C++
object via a JavaScript event handler calling webContents.destroy(), then
continue to dereference the freed `this` pointer. This is exploitable
through <webview> guest WebContents because Destroy() calls `delete this`
synchronously for guests, unlike non-guests which safely defer deletion.
The fix has two layers:
1. A new `is_emitting_event_` flag is checked in Destroy() — when true,
guest deletion is deferred to a posted task instead of executing
synchronously. This is separate from `is_safe_to_delete_` (which
gates LoadURL re-entrancy) to avoid rejecting legitimate loadURL
calls from event handlers.
2. AutoReset<bool> guards on `is_emitting_event_` are added to
CloseContents, RenderViewDeleted, DidFinishNavigation, and
SetContentsBounds, preventing synchronous destruction while their
Emit() calls are on the stack.
Destroy() now requires both `is_safe_to_delete_` (navigation re-entrancy)
and `!is_emitting_event_` (event emission) to allow synchronous guest
deletion. The existing AutoReset guards on `is_safe_to_delete_` in
DidStartNavigation, DidRedirectNavigation, and ReadyToCommitNavigation
are also now effective for guests.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
fix: simpleFullScreen exits when web content calls requestFullscreen
SetHtmlApiFullscreen only checked IsFullscreen() to detect that the
window was already fullscreen, missing the simple-fullscreen case on
macOS. When web content triggered requestFullscreen the code fell
through to SetFullScreen(true) which toggled simple fullscreen off.
Include IsSimpleFullScreen() in the guard so the HTML-API fullscreen
state is updated without touching the window's fullscreen mode.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* chore: backport cppgc cleanups
Key fixes:
- Replace `base::WeakPtrFactory` with `gin::WeakCellFactory` in
MenuMac, MenuViews, and NetLog, since weak pointers to cppgc-managed
objects must go through weak cells
- Replace `v8::Global<v8::Value>` with `cppgc::Persistent<Menu>` for
the menu reference in BaseWindow
- Stop using `gin_helper::Handle<T>` with cppgc types; use raw `T*`
and add a `static_assert` to prevent future misuse
- Add proper `Trace()` overrides for Menu, MenuMac, MenuViews, and
NetLog to ensure cppgc members are visited during garbage collection
- Replace `SelfKeepAlive` prevent-GC mechanism in Menu with a
`cppgc::Persistent` prevent-GC captured in `BindSelfToClosure`
- Introduce `GC_PLUGIN_IGNORE` macro to suppress
known-safe violations: mojo::Remote fields, ObjC bridging pointers,
and intentional persistent self-references
- Mark `ArgumentHolder` as `CPPGC_STACK_ALLOCATED()` in both Electron's
and gin's function_template.h to silence raw-pointer-to-GC-type
warnings
* chore: fix build
chore: clean up clang-tidy warnings (#50862)
* chore: use emplace and use it correctly
* chore: redundant cast to the same type [google-readability-casting]
* chore: do not create objects with +new [google-objc-avoid-nsobject-new]
* chore: default arguments on virtual or override methods are prohibited [google-default-arguments]
* chore: warning: C-style casts are discouraged; use static_cast [google-readability-casting]
CFLocaleGetValue already returns CFTypeRef so that redundant static_cast was removed
* chore: refactor block to avoid use after move warning from clang-tidy
Looks like clang-tidy couldn't tell these were two mutually exclusive
branches so there was no actual issue, but refactoring is cleaner
anyway since it makes it more DRY.
* chore: C-style casts are discouraged; use static_cast [google-readability-casting]
No cast needed here, everything is already the correct type
* chore: C-style casts are discouraged; use static_cast/const_cast/reinterpret_cast [google-readability-casting]
* chore: use '= default' to define a trivial destructor [modernize-use-equals-default]
* chore: use range-based for loop instead [modernize-loop-convert]
* chore: redundant void argument list [modernize-redundant-void-arg]
* chore: address code review feedback
* chore: use auto
---------
Co-authored-by: Charles Kerr <charles@charleskerr.com>
fix: webContents.print() ignoring mediaSize when silent
PR #49523 moved the default media size fallback into OnGetDeviceNameToUse,
but the new code unconditionally writes kSettingMediaSize — clobbering
any mediaSize the caller had already set in WebContents::Print() from
options.mediaSize / pageSize. As a result, silent prints with an
explicit pageSize (e.g. "Letter") fell back to A4 with tiny content.
Only populate the default/printer media size when the caller hasn't
already supplied one, preserving the precedence:
1. user-supplied mediaSize / pageSize
2. printer default (when usePrinterDefaultPageSize is true)
3. A4 fallback
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Menu was holding a SelfKeepAlive to itself from construction, so any
Menu that was never opened (e.g. an application menu replaced before
being shown) stayed pinned in cppgc forever. Repeated calls to
Menu.setApplicationMenu leaked every prior Menu along with its model
and items.
Restore the original Pin/Unpin lifecycle: start keep_alive_ empty and
only assign `this` in OnMenuWillShow. OnMenuWillClose already clears
it.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
PR #50646 added a dock state allowlist in SetDockState() that collapsed any
non-matching value to "right". WebContents::OpenDevTools passes an empty
string when no `mode` option is given, which is the sentinel LoadCompleted()
uses to restore `currentDockState` from prefs. The allowlist clobbered that
sentinel to "right", so previously-undocked devtools would flash detached
and then snap back to the right dock.
Preserve the empty string through SetDockState() so the pref-restore path
runs; still reject any non-empty invalid value to keep the JS-injection
guard from #50646 intact.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
fix: enforce size constraints on window creation on Windows and Linux (#49906)
* enforce size constraints on window creation
* set constraints after resizing on init
* restore conditional centering
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
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.
WebContentsPermissionHelper::CheckPermission was hardcoding
GetPrimaryMainFrame() and deriving the requesting origin from
web_contents_->GetLastCommittedURL(), so the setPermissionCheckHandler
callback always received the top frame's origin and
details.isMainFrame/details.requestingUrl always reflected the main
frame, even when a cross-origin subframe with allow="serial" or
allow="camera; microphone" triggered the check.
Thread the requesting RenderFrameHost through CheckPermission,
CheckSerialAccessPermission, and CheckMediaAccessPermission so the
permission manager receives the real requesting frame. Update the
serial delegate and WebContents::CheckMediaAccessPermission callers to
pass the frame they already have.
Adds a regression test that loads a cross-origin iframe with
allow="camera; microphone", calls enumerateDevices() from within the
iframe, and asserts the permission check handler receives the iframe
origin for requestingOrigin, isMainFrame, and requestingUrl.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Sam Attard <sattard@anthropic.com>
fix: resolve getFileHandle concurrent stalling by queuing callbacks (#50597)
Previously, concurrent calls to FileSystemAccessPermissionContext::ConfirmSensitiveEntryAccess
for the same file path would silently discard the subsequent callbacks because
the internal callback map used a single callback per file path and std::map::try_emplace
would drop the callback if the key already existed. This caused Promises in JS
(e.g., dirHandle.getFileHandle()) to stall indefinitely.
This commit updates the callback map to hold a vector of callbacks, so all
concurrent requesters for the same filepath are grouped together and resolved
once the asynchronous blocklist check completes.
Notes: Fixed an issue where concurrent `getFileHandle` requests on the same path could stall indefinitely.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Kunal Dubey <21157775+xakep8@users.noreply.github.com>
fix: validate dock_state_ against allowlist before JS execution
The dock_state_ member was concatenated directly into a JavaScript
string and executed via ExecuteJavaScript() in the DevTools context.
We should validate against the four known dock states and fall back
to "right" for any unrecognized value for safety
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
fix: glitchy rendering and maximize behavior with different GTK themes (#50550)
* fix glitchy rendering with different gtk themes especially when maximizing
* use actual insets, not restored insets
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
fix the appearance of transparent frameless and client frame windows
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>
The `OnTraceBufferUsageAvailable` callback creates V8 handles via
`Dictionary::CreateEmpty()` before `promise.Resolve()` enters its
`SettleScope` (which provides a `HandleScope`). When the callback
fires asynchronously from a Mojo response (i.e. when a trace session
is active), there is no `HandleScope` on the stack, causing a fatal
V8 error: "Cannot create a handle without a HandleScope".
Add an explicit `v8::HandleScope` at the top of the callback, matching
the pattern used by the other contentTracing APIs which resolve their
promises through `SettleScope` or the static `ResolvePromise` helper.
Made-with: Cursor
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Alexey Kozy <alexey@anysphere.co>
fix: register PrintDialogLinuxFactory on Linux
Chromium 145 refactored Linux print dialog creation to use a factory
pattern instead of directly calling LinuxUi::CreatePrintDialog().
Chrome registers this factory in
ChromeBrowserMainExtraPartsViewsLinux::ToolkitInitialized(), but
Electron did not, causing PrintingContextLinux::EnsurePrintDialog()
to leave print_dialog_ null on every call.
Without a dialog, UseDefaultSettings() and UpdatePrinterSettings()
return success but with empty/unprocessed settings, causing
PrintMsgPrintParamsIsValid() to fail. This broke both window.print()
(no dialog appears) and webContents.print() (callback stuck until
app close with "Invalid printer settings").
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* fix: hex-encode Windows notification icon temp filenames
NotificationPresenterWin was using SHA1HashString(origin.spec()) directly
as the basename for the temporary PNG written for toast icons.
SHA1HashString returns raw digest bytes, so the generated filename could
contain invalid path characters on Windows. That caused WriteFile to fail
when saving notification icons, which left toast XML without the expected
icon path.
Hex-encode the digest before appending .png so the temporary filename is
filesystem-safe while keeping deterministic naming for a given origin.
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* Update shell/browser/notifications/win/notification_presenter_win.cc
Co-authored-by: Robo <hop2deep@gmail.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
GetDefaultPrinterDPI() creates a blank GtkPrintSettings and reads
its resolution, which returns 0 for uninitialized settings. With
DPI=0, SetPrintableAreaIfValid() computes a zero scale factor,
producing empty page dimensions that fail PrintMsgPrintParamsIsValid().
Fall back to kDefaultPdfDpi (72) when GTK returns 0, matching the
existing Windows fallback pattern when CreateDC fails.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
feat: add nativeTheme.shouldDifferentiateWithoutColor on macOS
Adds nativeTheme.shouldDifferentiateWithoutColor on macOS that maps to
NSWorkspace.accessibilityDisplayShouldDifferentiateWithoutColor. If true,
the user has indicated that they prefer UI that differentiates items with
something other than color alone. This is useful for users with color
vision deficiency.
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Robert Böhnke <robb@robb.is>
* feat: support notification priority on Windows
Add Windows notifications support urgency/priority levels.
This maps the existing `urgency` option (previously Linux-only) to
Windows toast notification priorities:
- 'critical' maps to ToastNotificationPriority_High, which sorts the
notification above default-priority items in Action Center.
- 'normal' and 'low' both map to ToastNotificationPriority_Default.
Note that on Windows, 'critical' priority does not prevent the toast
from being auto-dismissed. Users should additionally set `timeoutType`
to 'never' for that behavior.
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* chore: make linter happy
Co-authored-by: Charles Kerr <charles@charleskerr.com>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
* fix: correct utility process exit code on Windows
On Windows, process exit codes are 32-bit unsigned integers (DWORD).
When passed from Chromium to Electron as a signed int and then
implicitly converted to uint64_t, values with the high bit set
(e.g., NTSTATUS codes) undergo sign extension, producing incorrect
values.
Cast the exit code to uint32_t before widening to uint64_t to
prevent sign extension and preserve the original Windows exit code.
Fixes#49455
Co-authored-by: João Silva <joaomrsilva@tecnico.ulisboa.pt>
* fix: narrow HandleTermination and Shutdown to uint32_t, add tests
Co-authored-by: João Silva <joaomrsilva@tecnico.ulisboa.pt>
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: João Silva <joaomrsilva@tecnico.ulisboa.pt>
fix: improved the appearance of shadows and borders on frameless windows on Wayland (#50007)
* remove painting from linux frame layout
* use chromium csd strategy for frameless windows
* Apply suggestions from code review
Remove unneeded virtual methods
* removed inline destructors
---------
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Mitchell Cohen <mitch.cohen@me.com>