fix: crash when renderer process crashes while webview is reloading (#46735)

WebView uses WebContentsViewChildFrame, which doesn't have a Focus impl
and triggers a fatal NOTREACHED.
This commit is contained in:
wujinli 2025-04-25 16:10:27 +08:00 committed by GitHub
parent 37f8db15e9
commit 3e78bbde6a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 31 additions and 0 deletions

View file

@ -4004,6 +4004,14 @@ void WebContents::ExitPictureInPicture() {
PictureInPictureWindowManager::GetInstance()->ExitPictureInPicture();
}
bool WebContents::ShouldFocusPageAfterCrash(content::WebContents* source) {
// WebView uses WebContentsViewChildFrame, which doesn't have a Focus impl
// and triggers a fatal NOTREACHED.
if (is_guest())
return false;
return true;
}
void WebContents::DevToolsSaveToFile(const std::string& url,
const std::string& content,
bool save_as,

View file

@ -709,6 +709,7 @@ class WebContents final : public ExclusiveAccessContext,
content::PictureInPictureResult EnterPictureInPicture(
content::WebContents* web_contents) override;
void ExitPictureInPicture() override;
bool ShouldFocusPageAfterCrash(content::WebContents* source) override;
// InspectableWebContentsDelegate:
void DevToolsSaveToFile(const std::string& url,

View file

@ -1895,6 +1895,28 @@ describe('<webview> tag', function () {
expect(channel).to.equal('onbeforeunload');
});
it('does not crash when renderer process crashes', async function () {
// It takes more time to wait for the rendering process to crash
this.timeout(120000);
await loadWebView(w, {
nodeintegration: 'on',
webpreferences: 'contextIsolation=no',
src: blankPageUrl
});
// Create a crash in the rendering process of a webview
await w.executeJavaScript(`new Promise((resolve, reject) => {
webview.addEventListener('render-process-gone', (e) => resolve({...e}), {once: true})
webview.executeJavaScript('process.crash()', true)
})`);
// Reload the webview and the main process will not crash.
await w.executeJavaScript(`new Promise((resolve, reject) => {
webview.reload()
webview.addEventListener('did-finish-load', () => {
resolve()
})
})`);
});
});
describe('<webview>.goForward()', () => {