Open links in the browser for every click gesture, not just a plain click - #358
amitraj2203 wants to merge 4 commits into
Conversation
The site links each cancel their own navigation in an onClick handler. A middle click fires auxclick, which a click handler never sees, so Chromium's "open in a new window" default ran and the site loaded inside a bare app window with no address bar and no way back. Refuse navigation and window creation once for the app window instead, and hand the address to the system browser. Every link is covered, including ones added later, and the address goes out through the same external-url.js gate the renderer already uses. Fixes WordPress#284
Two findings from the review pass on this branch. The window guard only intercepted http and https, so anything else was left to navigate the main window. That window is the one with the preload bridge attached, and it renders content the app does not author — captured email bodies among it — where a link can point at a local path or at one relative to the app's own file: origin. It now refuses every navigation except a reload, which is the one case that has to keep working; a plain deny breaks reloading the window. The onFailed reporter also only covered the link path. openExternalUrl ignored it and let a rejecting openExternal propagate out of the url:open handler, where none of the renderer's 23 call sites catches anything — so an ordinary click on an address the OS cannot open was still a link that did nothing with nothing in the log. Reporting moved into openExternalUrl, which is where both paths meet. Tests for both fail on the previous code.
Both were out of scope for WordPress#284. The navigation hole they closed — the app window following a file: or relative link out of its own page — is on trunk already and is not something this fix introduced, and the missing failure log on the url:open path is a gap in external-url.js rather than in the link handling. Neither belongs in a PR that fixes one reported bug. Both are worth doing on their own; noted in the PR description so they are not lost.
Trunk moved every test into `tests/unit/` in WordPress#377, and this branch predates that, so the merge raises a `CONFLICT (file location)` for the new `test/window-links.test.cjs`. Git relocates the file on its own; it does not rewrite what is inside it. Accepting the move alone leaves `require('../src/window-links.js')` pointing one directory too high, and the test throws `MODULE_NOT_FOUND` the first time it runs. This resolution accepts the relocation and takes the require to `../../src/window-links.js`, the depth every other file in `tests/unit/` already uses. --- Generated with the help of Claude Code, https://code.claude.com Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
@amitraj2203 thank you for this PR. You'll notice I just merged |
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
489d8b2 to
409e956
Compare
|
Thanks for this, the approach is right and I'd like to get it in. Trunk moved under the branch, so two imports no longer exist. The merge is clean but both end up
With those two swapped and trunk merged in, lint and the unit suite pass for me. Not blocking: And an apology: I pushed the two fixes to your branch before thinking better of it, then force-pushed it back to |
## Why An agent found two rebase breakages on an external contributor's pull request (#358): trunk had removed two exports the branch still imported. The repository allows maintainer edits on that branch and each fix was one line, so the agent pushed a merge and a fix commit to the contributor's fork. Nothing in `AGENTS.md` said not to. That is the author's call, not the agent's. A contributor's branch is theirs: what lands on it, and when it merges, is decided by whoever opened the pull request. The right move on a pull request the person you work for did not open is a review with the findings written down. ## What changes One section in `AGENTS.md`, under "Before opening a pull request": a pull request you did not open belongs to its author. No pushes, rebases, description edits or merges on it, whatever the branch permissions say and however small the fix. Reviewing it and leaving findings, with a diff where that helps, is what an agent may do. If the author is unresponsive and the work is urgent, the agent says so and lets the person decide how to reach them. ## How to test this Platforms: any. Documentation only, nothing runs. **Starting state:** any checkout of this branch. 1. Open `AGENTS.md` and find the section "A pull request you did not open belongs to its author". It sits between the CodeRabbit paragraphs and "The pull request description follows the template". 2. Read it as an agent about to act on a pull request someone else opened. Expected: it names every action that is off limits (push, rebase, update, edit description, merge) and the one that is allowed (review and leave findings). **What must not have happened:** no other line of `AGENTS.md` changed. `git diff trunk --stat` lists one file with six added lines. ## Risks and limitations None to the app. The rule constrains agents only; a human maintainer keeps whatever latitude the repository gives them. ## Related Prompted by #358, where the rule was broken before it existed. --- <details> <summary>Review outcome (required — see AGENTS.md)</summary> Documentation change, six added lines in `AGENTS.md`, no code. Read once against the surrounding sections for tone and placement; `npm run lint` does not cover Markdown. Nothing to fix, nothing deferred. </details> <details> <summary>Screenshots or recording</summary> Nothing on screen changes. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_0123opUnXoxs1CAN7YQ7q8KU Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Why
Middle-clicking the site link, wp-admin or Adminer opens the site inside an app window with no address bar and no back button. Only closing it gets you out. See #284.
Each link cancels its own navigation in
onClick. A middle click firesauxclick, which a click handler never sees, so Chromium's "open in a new window" default runs.What changes
src/window-links.jsdenies window creation and http/https navigation on the app window, and sends the address to the system browser instead. One place, so every link is covered including new ones.file:navigation is left alone on purpose. The app's own page is afile:URL and blocking it stopslocation.reload().The links keep their
onClickhandlers. They're redundant now, but removing seven of them is a separate change.How to test this
Platforms: any. Needs a mouse with a clickable scroll wheel; macOS trackpads have no middle button.
Starting state: a site that has finished setting up.
What must not have happened:
For the old behaviour, check out
trunkand repeat steps 1-3.Risks and limitations
Cmd/Ctrl+click is not affected by this bug, though #284 says it is. Chromium sends it as a normal
click, so the existingpreventDefault()catches it. I tested all four gestures on trunk: only middle click reproduces. Worth knowing before testing, or the gesture the issue names looks like it disproves the fix.The review found three separate bugs sitting next to this code. They're listed below and left alone.
Related
Fixes #284
Review outcome (required — see AGENTS.md)
Lint clean.
npm testandnpm run test:electronboth 1034 pass.Fixed: an empty
catchin the new module swallowed a failedopenExternal.Not fixed, all pre-existing and none caused by this change:
file:or page-relative link. One route is the email body atindex.jsx:5551, rendered withdangerouslySetInnerHTML. Trunk has no guard on this window at all. If you fix it, note that blocking every navigation breakslocation.reload(), so the exemption has to be the current URL.openExternalUrlhas no way to report a failed open, and lets the rejection propagate into a renderer that catches nothing at 23 call sites. So a click on an address the OS can't open is a link that did nothing, with nothing in the log.openLinksExternallycall and the suite stays green.test/ipc-wiring.test.cjscan't reachcreateWindow:app.whenReady()is stubbed as a promise that never settles andmain.jshas no exports.I had fixed the first two, then reverted them as out of scope, which is why there's a revert in the history. The code matches the first commit.
Screenshots
Nothing new appears on screen; the fix is a window that stops appearing. I have a screenshot of the bug on trunk if it's useful.