fix(browser): land PR #22571 with safe extension handshake handling
Bind relay WS message handling before onopen and add non-blocking connect.challenge response support without forcing handshake waits on current relay protocol. Landed from contributor @pandego (PR #22571). Co-authored-by: pandego <7780875+pandego@users.noreply.github.com>
This commit is contained in:
@@ -13,6 +13,9 @@ const BADGE = {
|
||||
let relayWs = null
|
||||
/** @type {Promise<void>|null} */
|
||||
let relayConnectPromise = null
|
||||
let relayGatewayToken = ''
|
||||
/** @type {string|null} */
|
||||
let relayConnectRequestId = null
|
||||
|
||||
let nextSession = 1
|
||||
|
||||
@@ -143,6 +146,13 @@ async function ensureRelayConnection() {
|
||||
|
||||
const ws = new WebSocket(wsUrl)
|
||||
relayWs = ws
|
||||
relayGatewayToken = gatewayToken
|
||||
// Bind message handler before open so an immediate first frame (for example
|
||||
// gateway connect.challenge) cannot be missed.
|
||||
ws.onmessage = (event) => {
|
||||
if (ws !== relayWs) return
|
||||
void whenReady(() => onRelayMessage(String(event.data || '')))
|
||||
}
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
const t = setTimeout(() => reject(new Error('WebSocket connect timeout')), 5000)
|
||||
@@ -162,10 +172,6 @@ async function ensureRelayConnection() {
|
||||
|
||||
// Bind permanent handlers. Guard against stale socket: if this WS was
|
||||
// replaced before its close fires, the handler is a no-op.
|
||||
ws.onmessage = (event) => {
|
||||
if (ws !== relayWs) return
|
||||
void whenReady(() => onRelayMessage(String(event.data || '')))
|
||||
}
|
||||
ws.onclose = () => {
|
||||
if (ws !== relayWs) return
|
||||
onRelayClosed('closed')
|
||||
@@ -188,6 +194,8 @@ async function ensureRelayConnection() {
|
||||
// Debugger sessions are kept alive so they survive transient WS drops.
|
||||
function onRelayClosed(reason) {
|
||||
relayWs = null
|
||||
relayGatewayToken = ''
|
||||
relayConnectRequestId = null
|
||||
|
||||
for (const [id, p] of pending.entries()) {
|
||||
pending.delete(id)
|
||||
@@ -308,6 +316,33 @@ function sendToRelay(payload) {
|
||||
ws.send(JSON.stringify(payload))
|
||||
}
|
||||
|
||||
function ensureGatewayHandshakeStarted(payload) {
|
||||
if (relayConnectRequestId) return
|
||||
const nonce = typeof payload?.nonce === 'string' ? payload.nonce.trim() : ''
|
||||
relayConnectRequestId = `ext-connect-${Date.now()}-${Math.random().toString(16).slice(2, 8)}`
|
||||
sendToRelay({
|
||||
type: 'req',
|
||||
id: relayConnectRequestId,
|
||||
method: 'connect',
|
||||
params: {
|
||||
minProtocol: 3,
|
||||
maxProtocol: 3,
|
||||
client: {
|
||||
id: 'chrome-relay-extension',
|
||||
version: '1.0.0',
|
||||
platform: 'chrome-extension',
|
||||
mode: 'webchat',
|
||||
},
|
||||
role: 'operator',
|
||||
scopes: ['operator.read', 'operator.write'],
|
||||
caps: [],
|
||||
commands: [],
|
||||
nonce: nonce || undefined,
|
||||
auth: relayGatewayToken ? { token: relayGatewayToken } : undefined,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async function maybeOpenHelpOnce() {
|
||||
try {
|
||||
const stored = await chrome.storage.local.get(['helpOnErrorShown'])
|
||||
@@ -349,6 +384,33 @@ async function onRelayMessage(text) {
|
||||
return
|
||||
}
|
||||
|
||||
if (msg && msg.type === 'event' && msg.event === 'connect.challenge') {
|
||||
try {
|
||||
ensureGatewayHandshakeStarted(msg.payload)
|
||||
} catch (err) {
|
||||
console.warn('gateway connect handshake start failed', err instanceof Error ? err.message : String(err))
|
||||
relayConnectRequestId = null
|
||||
const ws = relayWs
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
ws.close(1008, 'gateway connect failed')
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (msg && msg.type === 'res' && relayConnectRequestId && msg.id === relayConnectRequestId) {
|
||||
relayConnectRequestId = null
|
||||
if (!msg.ok) {
|
||||
const detail = msg?.error?.message || msg?.error || 'gateway connect failed'
|
||||
console.warn('gateway connect handshake rejected', String(detail))
|
||||
const ws = relayWs
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
ws.close(1008, 'gateway connect failed')
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (msg && msg.method === 'ping') {
|
||||
try {
|
||||
sendToRelay({ method: 'pong' })
|
||||
|
||||
Reference in New Issue
Block a user