Skip to content

Commit b4b71a0

Browse files
author
Aaron
committed
fix(extensions): resolve extension-relative URLs in windows.create
chrome.windows.create({ url: 'notification.html' }) from an extension background (e.g. Rabby's detached signing window) was passed through to impl.createWindow unresolved, producing a blank window (ERR_ABORTED). tabs.create already resolves via validateExtensionUrl; windows.create now does the same. Helper moved to api/common.ts to avoid a tabs<->windows import cycle. Claude-Session: https://claude.ai/code/session_01McBa3Lh2fTj1FyrjEiHGf3
1 parent 5b60d98 commit b4b71a0

3 files changed

Lines changed: 34 additions & 18 deletions

File tree

‎packages/electron-chrome-extensions/src/browser/api/common.ts‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,22 @@ export const getExtensionUrl = (extension: Electron.Extension, uri: string) => {
3636
} catch {}
3737
}
3838

39+
export const validateExtensionUrl = (url: string, extension: Electron.Extension) => {
40+
// Convert relative URLs to absolute if needed
41+
try {
42+
url = new URL(url, extension.url).href
43+
} catch (e) {
44+
throw new Error('Invalid URL')
45+
}
46+
47+
// Prevent creating chrome://kill or other debug commands
48+
if (url.startsWith('chrome:') || url.startsWith('javascript:')) {
49+
throw new Error('Invalid URL')
50+
}
51+
52+
return url
53+
}
54+
3955
export const resolveExtensionPath = (
4056
extension: Electron.Extension,
4157
uri: string,

‎packages/electron-chrome-extensions/src/browser/api/tabs.ts‎

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,17 @@
11
import { ExtensionContext } from '../context'
22
import { ExtensionEvent } from '../router'
3-
import { getAllWindows, matchesPattern, matchesTitlePattern, TabContents } from './common'
3+
import {
4+
getAllWindows,
5+
matchesPattern,
6+
matchesTitlePattern,
7+
validateExtensionUrl,
8+
TabContents,
9+
} from './common'
410
import { WindowsAPI } from './windows'
511
import debug from 'debug'
612

713
const d = debug('electron-chrome-extensions:tabs')
814

9-
const validateExtensionUrl = (url: string, extension: Electron.Extension) => {
10-
// Convert relative URLs to absolute if needed
11-
try {
12-
url = new URL(url, extension.url).href
13-
} catch (e) {
14-
throw new Error('Invalid URL')
15-
}
16-
17-
// Prevent creating chrome://kill or other debug commands
18-
if (url.startsWith('chrome:') || url.startsWith('javascript:')) {
19-
throw new Error('Invalid URL')
20-
}
21-
22-
return url
23-
}
24-
2515
export class TabsAPI {
2616
static TAB_ID_NONE = -1
2717
static WINDOW_ID_NONE = -1

‎packages/electron-chrome-extensions/src/browser/api/windows.ts‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ExtensionContext } from '../context'
22
import { ExtensionEvent } from '../router'
3+
import { validateExtensionUrl } from './common'
34
import debug from 'debug'
45

56
const d = debug('electron-chrome-extensions:windows')
@@ -109,7 +110,16 @@ export class WindowsAPI {
109110
}
110111

111112
private async create(event: ExtensionEvent, details: chrome.windows.CreateData) {
112-
const win = await this.ctx.store.createWindow(event, details)
113+
// Resolve extension-relative URLs (e.g. 'notification.html' from wallet
114+
// extensions) against the calling extension, mirroring tabs.create.
115+
let url = details.url
116+
if (typeof url === 'string') {
117+
url = validateExtensionUrl(url, event.extension)
118+
} else if (Array.isArray(url)) {
119+
url = url.map((u) => validateExtensionUrl(u, event.extension))
120+
}
121+
122+
const win = await this.ctx.store.createWindow(event, { ...details, url })
113123
return this.getWindowDetails(win)
114124
}
115125

0 commit comments

Comments
 (0)