Repository: electron/electron
Pull request: fix: crash when renderer process crashes while webview is reloading

#### Description of Change

Fix crash when renderer process crashes while webview is reloading

#### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->

- [x] PR description included and stakeholders cc'd
- [x] `npm test` passes
- [x] tests are [changed or added](https://github.com/electron/electron/blob/main/docs/development/testing.md)
- [ ] relevant API documentation, tutorials, and examples are updated and follow the [documentation style guide](https://github.com/electron/electron/blob/main/docs/development/style-guide.md)
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes
Notes: Fix crash when renderer process crashes while webview is reloading


Changed files:
filename: shell/browser/api/electron_api_web_contents.cc
patch: @@ -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,

filename: shell/browser/api/electron_api_web_contents.h
patch: @@ -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,

filename: spec/webview-spec.ts
patch: @@ -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()', () => {