Skip to content

Fix bookmarklet on mobile browsers#100

Draft
kraftbj wants to merge 3 commits intotrunkfrom
investigate-issue-50
Draft

Fix bookmarklet on mobile browsers#100
kraftbj wants to merge 3 commits intotrunkfrom
investigate-issue-50

Conversation

@kraftbj
Copy link
Collaborator

@kraftbj kraftbj commented Mar 16, 2026

Summary

  • When window.open() fails (common on mobile browsers like Firefox Mobile/Fenix), falls back to navigating the current tab with scraped data encoded as JSON in a _data URL parameter
  • PHP backend parses and sanitizes inline data through the same limit_* methods used for POST data
  • React app skips the postMessage listener when inline data mode is active
  • Fallback builds a minimal payload (only the meta keys Press This actually uses, canonical/shortlink only) with a 7500-char URL cap to avoid browser/server truncation
  • pm flag overridden to 0 in fallback URL so the app doesn't wait for postMessage data that will never arrive
  • _data param stripped from browser history via replaceState to avoid leaking scraped content
  • Inline data path respects the enable_press_this_media_discovery filter, matching the POST data path

Compatibility note

PR #90 (HTML selection capture) touches the same files. When both merge, the second will need:

  1. Standard merge conflict resolution (edits are in different sections)
  2. Regenerate bookmarklet.min.js
  3. Add sel_html to the inline data field map in PHP so HTML selections work in the fallback path too

Test plan

  • Existing tests pass (258 PHP, 285 JS)
  • New tests: popup-blocked fallback path, minimal payload construction, URL length cap, pm flag override, _data param parsing, non-override of existing params, invalid JSON handling
  • Manual: force popup = null in bookmarklet.js, verify current-tab navigation with _data param loads editor with scraped content
  • Manual: verify normal popup path still works unchanged on desktop
  • Manual: verify _data is stripped from the URL bar after the app loads in fallback mode

Fixes #50

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
@kraftbj kraftbj added this to the 2.1.0 milestone Mar 16, 2026
@kraftbj kraftbj requested a review from Copilot March 16, 2026 23:02
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 _data JSON URL parameter (with some array trimming).
  • Extend the PHP bootstrap to parse/merge _data using existing limit_* sanitizers and expose an inlineDataMode flag 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.

Comment on lines +801 to +829
// Process media arrays.
foreach ( array( '_images', '_embeds', '_og_video' ) as $type ) {
if ( empty( $inline_data[ $type ] ) || ! is_array( $inline_data[ $type ] ) ) {
continue;
}

if ( ! isset( $data[ $type ] ) ) {
$data[ $type ] = array();
}

$items = $this->limit_array( $inline_data[ $type ] );

foreach ( $items as $value ) {
if ( '_images' === $type ) {
$value = $this->limit_img( $value );
} else {
$value = $this->limit_embed( $value );
}

if ( ! empty( $value ) && ! in_array( $value, $data[ $type ], true ) ) {
if ( '_og_video' === $type ) {
if ( ! isset( $data['_embeds'] ) ) {
$data['_embeds'] = array();
}
if ( ! in_array( $value, $data['_embeds'], true ) ) {
$data['_embeds'][] = $value;
}
} else {
$data[ $type ][] = $value;
Comment on lines +873 to +875
$this->inline_data_mode = true;
}
}
Comment on lines +347 to +357
// Popup blocked (common on mobile browsers). Navigate current window with inline data.
// Trim arrays to limit URL length for the fallback path.
if ( scrapedData._images && scrapedData._images.length > 5 ) {
scrapedData._images = scrapedData._images.slice( 0, 5 );
}
if ( scrapedData._embeds && scrapedData._embeds.length > 3 ) {
scrapedData._embeds = scrapedData._embeds.slice( 0, 3 );
}

top.location.href = pt_url + '&_data=' + encURI( JSON.stringify( scrapedData ) );
}
Comment on lines +185 to +190
// Skip if inline data mode — data was passed via URL, not postMessage.
if (
! data.postMessageMode ||
data.inlineDataMode ||
postMessageReceived
) {
kraftbj added 2 commits March 16, 2026 18:55
- 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
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.

Fix bookmarklet on mobile browsers, eg Firefox

2 participants