Skip to content

feat(paywalls): add web_view message model and parsing (PWENG-98)#3654

Draft
alexrepty wants to merge 1 commit into
alexrepty/paywalls-web-view-value-typesfrom
alexrepty/paywalls-web-view-message-model
Draft

feat(paywalls): add web_view message model and parsing (PWENG-98)#3654
alexrepty wants to merge 1 commit into
alexrepty/paywalls-web-view-value-typesfrom
alexrepty/paywalls-web-view-message-model

Conversation

@alexrepty

@alexrepty alexrepty commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Checklist

  • If applicable, unit tests
  • If applicable, create follow-up issues for purchases-ios and hybrids

Motivation

Defines the inbound message model and parsing for web_view ↔ native communication, so messages from web content are validated before reaching app code.

Part of PWENG-98.

Description

  • Adds the public PaywallWebViewMessage plus the PaywallWebViewMessageHandler / PaywallWebViewController surface.
  • Adds the internal WebViewMessageType and WebViewMessageParser: validates the flat envelope, enforces payload size / nesting-depth caps, requires the component_id to match the rendered component, and validates per-type fields (rc:step-loaded, rc:step-complete, rc:request-variables, rc:error); unknown types are dropped.
  • Pure data/logic — no live WebView bridge yet.
  • Tested by WebViewMessageParserTest.

iOS parity: mirrors purchases-ios (web-view-bridge-wiring).
Stack (merge bottom-up): schema → rendering → CSP → value types → message model → variables provider → JS bridge → wiring.


Note

Low Risk
Additive public API and internal validation logic with no runtime WebView integration or purchase flow changes in this PR.

Overview
Introduces the public surface for Paywalls V2 web_view ↔ native messaging: PaywallWebViewMessage, PaywallWebViewMessageHandler, and PaywallWebViewController (reply via postVariables / postMessage using PaywallWebViewValue). App code will wire the handler through PaywallOptions.Builder.setWebViewMessageHandler in a follow-up; the SDK does not auto-dismiss or purchase on rc:step-complete.

Adds internal parsing via WebViewMessageParser: validates the flat postMessage envelope, caps payload size (64KB) and nesting depth, requires component_id to match the rendered web view, handles rc:step-loaded, rc:step-complete, rc:request-variables, and rc:error, and drops unknown types and invalid payloads. api.txt is updated for the new types.

No live WebView bridge in this PR—data and validation only, covered by WebViewMessageParserTest.

Reviewed by Cursor Bugbot for commit a1cc787. Bugbot is set up for automated code reviews on this repo. Configure here.

@alexrepty alexrepty changed the title feat(paywalls): add web_view bidirectional messaging feat(paywalls): add web_view message types and parsing Jun 25, 2026
@alexrepty alexrepty changed the base branch from alexrepty/paywalls-web-view-csp to graphite-base/3654 June 26, 2026 10:49
@alexrepty alexrepty force-pushed the alexrepty/paywalls-web-view-message-model branch from 21899a1 to 8558b7d Compare June 26, 2026 10:49
@alexrepty alexrepty force-pushed the graphite-base/3654 branch from 66c0ccb to 3e62e49 Compare June 26, 2026 10:49
@alexrepty alexrepty changed the base branch from graphite-base/3654 to alexrepty/paywalls-web-view-value-types June 26, 2026 10:49
@alexrepty alexrepty changed the title feat(paywalls): add web_view message types and parsing feat(paywalls): add web_view message model and parsing Jun 26, 2026
@alexrepty alexrepty force-pushed the alexrepty/paywalls-web-view-message-model branch from 8558b7d to 2790f47 Compare June 26, 2026 14:20
@alexrepty alexrepty force-pushed the alexrepty/paywalls-web-view-value-types branch 2 times, most recently from 2716386 to 27793a8 Compare June 26, 2026 14:26
@alexrepty alexrepty force-pushed the alexrepty/paywalls-web-view-message-model branch 4 times, most recently from b70692b to c8ba63e Compare June 29, 2026 09:58
@alexrepty alexrepty changed the title feat(paywalls): add web_view message model and parsing feat(paywalls): add web_view message model and parsing (PWENG-98) Jun 29, 2026
@alexrepty alexrepty force-pushed the alexrepty/paywalls-web-view-message-model branch from c8ba63e to 5525f6c Compare June 29, 2026 13:58
@alexrepty alexrepty force-pushed the alexrepty/paywalls-web-view-value-types branch from 27793a8 to 81453b8 Compare June 29, 2026 13:58
@alexrepty alexrepty force-pushed the alexrepty/paywalls-web-view-message-model branch from 5525f6c to d7f8fa1 Compare June 29, 2026 14:14
@alexrepty alexrepty force-pushed the alexrepty/paywalls-web-view-value-types branch from 81453b8 to 5505947 Compare June 29, 2026 14:14
@alexrepty alexrepty marked this pull request as ready for review June 29, 2026 14:42
@alexrepty alexrepty requested a review from a team as a code owner June 29, 2026 14:42
@alexrepty alexrepty force-pushed the alexrepty/paywalls-web-view-message-model branch from d7f8fa1 to 86b7b79 Compare June 30, 2026 07:44
@alexrepty alexrepty force-pushed the alexrepty/paywalls-web-view-value-types branch from 5505947 to 74610d7 Compare June 30, 2026 07:44
@alexrepty alexrepty force-pushed the alexrepty/paywalls-web-view-value-types branch from 74610d7 to a42c874 Compare June 30, 2026 08:43
@alexrepty alexrepty force-pushed the alexrepty/paywalls-web-view-message-model branch from 86b7b79 to cdc1156 Compare June 30, 2026 08:43

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit cdc1156. Configure here.

fun parse(rawJson: String, expectedComponentId: String): PaywallWebViewMessage? {
if (rawJson.toByteArray(Charsets.UTF_8).size > MAX_PAYLOAD_BYTES) {
Logger.w("Dropping web view message: payload exceeds $MAX_PAYLOAD_BYTES bytes.")
return null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Payload check unbounded allocation

Medium Severity

The 64KB payload cap is enforced by calling toByteArray(UTF_8) on the entire raw JSON string first. A hostile or buggy web view can send a very large string and trigger a huge allocation (and possible OOM) before the message is dropped, even though the limit is meant to bound work.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit cdc1156. Configure here.

@AlvaroBrey AlvaroBrey force-pushed the alexrepty/paywalls-web-view-message-model branch from cdc1156 to 7c75281 Compare July 6, 2026 08:12
@AlvaroBrey AlvaroBrey force-pushed the alexrepty/paywalls-web-view-value-types branch from a42c874 to 7aceb78 Compare July 6, 2026 08:12
@AlvaroBrey AlvaroBrey self-assigned this Jul 6, 2026
Adds a bidirectional JS<->native bridge for the Paywalls V2 `web_view` component: a document-start `window.RevenueCatWebView` shim, message parsing/validation (`WebViewMessageParser`, `WebViewMessageType`), the public `PaywallWebViewMessage` / `PaywallWebViewValue` / `PaywallWebViewMessageHandler` / `PaywallWebViewController` surface, and an SDK-managed variables provider (locale, color scheme, custom variables). Apps opt in via `PaywallOptions.setWebViewMessageHandler(...)`, threaded through `PaywallState` / `OfferingToStateMapper`.

Regenerates ui/revenuecatui/api.txt for the new public API.

Recommended labels: pr:feat, pr:RevenueCatUI, feat:Paywalls_V2
@AlvaroBrey AlvaroBrey force-pushed the alexrepty/paywalls-web-view-value-types branch from 7aceb78 to cf8d3d0 Compare July 6, 2026 13:57
@AlvaroBrey AlvaroBrey force-pushed the alexrepty/paywalls-web-view-message-model branch from 7c75281 to a1cc787 Compare July 6, 2026 13:57
@AlvaroBrey AlvaroBrey marked this pull request as draft July 6, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants