Conversation
When window.open() fails (common on mobile browsers like Firefox Mobile), fall back to navigating the current tab with scraped data encoded as JSON in a _data URL parameter. The PHP backend parses and sanitizes this inline data through the same limit_* methods used for POST data, and the React app skips the postMessage listener when inline data mode is active. Arrays are trimmed (5 images, 3 embeds) in the fallback path to keep URL length manageable. See #50
There was a problem hiding this comment.
Pull request overview
This PR improves Press This bookmarklet compatibility on mobile browsers where window.open() commonly fails by introducing a current-tab navigation fallback that carries scraped data inline.
Changes:
- Add a popup-blocked fallback in the bookmarklet that navigates the current tab and passes scraped data via a
_dataJSON URL parameter (with some array trimming). - Extend the PHP bootstrap to parse/merge
_datausing existinglimit_*sanitizers and expose aninlineDataModeflag to the React app. - Update the React app to skip the postMessage listener when inline data mode is active, and add tests for the new behavior.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
assets/bookmarklet.js |
Adds popup-blocked fallback to current-tab navigation with _data JSON payload and trims large arrays. |
assets/bookmarklet.min.js |
Regenerates minified bookmarklet to include the fallback behavior. |
class-wp-press-this-plugin.php |
Parses _data, merges sanitized inline values into $data, tracks inlineDataMode, and adjusts proxy/content generation behavior. |
src/App.js |
Skips postMessage listening when inlineDataMode is enabled. |
tests/bookmarklet/bookmarklet.test.js |
Adds assertions that fallback navigation and trimming logic exist in the bookmarklet source. |
tests/php/test-integration.php |
Adds integration tests covering _data parsing, precedence rules, and invalid JSON handling. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Respect enable_press_this_media_discovery filter for inline data path - Build minimal fallback payload (only used meta keys, canonical/shortlink) with 7500-char URL cap to avoid browser truncation - Override pm=0 in fallback URL so app doesn't wait for postMessage - Strip _data param from browser history via replaceState Fixes #50
There was a problem hiding this comment.
Pull request overview
This PR adds a mobile-friendly fallback for the Press This bookmarklet when window.open() is blocked (common on mobile browsers), by encoding a minimal scraped payload into a _data URL param that the PHP backend can merge and the React app can handle without waiting for postMessage.
Changes:
- Add bookmarklet fallback path that navigates the current tab with
_dataJSON and enforces a URL-length budget. - Add PHP support to parse/merge/sanitize
_datavia existinglimit_*/processing paths and exposeinlineDataModeto the client. - Update the React app to skip
postMessagehandling in inline mode and to strip_datafrom browser history; add tests for the new paths.
Reviewed changes
Copilot reviewed 5 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
assets/bookmarklet.js |
Adds popup-blocked fallback to current-tab navigation with _data JSON payload. |
assets/bookmarklet.min.js |
Rebuilt/minified bookmarklet including the fallback logic. |
class-wp-press-this-plugin.php |
Parses _data, sanitizes/merges into the normal data structure, and exposes inlineDataMode. |
src/App.js |
Strips _data from history and skips postMessage listener in inline mode. |
tests/bookmarklet/bookmarklet.test.js |
Adds assertions for fallback behavior and URL-length logic presence. |
tests/php/test-integration.php |
Adds integration tests for _data parsing, precedence, and invalid JSON handling. |
package-lock.json |
Updates the typescript entry metadata (devOptional → dev). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
When window.open() is blocked on mobile browsers, the bookmarklet now stores scraped data in window.name instead of encoding it as JSON in a _data URL parameter. This solves two problems: - Confidentiality: scraped content no longer leaks into browser history, server access logs, or session restore - URL length: window.name has no practical size limit, eliminating the need for progressive payload reduction and silent truncation The React app reads window.name on load (signaled by &wn=1), clears it immediately, and processes data through the same pipeline as the postMessage path. The shared processScrapedData callback is extracted from the postMessage handler for reuse. Removes ~90 lines of PHP inline data parsing code that is no longer needed since data processing happens entirely client-side.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 7 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Set window_name_mode via single assignment (defensive against multiple merge_or_fetch_data calls) - Restore $_SERVER['REQUEST_METHOD'] in test helper to avoid state leaks - Soften window.name size limit claim in bookmarklet comment - Fix stale docblock on window_name_mode property
An inline script in the PHP template now reads window.name into window.__ptWindowName and clears window.name immediately, before any admin hook scripts execute. The React app reads from the stashed copy instead of window.name directly. This narrows the exposure window for attacker-prefilled window.name payloads and prevents same-origin admin scripts from accessing scraped data.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 7 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 7 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Only navigate with &wn=1 when JSON serialization succeeds, preventing the app from parsing stale or attacker-controlled window.name data. Add event.origin check on the postMessage listener and a 1 MB size cap before parsing window.name.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 7 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The bookmarklet controls what goes into window.name, so a size cap on the receiving end is redundant.
Read back window.name after writing to detect silent browser truncation. If the payload didn't survive intact, navigate without &wn=1 so the user gets the normal URL flow instead of a silently empty editor.
Summary
window.open()fails (common on mobile browsers like Firefox Mobile/Fenix), falls back to storing scraped data inwindow.nameand navigating the current tabwindow.namepersists across cross-origin navigations within the same tab, has no size limit, and keeps data out of URLs (avoiding leaks to browser history, server logs, and session restore)&wn=1and sets awindowNameModeflag — no server-side data parsing neededwindow.nameon load, clears it immediately, and processes data through a sharedprocessScrapedDatacallback (same pipeline as the postMessage path)wnparam stripped from the URL bar viareplaceStateprocessScrapedDatacallback is extracted from the postMessage handler for reuse by both transport pathsWhy window.name instead of URL parameters?
The previous approach encoded scraped data as JSON in a
_dataURL parameter. This had two problems:window.nameeliminates both issues — it lives only in tab memory (no logs, no history) and supports multi-MB payloads.Why not POST form / sessionStorage / REST stash?
Compatibility note
PR #90 (HTML selection capture) touches the same files. When both merge, the second will need standard merge conflict resolution and a
bookmarklet.min.jsrebuild. Thesel_htmlfield is automatically included in the fullscrapedDatapayload sent viawindow.name— no additional field mapping is needed.Test plan
popup = nullin bookmarklet.js, verify current-tab navigation loads editor with scraped content from window.namewnparam is stripped from the URL bar after loadFixes #50