Skip to content

Commit a8d0ebb

Browse files
committed
fix(desktop): preserve the foreground restore timeout after promotion
1 parent 79836b0 commit a8d0ebb

2 files changed

Lines changed: 58 additions & 48 deletions

File tree

apps/desktop/src/main/browser-agent/session.test.ts

Lines changed: 56 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -840,53 +840,64 @@ describe('browser-agent session', () => {
840840
}
841841
})
842842

843-
it('extends an in-flight background restore without restarting its load', async () => {
844-
vi.useFakeTimers()
845-
try {
846-
const tabs = Array.from({ length: 4 }, (_, index) => ({
847-
url: `https://active-restore-${index}.example/`,
848-
}))
849-
const { persistence } = memoryBrowserPersistence({
850-
'chat-active-restore': { v: 1, tabs, activeIndex: 0, downloads: [] },
851-
})
852-
const createdContents: MockView['webContents'][] = []
853-
const selectedLoads: Array<() => void> = []
854-
session = freshSession(
855-
win,
856-
{
857-
onTabCreated: (webContents) => {
858-
const contents = webContents as unknown as MockView['webContents']
859-
const index = createdContents.push(contents) - 1
860-
contents.loadURL.mockImplementation(
861-
() =>
862-
new Promise<void>((resolve) => {
863-
if (index === 1) selectedLoads.push(resolve)
864-
})
865-
)
843+
it.each(['loaded', 'timed-out'] as const)(
844+
'gives a late foreground promotion its full loading window (%s)',
845+
async (outcome) => {
846+
vi.useFakeTimers()
847+
try {
848+
const tabs = Array.from({ length: 4 }, (_, index) => ({
849+
url: `https://active-restore-${index}.example/`,
850+
}))
851+
const { persistence } = memoryBrowserPersistence({
852+
'chat-active-restore': { v: 1, tabs, activeIndex: 0, downloads: [] },
853+
})
854+
const createdContents: MockView['webContents'][] = []
855+
const selectedLoads: Array<() => void> = []
856+
session = freshSession(
857+
win,
858+
{
859+
onTabCreated: (webContents) => {
860+
const contents = webContents as unknown as MockView['webContents']
861+
const index = createdContents.push(contents) - 1
862+
contents.loadURL.mockImplementation(
863+
() =>
864+
new Promise<void>((resolve) => {
865+
if (index === 1) selectedLoads.push(resolve)
866+
})
867+
)
868+
},
866869
},
867-
},
868-
persistence
869-
)
870-
871-
const selected = session.withBrowserScope('chat-active-restore', () => {
872-
session.restoreBrowserSession()
873-
return session.switchAutomationTab('2')
874-
})
875-
const selection = session.withBrowserScope('chat-active-restore', () =>
876-
session.waitForPendingTabRestore(selected)
877-
)
878-
879-
expect(createdContents[1].loadURL).toHaveBeenCalledOnce()
880-
expect(createdContents[1].stop).not.toHaveBeenCalled()
881-
await vi.advanceTimersByTimeAsync(15_000)
882-
expect(createdContents[1].stop).not.toHaveBeenCalled()
883-
884-
selectedLoads[0]?.()
885-
await expect(selection).resolves.toBe(true)
886-
} finally {
887-
vi.useRealTimers()
870+
persistence
871+
)
872+
873+
session.withBrowserScope('chat-active-restore', () => session.restoreBrowserSession())
874+
await vi.advanceTimersByTimeAsync(14_000)
875+
const selected = session.withBrowserScope('chat-active-restore', () =>
876+
session.switchAutomationTab('2')
877+
)
878+
const selection = session.withBrowserScope('chat-active-restore', () =>
879+
session.waitForPendingTabRestore(selected)
880+
)
881+
882+
expect(createdContents[1].loadURL).toHaveBeenCalledOnce()
883+
expect(createdContents[1].stop).not.toHaveBeenCalled()
884+
await vi.advanceTimersByTimeAsync(19_999)
885+
expect(createdContents[1].stop).not.toHaveBeenCalled()
886+
887+
if (outcome === 'loaded') {
888+
selectedLoads[0]?.()
889+
await expect(selection).resolves.toBe(true)
890+
} else {
891+
session.withBrowserScope('chat-active-restore', () => session.switchAutomationTab('2'))
892+
await vi.advanceTimersByTimeAsync(1)
893+
await expect(selection).resolves.toBe(false)
894+
expect(createdContents[1].stop).toHaveBeenCalledOnce()
895+
}
896+
} finally {
897+
vi.useRealTimers()
898+
}
888899
}
889-
})
900+
)
890901

891902
it('queues a fifth foreground restore without preempting another foreground restore', async () => {
892903
const snapshots = Object.fromEntries(

apps/desktop/src/main/browser-agent/session.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2448,8 +2448,7 @@ function loadPendingTabRestore(pending: PendingTabRestore, timeoutMs: number): P
24482448
return new Promise((resolve) => {
24492449
let settled = false
24502450
let timeout: ReturnType<typeof setTimeout> | undefined
2451-
const startedAt = Date.now()
2452-
let deadlineAt = startedAt + timeoutMs
2451+
let deadlineAt = Date.now() + timeoutMs
24532452
let foregroundDeadlineGranted = pending.priority === 'foreground'
24542453
const finish = (loaded: boolean) => {
24552454
if (settled) return
@@ -2496,7 +2495,7 @@ function loadPendingTabRestore(pending: PendingTabRestore, timeoutMs: number): P
24962495
pending.promoteToForeground = () => {
24972496
if (settled || foregroundDeadlineGranted) return
24982497
foregroundDeadlineGranted = true
2499-
deadlineAt = startedAt + FOREGROUND_TAB_RESTORE_TIMEOUT_MS
2498+
deadlineAt = Date.now() + FOREGROUND_TAB_RESTORE_TIMEOUT_MS
25002499
scheduleDeadline()
25012500
}
25022501
scheduleDeadline()

0 commit comments

Comments
 (0)