fix: emit will-navigate for sandboxed contents (#22188)
This commit is contained in:
parent
8045152e59
commit
a25d7fa440
5 changed files with 187 additions and 104 deletions
|
@ -292,8 +292,21 @@ content::WebContents* CommonWebContentsDelegate::OpenURLFromTab(
|
||||||
load_url_params.should_replace_current_entry =
|
load_url_params.should_replace_current_entry =
|
||||||
params.should_replace_current_entry;
|
params.should_replace_current_entry;
|
||||||
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
|
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
|
||||||
|
load_url_params.started_from_context_menu = params.started_from_context_menu;
|
||||||
load_url_params.initiator_origin = params.initiator_origin;
|
load_url_params.initiator_origin = params.initiator_origin;
|
||||||
load_url_params.should_clear_history_list = true;
|
load_url_params.source_site_instance = params.source_site_instance;
|
||||||
|
load_url_params.frame_tree_node_id = params.frame_tree_node_id;
|
||||||
|
load_url_params.redirect_chain = params.redirect_chain;
|
||||||
|
load_url_params.has_user_gesture = params.user_gesture;
|
||||||
|
load_url_params.blob_url_loader_factory = params.blob_url_loader_factory;
|
||||||
|
load_url_params.href_translate = params.href_translate;
|
||||||
|
load_url_params.reload_type = params.reload_type;
|
||||||
|
|
||||||
|
if (params.post_data) {
|
||||||
|
load_url_params.load_type =
|
||||||
|
content::NavigationController::LOAD_TYPE_HTTP_POST;
|
||||||
|
load_url_params.post_data = params.post_data;
|
||||||
|
}
|
||||||
|
|
||||||
source->GetController().LoadURLWithParams(load_url_params);
|
source->GetController().LoadURLWithParams(load_url_params);
|
||||||
return source;
|
return source;
|
||||||
|
|
|
@ -291,4 +291,12 @@ void ElectronSandboxedRendererClient::WillReleaseScriptContext(
|
||||||
InvokeHiddenCallback(context, kLifecycleKey, "onExit");
|
InvokeHiddenCallback(context, kLifecycleKey, "onExit");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ElectronSandboxedRendererClient::ShouldFork(blink::WebLocalFrame* frame,
|
||||||
|
const GURL& url,
|
||||||
|
const std::string& http_method,
|
||||||
|
bool is_initial_navigation,
|
||||||
|
bool is_server_redirect) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace electron
|
} // namespace electron
|
||||||
|
|
|
@ -37,6 +37,11 @@ class ElectronSandboxedRendererClient : public RendererClientBase {
|
||||||
void RenderViewCreated(content::RenderView*) override;
|
void RenderViewCreated(content::RenderView*) override;
|
||||||
void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) override;
|
void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) override;
|
||||||
void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) override;
|
void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) override;
|
||||||
|
bool ShouldFork(blink::WebLocalFrame* frame,
|
||||||
|
const GURL& url,
|
||||||
|
const std::string& http_method,
|
||||||
|
bool is_initial_navigation,
|
||||||
|
bool is_server_redirect) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<base::ProcessMetrics> metrics_;
|
std::unique_ptr<base::ProcessMetrics> metrics_;
|
||||||
|
|
|
@ -434,110 +434,168 @@ describe('BrowserWindow module', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('navigation events', () => {
|
for (const sandbox of [false, true]) {
|
||||||
let w = null as unknown as BrowserWindow
|
describe(`navigation events${sandbox ? ' with sandbox' : ''}`, () => {
|
||||||
beforeEach(() => {
|
let w = null as unknown as BrowserWindow
|
||||||
w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } })
|
beforeEach(() => {
|
||||||
})
|
w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: false, sandbox } })
|
||||||
afterEach(async () => {
|
})
|
||||||
await closeWindow(w)
|
afterEach(async () => {
|
||||||
w = null as unknown as BrowserWindow
|
await closeWindow(w)
|
||||||
})
|
w = null as unknown as BrowserWindow
|
||||||
|
})
|
||||||
|
|
||||||
describe('will-navigate event', () => {
|
describe('will-navigate event', () => {
|
||||||
it('allows the window to be closed from the event listener', (done) => {
|
let server = null as unknown as http.Server
|
||||||
w.webContents.once('will-navigate', () => {
|
let url = null as unknown as string
|
||||||
w.close()
|
before((done) => {
|
||||||
done()
|
server = http.createServer((req, res) => { res.end('') })
|
||||||
|
server.listen(0, '127.0.0.1', () => {
|
||||||
|
url = `http://127.0.0.1:${(server.address() as AddressInfo).port}/`
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
server.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('allows the window to be closed from the event listener', (done) => {
|
||||||
|
w.webContents.once('will-navigate', () => {
|
||||||
|
w.close()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
w.loadFile(path.join(fixtures, 'pages', 'will-navigate.html'))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can be prevented', (done) => {
|
||||||
|
let willNavigate = false
|
||||||
|
w.webContents.once('will-navigate', (e) => {
|
||||||
|
willNavigate = true
|
||||||
|
e.preventDefault()
|
||||||
|
})
|
||||||
|
w.webContents.on('did-stop-loading', () => {
|
||||||
|
if (willNavigate) {
|
||||||
|
// i.e. it shouldn't have had '?navigated' appended to it.
|
||||||
|
expect(w.webContents.getURL().endsWith('will-navigate.html')).to.be.true()
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
w.loadFile(path.join(fixtures, 'pages', 'will-navigate.html'))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('is triggered when navigating from file: to http:', async () => {
|
||||||
|
await w.loadFile(path.join(fixtures, 'api', 'blank.html'))
|
||||||
|
w.webContents.executeJavaScript(`location.href = ${JSON.stringify(url)}`)
|
||||||
|
const navigatedTo = await new Promise(resolve => {
|
||||||
|
w.webContents.once('will-navigate', (e, url) => {
|
||||||
|
e.preventDefault()
|
||||||
|
resolve(url)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
expect(navigatedTo).to.equal(url)
|
||||||
|
expect(w.webContents.getURL()).to.match(/^file:/)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('is triggered when navigating from about:blank to http:', async () => {
|
||||||
|
await w.loadURL('about:blank')
|
||||||
|
w.webContents.executeJavaScript(`location.href = ${JSON.stringify(url)}`)
|
||||||
|
const navigatedTo = await new Promise(resolve => {
|
||||||
|
w.webContents.once('will-navigate', (e, url) => {
|
||||||
|
e.preventDefault()
|
||||||
|
resolve(url)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
expect(navigatedTo).to.equal(url)
|
||||||
|
expect(w.webContents.getURL()).to.equal('about:blank')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('will-redirect event', () => {
|
||||||
|
let server = null as unknown as http.Server
|
||||||
|
let url = null as unknown as string
|
||||||
|
before((done) => {
|
||||||
|
server = http.createServer((req, res) => {
|
||||||
|
if (req.url === '/302') {
|
||||||
|
res.setHeader('Location', '/200')
|
||||||
|
res.statusCode = 302
|
||||||
|
res.end()
|
||||||
|
} else if (req.url === '/navigate-302') {
|
||||||
|
res.end(`<html><body><script>window.location='${url}/302'</script></body></html>`)
|
||||||
|
} else {
|
||||||
|
res.end()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
server.listen(0, '127.0.0.1', () => {
|
||||||
|
url = `http://127.0.0.1:${(server.address() as AddressInfo).port}`
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
server.close()
|
||||||
|
})
|
||||||
|
it('is emitted on redirects', (done) => {
|
||||||
|
w.webContents.on('will-redirect', () => {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
w.loadURL(`${url}/302`)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('is emitted after will-navigate on redirects', (done) => {
|
||||||
|
let navigateCalled = false
|
||||||
|
w.webContents.on('will-navigate', () => {
|
||||||
|
navigateCalled = true
|
||||||
|
})
|
||||||
|
w.webContents.on('will-redirect', () => {
|
||||||
|
expect(navigateCalled).to.equal(true, 'should have called will-navigate first')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
w.loadURL(`${url}/navigate-302`)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('is emitted before did-stop-loading on redirects', (done) => {
|
||||||
|
let stopCalled = false
|
||||||
|
w.webContents.on('did-stop-loading', () => {
|
||||||
|
stopCalled = true
|
||||||
|
})
|
||||||
|
w.webContents.on('will-redirect', () => {
|
||||||
|
expect(stopCalled).to.equal(false, 'should not have called did-stop-loading first')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
w.loadURL(`${url}/302`)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('allows the window to be closed from the event listener', (done) => {
|
||||||
|
w.webContents.once('will-redirect', () => {
|
||||||
|
w.close()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
w.loadURL(`${url}/302`)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can be prevented', (done) => {
|
||||||
|
w.webContents.once('will-redirect', (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
})
|
||||||
|
w.webContents.on('will-navigate', (e, u) => {
|
||||||
|
expect(u).to.equal(`${url}/302`)
|
||||||
|
})
|
||||||
|
w.webContents.on('did-stop-loading', () => {
|
||||||
|
expect(w.webContents.getURL()).to.equal(
|
||||||
|
`${url}/navigate-302`,
|
||||||
|
'url should not have changed after navigation event'
|
||||||
|
)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
w.webContents.on('will-redirect', (e, u) => {
|
||||||
|
expect(u).to.equal(`${url}/200`)
|
||||||
|
})
|
||||||
|
w.loadURL(`${url}/navigate-302`)
|
||||||
})
|
})
|
||||||
w.loadFile(path.join(fixtures, 'pages', 'will-navigate.html'))
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
}
|
||||||
describe('will-redirect event', () => {
|
|
||||||
let server = null as unknown as http.Server
|
|
||||||
let url = null as unknown as string
|
|
||||||
before((done) => {
|
|
||||||
server = http.createServer((req, res) => {
|
|
||||||
if (req.url === '/302') {
|
|
||||||
res.setHeader('Location', '/200')
|
|
||||||
res.statusCode = 302
|
|
||||||
res.end()
|
|
||||||
} else if (req.url === '/navigate-302') {
|
|
||||||
res.end(`<html><body><script>window.location='${url}/302'</script></body></html>`)
|
|
||||||
} else {
|
|
||||||
res.end()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
server.listen(0, '127.0.0.1', () => {
|
|
||||||
url = `http://127.0.0.1:${(server.address() as AddressInfo).port}`
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
after(() => {
|
|
||||||
server.close()
|
|
||||||
})
|
|
||||||
it('is emitted on redirects', (done) => {
|
|
||||||
w.webContents.on('will-redirect', () => {
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
w.loadURL(`${url}/302`)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('is emitted after will-navigate on redirects', (done) => {
|
|
||||||
let navigateCalled = false
|
|
||||||
w.webContents.on('will-navigate', () => {
|
|
||||||
navigateCalled = true
|
|
||||||
})
|
|
||||||
w.webContents.on('will-redirect', () => {
|
|
||||||
expect(navigateCalled).to.equal(true, 'should have called will-navigate first')
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
w.loadURL(`${url}/navigate-302`)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('is emitted before did-stop-loading on redirects', (done) => {
|
|
||||||
let stopCalled = false
|
|
||||||
w.webContents.on('did-stop-loading', () => {
|
|
||||||
stopCalled = true
|
|
||||||
})
|
|
||||||
w.webContents.on('will-redirect', () => {
|
|
||||||
expect(stopCalled).to.equal(false, 'should not have called did-stop-loading first')
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
w.loadURL(`${url}/302`)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('allows the window to be closed from the event listener', (done) => {
|
|
||||||
w.webContents.once('will-redirect', () => {
|
|
||||||
w.close()
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
w.loadURL(`${url}/302`)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('can be prevented', (done) => {
|
|
||||||
w.webContents.once('will-redirect', (event) => {
|
|
||||||
event.preventDefault()
|
|
||||||
})
|
|
||||||
w.webContents.on('will-navigate', (e, u) => {
|
|
||||||
expect(u).to.equal(`${url}/302`)
|
|
||||||
})
|
|
||||||
w.webContents.on('did-stop-loading', () => {
|
|
||||||
expect(w.webContents.getURL()).to.equal(
|
|
||||||
`${url}/navigate-302`,
|
|
||||||
'url should not have changed after navigation event'
|
|
||||||
)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
w.webContents.on('will-redirect', (e, u) => {
|
|
||||||
expect(u).to.equal(`${url}/200`)
|
|
||||||
})
|
|
||||||
w.loadURL(`${url}/navigate-302`)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('focus and visibility', () => {
|
describe('focus and visibility', () => {
|
||||||
let w = null as unknown as BrowserWindow
|
let w = null as unknown as BrowserWindow
|
||||||
|
@ -2088,8 +2146,7 @@ describe('BrowserWindow module', () => {
|
||||||
'did-finish-load',
|
'did-finish-load',
|
||||||
'did-frame-finish-load',
|
'did-frame-finish-load',
|
||||||
'did-navigate-in-page',
|
'did-navigate-in-page',
|
||||||
// TODO(nornagon): sandboxed pages should also emit will-navigate
|
'will-navigate',
|
||||||
// 'will-navigate',
|
|
||||||
'did-start-loading',
|
'did-start-loading',
|
||||||
'did-stop-loading',
|
'did-stop-loading',
|
||||||
'did-frame-finish-load',
|
'did-frame-finish-load',
|
||||||
|
|
2
spec/fixtures/pages/will-navigate.html
vendored
2
spec/fixtures/pages/will-navigate.html
vendored
|
@ -1,7 +1,7 @@
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<script type="text/javascript" charset="utf-8">
|
<script type="text/javascript" charset="utf-8">
|
||||||
location.reload();
|
location.href += '?navigated'
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in a new issue