fix: show page title in popup title bar instead of doubling the origin

The native title bar and the origin bar both showed the origin, reading
as a doubled header. Match Chrome popup behavior: title bar shows the
page title (reset to origin on navigation so a stale title cannot
outlive its origin); the origin bar below remains the unspoofable trust
surface.

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Jinjing
2026-07-11 20:03:01 -07:00
co-authored by Orca
parent 384e091a34
commit 925bcccdc7
2 changed files with 28 additions and 0 deletions
@@ -253,6 +253,23 @@ describe('openPopupWithOriginBar', () => {
expect(lastWindow().setTitle).toHaveBeenCalledWith('http://phish.example.net')
})
it('shows the page title in the native title bar but resets to origin on navigation', () => {
const adopted = createFakeWebContents()
openPopupWithOriginBar(
{ webContents: adopted as never },
'https://accounts.example.com/oauth?code=SECRET'
)
// Until the page supplies a title, the window title is the origin.
expect(lastWindow().options.title).toBe('https://accounts.example.com')
adopted.emit('page-title-updated', {}, 'Sign in to Example')
expect(lastWindow().setTitle).toHaveBeenLastCalledWith('Sign in to Example')
// A stale title must not survive a cross-origin navigation.
adopted.emit('did-navigate', {}, 'https://evil.example.net/')
expect(lastWindow().setTitle).toHaveBeenLastCalledWith('https://evil.example.net')
})
it('closes the window when the popup content is destroyed', () => {
const adopted = createFakeWebContents()
openPopupWithOriginBar({ webContents: adopted as never }, 'https://example.com/')
@@ -139,6 +139,10 @@ export function openPopupWithOriginBar(
let currentUrl = initialUrl
const renderOrigin = (): void => {
const { label, insecure } = describePopupOrigin(currentUrl)
// Why: origin is the title only until the page supplies one — the bar
// below stays the trust surface, so the native title bar can show the
// page title (Chrome popup behavior) instead of doubling the origin.
// Re-asserting on navigation stops a stale title outliving its origin.
if (!window.isDestroyed()) {
window.setTitle(label)
}
@@ -161,6 +165,12 @@ export function openPopupWithOriginBar(
renderOrigin()
}
contentWebContents.on('did-navigate', handleDidNavigate)
const handlePageTitleUpdated = (_event: Electron.Event, title: string): void => {
if (!window.isDestroyed() && title) {
window.setTitle(title)
}
}
contentWebContents.on('page-title-updated', handlePageTitleUpdated)
// Why: with no adopted contents there is no Chromium-driven navigation for
// this popup, so load the target ourselves (opener handle is already gone).
@@ -179,6 +189,7 @@ export function openPopupWithOriginBar(
if (!contentWebContents.isDestroyed()) {
contentWebContents.off('destroyed', handleContentDestroyed)
contentWebContents.off('did-navigate', handleDidNavigate)
contentWebContents.off('page-title-updated', handlePageTitleUpdated)
// Why: close() (not destroy) so the page's unload handlers run — OAuth
// pages often notify the opener from unload.
contentWebContents.close()