Skip to content

Fix window.open() and target=_blank not opening in new tab#693

Closed
lark1115 wants to merge 2 commits intomanaflow-ai:mainfrom
lark1115:fix-606-window-open-new-tab
Closed

Fix window.open() and target=_blank not opening in new tab#693
lark1115 wants to merge 2 commits intomanaflow-ai:mainfrom
lark1115:fix-606-window-open-new-tab

Conversation

@lark1115
Copy link
Contributor

@lark1115 lark1115 commented Feb 28, 2026

Summary

  • createWebViewWith is only called when the page requests a new window (window.open(), target=_blank). Always open in a new tab regardless of modifier keys/mouse button, since programmatic calls have no user gesture.
  • Fix insecure HTTP navigation path to treat targetFrame == nil as new-tab intent, consistent with the secure path.

Closes #606

Test plan

  • Open a page that calls window.open() — verify it opens in a new tab
  • Click a target=_blank link — verify it opens in a new tab
  • Cmd+click a regular link — verify it still opens in a new tab
  • Middle-click a regular link — verify it still opens in a new tab
  • Navigate to an insecure HTTP URL via window.open() — verify the insecure HTTP prompt shows with new-tab intent

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Navigation now consistently treats links without a target frame as “open in new tab”, avoiding unexpected in-place loads.
    • Blocked insecure navigations and new-window requests are opened in new tabs instead of loading in the current view, improving navigation predictability.
…ai#606)

When a page calls window.open() or uses target=_blank, createWebViewWith is
invoked regardless of user gesture. The old code checked modifier keys and
mouse button to decide new-tab vs in-place, which always chose in-place for
programmatic calls. Now createWebViewWith always opens a new tab, since it is
only called when the page explicitly requests a new window.

Also fix the insecure HTTP navigation path to treat targetFrame==nil as
new-tab intent, consistent with the secure path.

Closes manaflow-ai#606
@vercel
Copy link

vercel bot commented Feb 28, 2026

@lark1115 is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Feb 28, 2026

No actionable comments were generated in the recent review. ����

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 048ba3a and 0e548a8.

📒 Files selected for processing (1)
  • Sources/Panels/BrowserPanel.swift

📝 Walkthrough

Walkthrough

BrowserPanel navigation and UI-delegate behavior adjusted so nil navigationAction.targetFrame and createWebViewWith calls are treated as new-tab intents; blocked insecure navigations with nil targets open in a new tab rather than loading in place. window.open() now triggers opening URLs in a new tab via the existing openInNewTab handler.

Changes

Cohort / File(s) Summary
Browser Navigation & Window Handling
Sources/Panels/BrowserPanel.swift
Treat nil navigationAction.targetFrame as new-tab intent (OR with existing new-tab flag); when navigation would block insecure HTTP and target is nil, open URL in a new tab instead of loading in place; simplify webView(_:createWebViewWith:for:windowFeatures:) to always open new windows as new tabs via openInNewTab, removing previous conditional branches and loadInPlace paths.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant WebPage as Web Page
    participant WKWebView
    participant BrowserPanel
    participant OpenInNewTab as openInNewTab Handler

    User->>WebPage: Trigger link/navigation or window.open(url, '_blank')
    WebPage->>WKWebView: navigationAction / window.open call
    WKWebView->>BrowserPanel: decidePolicyFor / createWebViewWith delegate
    BrowserPanel->>BrowserPanel: Treat nil targetFrame or createWebViewWith as new-tab intent
    BrowserPanel->>OpenInNewTab: Call openInNewTab(url)
    OpenInNewTab->>OpenInNewTab: Create new tab / surface and load URL
    OpenInNewTab-->>User: New tab displays URL
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 I nudged a silent window to spring,
A tiny hop, now URLs sing,
window.open() leaps to a tab brand new,
No more quiet failures — hello view!
Hooray for tabs, and a carrot or two. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main fix: enabling window.open() and target=_blank to open in new tabs, which matches the primary objective of the changeset.
Linked Issues check ✅ Passed The PR directly addresses all requirements from issue #606: implements createWebViewWith delegate, ensures page-initiated new-window requests open in new tabs, and treats them as new-tab intent regardless of user gestures.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the objective of fixing window.open() and target=_blank behavior; no unrelated modifications are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
Sources/Panels/BrowserPanel.swift (1)

3243-3245: Recommended cleanup: remove now-dead conditional branches in createWebViewWith.

Since Line 3245 hard-codes shouldOpenInNewTab = true, the .currentTab and loadInPlace branches at Lines 3271 and 3284-3288 are unreachable. Simplifying this will make the intent clearer and reduce maintenance risk.

♻️ Proposed simplification
-        // createWebViewWith is only called when the page requests a new window,
-        // so always treat as new-tab intent regardless of modifiers/button.
-        let shouldOpenInNewTab = true
+        // createWebViewWith is only called when the page requests a new window,
+        // so always treat as new-tab intent regardless of modifiers/button.
+        let intent: BrowserInsecureHTTPNavigationIntent = .newTab
@@
-            if let requestNavigation {
-                let intent: BrowserInsecureHTTPNavigationIntent =
-                    shouldOpenInNewTab ? .newTab : .currentTab
+            if let requestNavigation {
 `#if` DEBUG
                 dlog(
                     "browser.nav.createWebView.action kind=requestNavigation intent=\(intent == .newTab ? "newTab" : "currentTab") " +
                     "url=\(url.absoluteString)"
                 )
 `#endif`
                 requestNavigation(navigationAction.request, intent)
-            } else if shouldOpenInNewTab {
+            } else {
 `#if` DEBUG
                 dlog("browser.nav.createWebView.action kind=openInNewTab url=\(url.absoluteString)")
 `#endif`
                 openInNewTab?(url)
-            } else {
-#if DEBUG
-                dlog("browser.nav.createWebView.action kind=loadInPlace url=\(url.absoluteString)")
-#endif
-                webView.load(navigationAction.request)
             }

Also applies to: 3270-3289

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Panels/BrowserPanel.swift` around lines 3243 - 3245, The conditional
branches in createWebViewWith that handle .currentTab and the loadInPlace path
are now dead because shouldOpenInNewTab is hard-coded true; remove the
unreachable .currentTab handling and the loadInPlace branch (including any
variables or comments only used for those cases) and simplify the function to
always follow the new-tab flow (use the new-tab helper/logic that currently runs
when shouldOpenInNewTab == true), keeping any shared setup and callbacks intact
and updating comments to reflect the always-new-tab intent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@Sources/Panels/BrowserPanel.swift`:
- Around line 3243-3245: The conditional branches in createWebViewWith that
handle .currentTab and the loadInPlace path are now dead because
shouldOpenInNewTab is hard-coded true; remove the unreachable .currentTab
handling and the loadInPlace branch (including any variables or comments only
used for those cases) and simplify the function to always follow the new-tab
flow (use the new-tab helper/logic that currently runs when shouldOpenInNewTab
== true), keeping any shared setup and callbacks intact and updating comments to
reflect the always-new-tab intent.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7143359 and 048ba3a.

📒 Files selected for processing (1)
  • Sources/Panels/BrowserPanel.swift
@greptile-apps
Copy link

greptile-apps bot commented Feb 28, 2026

Greptile Summary

Fixed window.open() and target=_blank links to consistently open in new tabs across all navigation paths. The changes ensure that programmatic window requests always create new tabs regardless of modifier keys, which aligns with standard web behavior.

Key changes:

  • createWebViewWith: Now always opens in new tab instead of checking for Cmd/middle-click modifiers
  • decidePolicyFor navigationAction: Added dedicated handler for targetFrame == nil to open in new tab
  • Insecure HTTP path: Now correctly treats targetFrame == nil as new-tab intent

The implementation correctly addresses the bug where target=_blank links would navigate in-place instead of opening new tabs.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk.
  • The changes are well-scoped, logically sound, and fix a clear bug in the navigation behavior. The logic consistently treats window.open() and target=_blank as new-tab requests across all code paths. Only minor style cleanup opportunity with unused variable.
  • No files require special attention.

Important Files Changed

Filename Overview
Sources/Panels/BrowserPanel.swift Fixes window.open() and target=_blank to always open in new tabs; ensures consistent behavior across navigation paths

Last reviewed commit: 048ba3a

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

for navigationAction: WKNavigationAction,
windowFeatures: WKWindowFeatures
) -> WKWebView? {
let hasRecentMiddleClickIntent = CmuxWebView.hasRecentMiddleClickIntent(for: webView)
Copy link

Choose a reason for hiding this comment

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

hasRecentMiddleClickIntent is computed but no longer used after setting shouldOpenInNewTab = true. Consider removing this line.

Address review feedback: remove unused hasRecentMiddleClickIntent,
shouldOpenInNewTab constant, and unreachable loadInPlace branch.
Simplify intent to always .newTab since createWebViewWith is only
called for page-initiated window requests.

Co-authored-by: Codex <noreply@openai.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
lawrencecchen added a commit that referenced this pull request Mar 2, 2026
Always open programmatic navigation (window.open, target=_blank) in a new tab.
Fix insecure HTTP path to treat nil targetFrame as new-tab intent.

Closes #606

Co-authored-by: lark <lark1115caster@gmail.com>
@lawrencecchen
Copy link
Contributor

Merged manually after rebasing to resolve conflicts. Thanks @lark1115!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants