Skip to content

Ade Browser Link Crashes#674

Merged
arul28 merged 5 commits into
mainfrom
ade/ade-browser-when-visit-linear-a73f0d7b
Jun 30, 2026
Merged

Ade Browser Link Crashes#674
arul28 merged 5 commits into
mainfrom
ade/ade-browser-when-visit-linear-a73f0d7b

Conversation

@arul28

@arul28 arul28 commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Summary

Describe the change.

What Changed

Key files and behaviors.

Validation

How you tested.

Risks

Anything to watch.

ADE   Open in ADE  ·  ade/ade-browser-when-visit-linear-a73f0d7b branch  ·  PR #674

Summary by CodeRabbit

  • New Features

    • Browser tabs now automatically recover after a renderer crash, restoring the tab to a safe blank page and notifying you of the issue.
  • Bug Fixes

    • Popup links are now handled more reliably by opening them in the intended tab instead of creating a separate window.
    • Improved tab state updates and error reporting during page load failures and crash recovery.

Greptile Summary

This PR fixes two Electron browser crash issues: renderer process crashes now recover the tab to about:blank instead of leaving it in a broken state, and popup link handling now correctly creates tabs inside Electron's createWindow callback rather than pre-creating them in setWindowOpenHandler.

  • Crash recovery: Adds recoverTabAfterRenderProcessGone with idempotency via renderProcessRecoveryTabs Set, proper cleanup in a finally block (notifyTabActivity + emitStatus), and clear distinction between a clean exit and a real crash.
  • Popup fix: Moves WebContentsView creation into the createWindow callback and ignores caller-supplied webPreferences in favor of browserWebPreferences(), closing a potential security gap where a page could influence popup sandbox settings.
  • Tests: A new test verifies crash recovery emits the right error event and restores tab state; the existing popup test is expanded to verify secure web preferences are applied regardless of what the opener specifies.

Confidence Score: 5/5

Safe to merge — both crash recovery and popup handling are well-guarded with finally-block cleanup, idempotency, and secure web preferences enforced on every popup tab.

The crash recovery path uses a finally block that always calls notifyTabActivity and emitStatus regardless of success or failure, and the renderProcessRecoveryTabs Set prevents re-entrant recovery. The popup change correctly defers WebContentsView creation into createWindow and ignores caller-supplied web preferences, which is both the correct Electron API pattern and a hardening of the security boundary. Tests cover both code paths including the URL-redaction behaviour on the logger.

No files require special attention.

Important Files Changed

Filename Overview
apps/desktop/src/main/services/builtInBrowser/builtInBrowserService.ts Adds crash recovery for renderer processes and fixes popup tab creation; logic is well-guarded with idempotency, finally-block cleanup, and security-enforcing web preferences
apps/desktop/src/main/services/builtInBrowser/builtInBrowserService.test.ts Adds crash recovery test (including URL redaction validation) and extends popup test to assert secure web preferences are applied regardless of opener-supplied options

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant E as Electron
    participant H as render-process-gone handler
    participant R as recoverTabAfterRenderProcessGone
    participant WC as WebContents

    E->>H: render-process-gone (crashed, exitCode)
    H->>H: tabForWebContents(wc) → tab
    alt tab not found
        H->>H: emitStatus()
    else tab found
        H->>R: recoverTabAfterRenderProcessGone(tab, details)
        R->>R: check renderProcessRecoveryTabs / isDestroyed → early return if true
        alt "reason == clean-exit"
            R->>R: notifyTabActivity + emitStatus
        else real crash
            R->>R: renderProcessRecoveryTabs.add(tab.id)
            R->>R: clearPendingRequests + pushNetworkDiagnostic
            R->>WC: loadURL(about:blank)
            WC-->>R: resolved
            R->>R: emitError(Recovered the tab to a blank page)
            R->>R: [finally] renderProcessRecoveryTabs.delete + notifyTabActivity + emitStatus
        end
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant E as Electron
    participant H as render-process-gone handler
    participant R as recoverTabAfterRenderProcessGone
    participant WC as WebContents

    E->>H: render-process-gone (crashed, exitCode)
    H->>H: tabForWebContents(wc) → tab
    alt tab not found
        H->>H: emitStatus()
    else tab found
        H->>R: recoverTabAfterRenderProcessGone(tab, details)
        R->>R: check renderProcessRecoveryTabs / isDestroyed → early return if true
        alt "reason == clean-exit"
            R->>R: notifyTabActivity + emitStatus
        else real crash
            R->>R: renderProcessRecoveryTabs.add(tab.id)
            R->>R: clearPendingRequests + pushNetworkDiagnostic
            R->>WC: loadURL(about:blank)
            WC-->>R: resolved
            R->>R: emitError(Recovered the tab to a blank page)
            R->>R: [finally] renderProcessRecoveryTabs.delete + notifyTabActivity + emitStatus
        end
    end
Loading

Reviews (5): Last reviewed commit: "Ignore untrusted popup web preferences" | Re-trigger Greptile

@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
ade Ignored Ignored Preview Jun 30, 2026 4:48pm

@arul28

arul28 commented Jun 30, 2026

Copy link
Copy Markdown
Owner Author

@copilot review but do not make fixes

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds async renderer crash recovery to builtInBrowserService: a per-tab guard set prevents duplicate recovery, and a new recoverTabAfterRenderProcessGone function clears pending requests, emits diagnostics/errors, and reloads to about:blank. The setWindowOpenHandler popup behavior changes from allow+createWindow to deny+explicit loadURL. Tests cover both new behaviors.

Built-in Browser Service

Layer / File(s) Summary
Crash recovery implementation and event wiring
apps/desktop/src/main/services/builtInBrowser/builtInBrowserService.ts
Adds a per-tab Set to guard duplicate concurrent recoveries, an async recoverTabAfterRenderProcessGone that handles clean-exit vs crashes differently (clearing requests, emitting error/status, recording diagnostics, optionally stopping inspect, reloading to about:blank), and updates the render-process-gone handler to invoke this function asynchronously with error logging.
Popup deny-and-load handler
apps/desktop/src/main/services/builtInBrowser/builtInBrowserService.ts
Replaces setWindowOpenHandler returning allow+createWindow with a deny action that directly calls loadURL on the target tab's webContents, emitting error and status events on failure.
Tests: crash recovery and popup interception
apps/desktop/src/main/services/builtInBrowser/builtInBrowserService.test.ts
Adds a test simulating a render-process-gone crash (reason crashed, exit code 133) that intercepts loadURL, asserts recovered tab URL/loading state, emitted error event contents, and logger.warn payload. Updates the popup test description and assertions to expect action: "deny", no createWindow, and the Google sign-in selection URL.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

desktop

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: fixing ADE browser link/popup crashes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ade/ade-browser-when-visit-linear-a73f0d7b

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mintlify

mintlify Bot commented Jun 30, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
ade-ac1c6011 🟢 Ready View Preview Jun 30, 2026, 3:46 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/desktop/src/main/services/builtInBrowser/builtInBrowserService.ts`:
- Around line 1167-1172: The builtInBrowserService logger currently records the
full browser URL in builtInBrowserService.ts, which can leak sensitive query
data; update the built_in_browser.render_process_gone payload to log a redacted
value or origin only instead of tab.webContents.getURL(), and keep the same
tabId/reason/exitCode fields. Make the change in the code path that uses
logger()?.warn and adjust the corresponding test expectation so it asserts the
sanitized URL shape rather than the full arbitrary URL.
- Around line 1065-1095: Recover the crashed WebContents instance directly
instead of re-reading tab.webContents after an await in builtInBrowserService’s
render-process recovery flow. Capture the current tab.webContents in a local
variable before calling stopInspectQuietly, then use that saved reference for
isDestroyed() checks and loadURL("about:blank") so attachWebview cannot swap in
a different WebContents and get blanked by mistake.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 03213df6-6b47-4c9d-a431-bdf199357525

📥 Commits

Reviewing files that changed from the base of the PR and between c059e1e and 8fc64dd.

📒 Files selected for processing (2)
  • apps/desktop/src/main/services/builtInBrowser/builtInBrowserService.test.ts
  • apps/desktop/src/main/services/builtInBrowser/builtInBrowserService.ts

Comment thread apps/desktop/src/main/services/builtInBrowser/builtInBrowserService.ts Outdated
Comment thread apps/desktop/src/main/services/builtInBrowser/builtInBrowserService.ts Outdated
@arul28

arul28 commented Jun 30, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 446f9a754a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (tab) {
const popupUrl = stringOrNull(url) ?? "about:blank";
// Own popup navigation; Electron cannot attach an existing WebContentsView as a native guest window.
void tab.webContents.loadURL(popupUrl).catch((error) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve POST data when opening popups

When the popup request comes from a <form target="_blank" method="post">, Electron passes the POST payload/referrer on the window-open details, but this manual loadURL(popupUrl) turns the new tab navigation into a plain GET. Before this change, returning allow with createWindow let Electron drive the original popup navigation into the returned WebContents, including the form body; with the new path, login/payment flows that submit popups by POST will open the right tab with the wrong request.

Useful? React with 👍 / 👎.

@arul28

arul28 commented Jun 30, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 830c2415d2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1139 to +1144
void tab.webContents.loadURL(popupUrl, popupLoadOptions).catch((error) => {
emitError(new Error(`Could not open browser popup: ${errorMessage(error)}`));
emitStatus();
});
}
return { action: "deny" };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve opener semantics for browser popups

When a page opens an OAuth/SSO popup with window.open or a target=_blank form and expects the returned WindowProxy/window.opener relationship, returning action: "deny" makes Chromium treat the popup as blocked while ADE separately loads the URL into an unrelated tab. That breaks popup-based providers such as Google sign-in flows that complete by posting back to or closing the opener; the previous createWindow path preserved that child-window relationship while still using ADE-managed webContents.

Useful? React with 👍 / 👎.

@arul28

arul28 commented Jun 30, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0a6c4c25a1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const createTabState = (): BrowserTabState => {
configureBrowserSession();
const browserWebPreferences = (overrides: Electron.WebPreferences = {}): Electron.WebPreferences => ({
...overrides,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep untrusted popup preferences out

When a visited page calls window.open(..., ..., "javascript=no,webviewTag=yes"), Electron passes those feature-derived values in options.webPreferences (docs), and this spread carries them into the ADE tab. That lets arbitrary page content change the popup tab's preferences, e.g. disabling JavaScript in an auth popup or enabling <webview> despite ADE's default of keeping it off; the previous createTabState() path ignored popup-supplied preferences. Please whitelist only the preferences ADE intentionally preserves, or drop these overrides entirely.

Useful? React with 👍 / 👎.

@arul28

arul28 commented Jun 30, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: e6a63a248c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@arul28 arul28 merged commit 3580a4b into main Jun 30, 2026
27 checks passed
@arul28 arul28 deleted the ade/ade-browser-when-visit-linear-a73f0d7b branch June 30, 2026 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant