Skill update round trip / roundtrip (false, macos-latest, copy, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (false, macos-latest, symlink, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (false, ubuntu-latest, copy, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (false, ubuntu-latest, symlink, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (false, ubuntu-latest, symlink, latest) (push) Canceled after 0s
Skill update round trip / roundtrip (false, windows-latest, copy, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (false, windows-latest, symlink, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (true, macos-latest, copy, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (true, macos-latest, symlink, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (true, ubuntu-latest, copy, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (true, ubuntu-latest, symlink, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (true, windows-latest, copy, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (true, windows-latest, symlink, 1.5.17) (push) Canceled after 0s
89 lines
2.7 KiB
TypeScript
89 lines
2.7 KiB
TypeScript
import type { WebContents } from 'electron'
|
|
|
|
/**
|
|
* True when the target stays inside the window's own privileged document: for `file:`
|
|
* the exact same host+path (query/hash may differ, as a reload keeps them), for http(s)
|
|
* the same origin. Also gates preload privilege in installPrivilegedWindowNavigationPolicy,
|
|
* so loosening it past a same-origin document hands a foreign page the Orca bridge.
|
|
*/
|
|
export function isRendererDocumentNavigation(currentUrl: string, nextUrl: string): boolean {
|
|
try {
|
|
const current = new URL(currentUrl)
|
|
const next = new URL(nextUrl)
|
|
if (current.protocol === 'file:') {
|
|
return (
|
|
next.protocol === 'file:' &&
|
|
next.host === current.host &&
|
|
next.pathname === current.pathname
|
|
)
|
|
}
|
|
return (
|
|
(current.protocol === 'http:' || current.protocol === 'https:') &&
|
|
(next.protocol === 'http:' || next.protocol === 'https:') &&
|
|
next.origin === current.origin
|
|
)
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
export function registerRendererDocumentNavigation(
|
|
webContents: Pick<WebContents, 'getURL' | 'isLoadingMainFrame' | 'on'>,
|
|
onStarted: () => (() => void) | void
|
|
): void {
|
|
let documentGeneration = 0
|
|
let fenceGeneration = 0
|
|
let fenceActive = false
|
|
let cancelReload: (() => void) | null = null
|
|
const restoreSurvivingDocument = (): void => {
|
|
if (
|
|
!fenceActive ||
|
|
fenceGeneration !== documentGeneration ||
|
|
webContents.isLoadingMainFrame()
|
|
) {
|
|
return
|
|
}
|
|
fenceActive = false
|
|
const cancel = cancelReload
|
|
cancelReload = null
|
|
cancel?.()
|
|
}
|
|
// Why: did-start-loading also fires for blocked external links whose renderer document survives.
|
|
webContents.on('did-start-navigation', (_event, url, isSameDocument, isMainFrame) => {
|
|
if (isMainFrame && !isSameDocument && isRendererDocumentNavigation(webContents.getURL(), url)) {
|
|
if (!fenceActive) {
|
|
fenceActive = true
|
|
fenceGeneration = documentGeneration
|
|
cancelReload = onStarted() ?? null
|
|
}
|
|
}
|
|
})
|
|
webContents.on(
|
|
'did-fail-provisional-load',
|
|
(_event, _errorCode, _errorDescription, _validatedUrl, isMainFrame) => {
|
|
if (!isMainFrame) {
|
|
return
|
|
}
|
|
queueMicrotask(restoreSurvivingDocument)
|
|
}
|
|
)
|
|
webContents.on('will-navigate', (event, _url, _sameDocument, isMainFrame) => {
|
|
if (!isMainFrame) {
|
|
return
|
|
}
|
|
queueMicrotask(() => {
|
|
if (event.defaultPrevented) {
|
|
restoreSurvivingDocument()
|
|
}
|
|
})
|
|
})
|
|
webContents.on('did-stop-loading', restoreSurvivingDocument)
|
|
webContents.on('did-frame-navigate', (_event, _url, _code, _status, isMainFrame) => {
|
|
if (isMainFrame) {
|
|
documentGeneration += 1
|
|
fenceActive = false
|
|
cancelReload = null
|
|
}
|
|
})
|
|
}
|