mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-15 14:22:43 +00:00
fix(desktop): cancel downloads triggered by link-title fetch window
The hidden BrowserWindow used by fetchLinkTitle to scrape page titles had no will-download handler on its session. When a link artifact URL responds with Content-Disposition: attachment, Electron fires will-download and the file is saved for real — explaining the spurious download on the Artifacts page. Add guardLinkTitleSession() (parallel to the existing audio-mute guard for #49505) that installs a will-download handler which immediately cancels every download item on the hermes:link-titles session. Call it from getLinkTitleSession() right after the request-type blocklist is wired up.
This commit is contained in:
parent
7e9e13fe55
commit
42bc07d107
3 changed files with 28 additions and 5 deletions
|
|
@ -3,8 +3,7 @@
|
|||
// Hidden BrowserWindow used by tier-2 link-title resolution: when curl can't
|
||||
// read a page <title> (bot walls, JS-rendered pages), we briefly load the URL
|
||||
// in an offscreen window and read its title. That window loads arbitrary
|
||||
// user-linked pages — including YouTube/`watch` URLs that autoplay — so it must
|
||||
// never be allowed to emit sound.
|
||||
// user-linked pages, so it must never emit sound or trigger real downloads.
|
||||
|
||||
function linkTitleWindowOptions(partitionSession) {
|
||||
return {
|
||||
|
|
@ -39,4 +38,15 @@ function createLinkTitleWindow(BrowserWindow, partitionSession) {
|
|||
return window
|
||||
}
|
||||
|
||||
module.exports = { createLinkTitleWindow, linkTitleWindowOptions }
|
||||
// Cancel any download the title-fetch window triggers. Without this, a link
|
||||
// artifact URL served with Content-Disposition: attachment auto-downloads every
|
||||
// time the Artifacts page renders and fetchLinkTitle loads it.
|
||||
function guardLinkTitleSession(partitionSession) {
|
||||
try {
|
||||
partitionSession.on('will-download', (_event, item) => item.cancel())
|
||||
} catch {
|
||||
// best-effort; worst case is a spurious download
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { createLinkTitleWindow, guardLinkTitleSession, linkTitleWindowOptions }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const assert = require('node:assert/strict')
|
||||
const test = require('node:test')
|
||||
|
||||
const { createLinkTitleWindow, linkTitleWindowOptions } = require('./link-title-window.cjs')
|
||||
const { createLinkTitleWindow, guardLinkTitleSession, linkTitleWindowOptions } = require('./link-title-window.cjs')
|
||||
|
||||
function makeFakeBrowserWindow() {
|
||||
const calls = { audioMuted: [] }
|
||||
|
|
@ -54,3 +54,15 @@ test('createLinkTitleWindow still returns the window if muting throws', () => {
|
|||
|
||||
assert.ok(window instanceof ThrowingBrowserWindow)
|
||||
})
|
||||
|
||||
test('guardLinkTitleSession cancels downloads triggered by the title-fetch window', () => {
|
||||
let cancelled = false
|
||||
const handlers = {}
|
||||
guardLinkTitleSession({ on: (e, h) => { handlers[e] = h } })
|
||||
handlers['will-download'](null, { cancel: () => { cancelled = true } })
|
||||
assert.ok(cancelled)
|
||||
})
|
||||
|
||||
test('guardLinkTitleSession is a no-op when session.on throws', () => {
|
||||
assert.doesNotThrow(() => guardLinkTitleSession({ on() { throw new Error() } }))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ const {
|
|||
SESSION_WINDOW_MIN_WIDTH
|
||||
} = require('./session-windows.cjs')
|
||||
const { canImportHermesCli, verifyHermesCli } = require('./backend-probes.cjs')
|
||||
const { createLinkTitleWindow } = require('./link-title-window.cjs')
|
||||
const { createLinkTitleWindow, guardLinkTitleSession } = require('./link-title-window.cjs')
|
||||
const { probeGatewayWebSocket } = require('./gateway-ws-probe.cjs')
|
||||
const { adoptServedDashboardToken } = require('./dashboard-token.cjs')
|
||||
const { waitForDashboardPortAnnouncement } = require('./backend-ready.cjs')
|
||||
|
|
@ -3509,6 +3509,7 @@ function getLinkTitleSession() {
|
|||
linkTitleSession.webRequest.onBeforeRequest((details, callback) => {
|
||||
callback({ cancel: RENDER_TITLE_BLOCKED_RESOURCES.has(details.resourceType) })
|
||||
})
|
||||
guardLinkTitleSession(linkTitleSession)
|
||||
return linkTitleSession
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue