Skip to content

Fix #171: SW navigation interception caused window-in-window after core update#175

Merged
epeicher merged 1 commit into
trunkfrom
fix/171-window-in-window-after-core-update
May 12, 2026
Merged

Fix #171: SW navigation interception caused window-in-window after core update#175
epeicher merged 1 commit into
trunkfrom
fix/171-window-in-window-after-core-update

Conversation

@epeicher
Copy link
Copy Markdown
Collaborator

@epeicher epeicher commented May 12, 2026

Summary

  • Service worker stops intercepting iframe navigations, fixing the window-in-window symptom from We updated a plugin from updates page then links opening in a new tab #171.
  • Root cause: when the SW called event.respondWith( fetch( req ) ) for an iframe load, Chrome forwarded the request with Sec-Fetch-Dest: empty instead of iframe. The Sec-Fetch fallback in desktop_mode_is_chromeless_request() only matches iframe, so the plain-admin to portal redirect fired inside the iframe and rendered the desktop shell on top of itself.
  • The user-visible trigger is Dashboard, Updates, Update to latest 7.1 nightly: WP core finishes the upgrade with window.location = about.php?updated from inside the iframe, exercising exactly that path. Any same-origin iframe navigation that lost the desktop_mode_chromeless=1 flag would hit the same bug.
  • Fix: limit the SW navigation handler to top-level navigations (req.destination === 'document'). The offline fallback is meaningful only for the top-level desktop shell page, so iframe-targeted offline support was not lost.

Before

After clicking Update to latest 7.1 nightly:

top:    /wp-admin/update-core.php?desktop_mode_portal=1
  iframe[1]:  src=update-core.php?desktop_mode_chromeless=1
              actual=about.php?desktop_mode_portal=1   <-- portal nested in chromeless iframe
    iframe[2]: update-core.php?action=do-core-upgrade&desktop_mode_chromeless=1

Visible result: a second WP admin chrome bar and a second WP Updates window rendered inside the original window.

After

top:    /wp-admin/update-core.php?desktop_mode_portal=1
  iframe[1]:  /wp-admin/about.php   <-- chromeless, no portal redirect, no nested shell

The About WordPress page loads cleanly inside the existing WP Updates window.

How to verify

  1. Open wp-admin/update-core.php inside Desktop Mode (running against a dev/nightly WP install).
  2. Click Update to latest 7.x nightly.
  3. Wait for completion.
  4. Confirm the iframe lands on the About page with no second admin chrome and no nested desktop shell.

Test plan

  • Manual: nightly core update flow no longer renders the desktop shell inside the chromeless iframe
  • Manual: PWA install + offline fallback still works for the top-level desktop shell page (visit /desktop-mode/ offline)
  • npm run lint
  • ./node_modules/.bin/tsc --noEmit
  • npm run test:js (131 files, 1115 tests pass)

Fixes #171

Open WordPress Playground Preview

The PWA service worker intercepted every same-origin wp-admin
navigation, including iframe loads, by calling `event.respondWith(
fetch( req ) )`. Chrome rewrites `Sec-Fetch-Dest` from `iframe` to
`empty` when a service worker forwards a navigation that way, so the
Sec-Fetch fallback in `desktop_mode_is_chromeless_request()` could not
recognise the request as iframe-bound. The plain-admin to portal
redirect then fired inside the chromeless iframe and rendered the
entire desktop shell inside an existing window.

The user-visible trigger was Dashboard, Updates, Update to latest 7.1
nightly: WP core finishes the upgrade with `window.location =
about.php?updated` from inside the iframe, hitting exactly that path.

Limit the SW navigation handler to top-level navigations
(`req.destination === 'document'`). Iframe navigations pass through to
the browser, which keeps `Sec-Fetch-Dest: iframe` intact, so the
chromeless detection works and no portal redirect fires. The offline
fallback is unaffected because it is meaningful only for the top-level
desktop shell page.
@epeicher epeicher enabled auto-merge (squash) May 12, 2026 10:47
@github-actions
Copy link
Copy Markdown

✅ WordPress Plugin Check Report

✅ Status: Passed

📊 Report

All checks passed! No errors or warnings found.


🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

@epeicher epeicher merged commit 0d83f39 into trunk May 12, 2026
5 checks passed
@epeicher epeicher deleted the fix/171-window-in-window-after-core-update branch May 12, 2026 10:50
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.

We updated a plugin from updates page then links opening in a new tab

1 participant