Skip to content

SDK-762 detect WebKit inside in-app iframes - #588

Merged
joaodordio merged 3 commits into
mainfrom
SDK-762-ios-chrome-inapp-dismiss
Sep 28, 2026
Merged

joaodordio merged 3 commits into
mainfrom
SDK-762-ios-chrome-inapp-dismiss

Conversation

@joaodordio

@joaodordio joaodordio commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

📝 Summary

Chrome on iOS can now dismiss in-browser messages. The SDK was treating that browser as desktop Chrome.

🎟️ Jira Ticket: SDK-762

📖 Description

Chrome on iOS identifies as CriOS, so the Safari user-agent check in getInAppMessages sent it down the desktop path. The close button and click handlers were bound inside an iframe sandboxed without allow-scripts. WebKit does not run those handlers, so the message could not be closed. With isRequiredToDismissMessage or a full screen layout, no gesture worked. Tapping a template iterable://dismiss link raises Chrome's "trying to open another application" dialog and does not dismiss.

Real Safari still uses the user-agent result, so we do not dispatch a probe event there. Every other browser gets one click dispatched inside the iframe. If the listener does not run, we use the existing Safari path: close button on the parent page, and tap outside still dismisses when isRequiredToDismissMessage is set.

This does not make iterable://dismiss or action:// work on WebKit. Those links stay broken on Safari too. It also does not enable JavaScript inside the message iframe. That remains blocked on backend HTML sanitization (MOB-8729).

A docs PR is needed. The in-browser docs say the SDK does not generate a close button in Safari, and they do not mention Chrome on iOS.

🧪 How to test?

Jest: src/inapp/tests/inapp.test.ts (45 passing, including webkitBlocksIframeHandlers).

Playwright, published 2.3.2 versus this build, 60 runs (Chrome iOS, Safari iOS, Firefox iOS, Instagram in-app, Android Chrome; default, dismiss required, full screen; SDK close button, template dismiss link, tap outside):

  • Chrome on iOS and Instagram in-app: SDK close button moves to the parent page and dismisses, including when dismiss is required and on full screen. Tap outside dismisses when dismiss is required. Template iterable://dismiss still does not dismiss.
  • Safari, Firefox on iOS, and Android Chrome: no change.

On an iPhone running iOS 27, against 2.3.2: Chrome shows the app dialog on the template dismiss link in every layout, and the SDK close button does nothing. Safari says JavaScript is not enabled on that same link, and the SDK close button works. The fixed build has not been rechecked on a physical phone yet.

🧾 Changelog

Added under Unreleased in CHANGELOG.md.

📹 Loom recording if applicable

None.

🐞 Github Issues solved

None.

📚 Docs PR if applicable

Not opened yet. The Safari close-button limitation in the in-browser docs is inaccurate and should mention Chrome on iOS. Flagging that a docs PR is required.

…hrome user agent.

Chrome on iOS was treated as desktop Chrome, so close controls were bound inside a sandboxed iframe where WebKit drops them.
@joaodordio
joaodordio requested a review from a team as a code owner September 25, 2026 00:12
@codecov-commenter

codecov-commenter commented Sep 25, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.32%. Comparing base (600eef0) to head (d1b40fa).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #588      +/-   ##
==========================================
+ Coverage   74.43%   75.32%   +0.89%     
==========================================
  Files          57       57              
  Lines        2742     2752      +10     
  Branches      821      822       +1     
==========================================
+ Hits         2041     2073      +32     
+ Misses        700      639      -61     
- Partials        1       40      +39     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Dropping the WebKit probe wiring would leave the close button inside the iframe and this test would fail.

@rtlsilva rtlsilva left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking findings, approved.

expect(document.getElementById('iterable-iframe')).toBe(null);
});

it('puts the SDK close button on the parent page when Chrome on iOS cannot bind iframe handlers', async () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This Jest test forces detection, but no WebKit E2E test exercises the CriOS/non-Safari path.

This test replaces addEventListener with a no-op, directly forcing the detector's blocked result, so it only proves that the parent-control branch works after the detector returns true; it does not verify that a sandboxed WebKit iframe actually produces that result.

Since the fix depends entirely on this engine-specific behavior, should we add a Playwright WebKit regression test with a CriOS/non-Safari user agent and assert that the controls are placed on the parent page?

The Jest probe is stubbed because jsdom runs iframe listeners. This loads the built bundle in WebKit with a CriOS user agent and checks the close button is on the parent page.
@joaodordio
joaodordio merged commit ffd4eac into main Sep 28, 2026
8 checks passed
@joaodordio
joaodordio deleted the SDK-762-ios-chrome-inapp-dismiss branch September 28, 2026 23:01
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.

3 participants