fix: use appropriate site instance for cross-site nav's (#15821)
* fix: use Chromium's determined new site instance as candidate when navigating. When navigating to a new address, consider using Chromium's determined site instance for the new page as it should belong to an existing browsing instance when the navigation was triggered by window.open(). fixes 8100. * Revert "fix: use Chromium's determined new site instance as candidate when navigating." This reverts commit eb95f935654a2c4d4457821297670836c10fdfd5. * fix: delegate site instance creation back to content when sandboxed. * fix: ensure site isolation is on * test: adapt ut for cross-site navigation * fix: register pending processes during a navigation. * refactor: dont call loadURL for a window constructed from an existing webContents. * test: add sandboxed affinity UT's. * fix: check affinity before deciding if to force a new site instance. * chore: adapt subsequent patch. * refactor: constify logically const methods. * fix: do not reuse site instances when navigation redirects cross-site. * test: ensure localStorage accessible after x-site redirect. * test: adapt localStorage acess denied UT for site isolation. * fix: do not send render-view-deleted for speculative frames. * chore: amend tests after rebase. * test: add ut for webContents' render-view-deleted emission * fix: introduce current-render-view-deleted for current RVH's deletions. Revert render-view-deleted to being emitted with any RVH's deletion. current-render-view-deleted is emitted only when the RVH being deleted is the current one. * refactor: style and comments fixed.
This commit is contained in:
parent
46e7214974
commit
d5d1fa8290
14 changed files with 581 additions and 240 deletions
|
@ -90,6 +90,8 @@ describe('BrowserWindow module', () => {
|
|||
res.end()
|
||||
} else if (req.url === '/navigate-302') {
|
||||
res.end(`<html><body><script>window.location='${server.url}/302'</script></body></html>`)
|
||||
} else if (req.url === '/cross-site') {
|
||||
res.end(`<html><body><h1>${req.url}</h1></body></html>`)
|
||||
} else {
|
||||
res.end()
|
||||
}
|
||||
|
@ -1470,29 +1472,6 @@ describe('BrowserWindow module', () => {
|
|||
|
||||
const preload = path.join(fixtures, 'module', 'preload-sandbox.js')
|
||||
|
||||
// http protocol to simulate accessing another domain. This is required
|
||||
// because the code paths for cross domain popups is different.
|
||||
function crossDomainHandler (request, callback) {
|
||||
// Disabled due to false positive in StandardJS
|
||||
// eslint-disable-next-line standard/no-callback-literal
|
||||
callback({
|
||||
mimeType: 'text/html',
|
||||
data: `<html><body><h1>${request.url}</h1></body></html>`
|
||||
})
|
||||
}
|
||||
|
||||
before((done) => {
|
||||
protocol.interceptStringProtocol('http', crossDomainHandler, () => {
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
after((done) => {
|
||||
protocol.uninterceptProtocol('http', () => {
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('exposes ipcRenderer to preload script', (done) => {
|
||||
ipcMain.once('answer', function (event, test) {
|
||||
assert.strictEqual(test, 'preload')
|
||||
|
@ -1587,35 +1566,53 @@ describe('BrowserWindow module', () => {
|
|||
})
|
||||
|
||||
ipcRenderer.send('set-web-preferences-on-next-new-window', w.webContents.id, 'preload', preload)
|
||||
const openerWindowOpen = emittedOnce(ipcMain, 'opener-loaded')
|
||||
w.loadFile(
|
||||
path.join(fixtures, 'api', 'sandbox.html'),
|
||||
{ search: 'window-open-external' }
|
||||
)
|
||||
|
||||
// Wait for a message from the main window saying that it's ready.
|
||||
await openerWindowOpen
|
||||
|
||||
// Ask the opener to open a popup with window.opener.
|
||||
const expectedPopupUrl = `${server.url}/cross-site` // Set in "sandbox.html".
|
||||
|
||||
const browserWindowCreated = emittedOnce(app, 'browser-window-created')
|
||||
const childLoaded = emittedOnce(ipcMain, 'child-loaded')
|
||||
w.loadFile(path.join(fixtures, 'api', 'sandbox.html'), { search: 'window-open-external' })
|
||||
const expectedPopupUrl = 'http://www.google.com/#q=electron' // Set in the "sandbox.html".
|
||||
w.webContents.send('open-the-popup', expectedPopupUrl)
|
||||
|
||||
// The page is going to open a popup that it won't be able to close.
|
||||
// We have to close it from here later.
|
||||
// XXX(alexeykuzmin): It will leak if the test fails too soon.
|
||||
const [, popupWindow] = await browserWindowCreated
|
||||
|
||||
// Wait for a message from the popup's preload script.
|
||||
const [, openerIsNull, html, locationHref] = await childLoaded
|
||||
expect(openerIsNull).to.be.true('window.opener is not null')
|
||||
expect(html).to.equal(`<h1>${expectedPopupUrl}</h1>`,
|
||||
'looks like a http: request has not been intercepted locally')
|
||||
// Ask the popup window for details.
|
||||
const detailsAnswer = emittedOnce(ipcMain, 'child-loaded')
|
||||
popupWindow.webContents.send('provide-details')
|
||||
const [, openerIsNull, , locationHref] = await detailsAnswer
|
||||
expect(openerIsNull).to.be.false('window.opener is null')
|
||||
expect(locationHref).to.equal(expectedPopupUrl)
|
||||
|
||||
// Ask the page to access the popup.
|
||||
const answer = emittedOnce(ipcMain, 'answer')
|
||||
const touchPopupResult = emittedOnce(ipcMain, 'answer')
|
||||
w.webContents.send('touch-the-popup')
|
||||
const [, exceptionMessage] = await answer
|
||||
const [, popupAccessMessage] = await touchPopupResult
|
||||
|
||||
// Ask the popup to access the opener.
|
||||
const touchOpenerResult = emittedOnce(ipcMain, 'answer')
|
||||
popupWindow.webContents.send('touch-the-opener')
|
||||
const [, openerAccessMessage] = await touchOpenerResult
|
||||
|
||||
// We don't need the popup anymore, and its parent page can't close it,
|
||||
// so let's close it from here before we run any checks.
|
||||
await closeWindow(popupWindow, { assertSingleWindow: false })
|
||||
|
||||
expect(exceptionMessage).to.be.a('string',
|
||||
expect(popupAccessMessage).to.be.a('string',
|
||||
`child's .document is accessible from its parent window`)
|
||||
expect(exceptionMessage).to.match(/^Blocked a frame with origin/)
|
||||
expect(popupAccessMessage).to.match(/^Blocked a frame with origin/)
|
||||
expect(openerAccessMessage).to.be.a('string',
|
||||
`opener .document is accessible from a popup window`)
|
||||
expect(openerAccessMessage).to.match(/^Blocked a frame with origin/)
|
||||
})
|
||||
|
||||
it('should inherit the sandbox setting in opened windows', (done) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue