fix(desktop): a browser pane's popup is a real tab for extensions
1Password's icon showed up in a "Sign in with Google" popup opened from a browser pane, but clicking it filled nothing — the credentials went into the pane behind the popup.
Why
Two defects, stacked:
- A popup window was not a tab.
configurePopupWindowset up the scheme guard and window-open policy but never told the extension host, which calledextensions.addTabfor panes and extension windows only. Measured live from a background service worker:chrome.tabs.query({})listed the pane and nothing else while the popup was open. tabs.queryignorescurrentWindow. electron-chrome-extensions reads the flag and never applies it, so the query returns every window's active tab and the caller takes[0]. 1Password'sactiveNativeTabis exactlytabs.query({active: true, currentWindow: true}), so even once the popup was a tab it still resolved to the pane.
While fixing those, four more places where a popup is second-class:
- every window reported
type: "normal", andwindows.getAllignoredwindowTypes— 1Password creates its own detached popout withtype: "popup"and reads the type back; - a tab's
indexwas always-1, andqueryrenumberedindexby the position in the result it was returning, so the field never meant position in the window; chrome.runtime.getContexts(Electron's own) answers with the service worker and nothing else, so an extension cannot see its own open popup and opens a second one.chrome.extension.getViewsis unfixable here — it must returnWindowobjects from another process — which is why MV3 code reaches forgetContextsfirst;- a popup window had no context menu at all: no copy or paste in a sign-in field, no back, and none of the items an extension contributes.
What changed
browser-manageremitspopup-created; the extension host adds the window as its own single-tab window, which also covers the consent window Google opens mid-flow and windows an extension page opens.- The app tells the package a window's type, so pane popups and extension windows read as
popup. patches/electron-chrome-extensions@4.10.0.patch:currentWindow/lastFocusedWindowintabs.query; a window focused when it is added becomes the current one (Chromium focuses a popup beforedid-create-windowhands it over);windowTypefrom the app plus thewindowTypesfilter; real tabindexwith no renumbering, andindex/windowTypefilters.chrome.runtime.getContextsis served from the extension host, over the existing service-worker IPC, for the extension's own pages.- Panes and popups share one context-menu builder; the popup leaves out the split it cannot open.
Verification
Driven in the dev app over CDP, pane on localhost with a popup window opened from it.
With a probe extension that mirrors 1Password's call chain (content script → runtime.sendMessage → tabs.query({active, currentWindow}) → tabs.sendMessage):
| before | after | |
|---|---|---|
tabs.query({}) | pane only | pane + popup |
tabs.query({active, currentWindow}) | the pane | the popup |
| popup's password field | empty | filled |
| pane's field behind it | filled — wrong page | untouched |
With the real 1Password extension installed and signed in, a throwaway login saved for the test origin: clicking the in-field icon in the popup filled it, and 1Password's own background now answers tabs.query({active: true, currentWindow: true}) with the popup.
Also confirmed live in the app: windows.getAll() reports the popup as popup and {windowTypes: ["popup"]} filters to it; tabs carry index: 0 in their own window; tabs.query({windowType: "popup"}) returns the popup tab; runtime.getContexts({}) lists the service worker and an open extension page, which Electron's own implementation misses; and a right-click in a popup builds the same menu as the pane, 1Password's own item included.
Not verified visually: the native menu that Menu.popup() draws appears at the OS cursor, which a synthetic click does not move, so the check was on the menu the app builds for that window.
bun test for the touched packages is green, typecheck and lint clean, check:i18n reports no new messages (every label already existed).
Summary by cubic
Fixes the sign-in popup opened from a browser pane so extensions can act on it — 1Password's in-field icon appeared in a "Sign in with Google" popup, but clicking it filled the pane behind the popup instead.
Bug Fixes
- A popup from a pane or an extension's own window is now a real tab for extensions, so
chrome.tabs.queryreturns it and extension requests target the popup. It is announced only after its scheme guard and window-open policy are in place, inside a try/catch. tabs.querynow honorscurrentWindowandlastFocusedWindow, resolving the focused window the same waywindows.getCurrentdoes, and a popup already focused when registered becomes the current window.- Windows report a real type (
popupvsnormal),windows.getAllfilters onwindowTypes, and tabs carry a realindexthatqueryalso filters on. chrome.runtime.getContextsnow lists the extension's own open pages, so an extension can see its open popup instead of opening a second one.- Popup windows now get the same right-click menu as panes (minus the split action), which they previously lacked entirely.
Summary by CodeRabbit
- New Features
- Browser extensions can now access information about their background, tab, popup, and offscreen contexts.
- Extension windows and popups are more consistently reflected in tab and window listings, including window types and tab positions.
- Improvements
- Web content and popup windows now share consistent context menus, with unavailable page actions disabled.
- Extension API results better respect permissions, and tab and window queries support additional filters.
- Compatibility
- Native messaging APIs are no longer available.