feat(paywalls): render web_view component (PWENG-98)#3651
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
6b4ecb1 to
9e93b6c
Compare
61039df to
38f5302
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## alexrepty/paywalls-web-view-schema #3651 +/- ##
===================================================================
Coverage 80.48% 80.48%
===================================================================
Files 404 404
Lines 16728 16728
Branches 2389 2389
===================================================================
Hits 13464 13464
Misses 2322 2322
Partials 942 942 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
38f5302 to
6c73e7c
Compare
9e93b6c to
b911095
Compare
6c73e7c to
71e76e1
Compare
b911095 to
dc40011
Compare
88cb259 to
fd0371b
Compare
dc40011 to
003b8ee
Compare
003b8ee to
fa1fcdf
Compare
fd0371b to
bc0f4e0
Compare
| dateLocale = locale, | ||
| customVariables = customVariables, | ||
| defaultCustomVariables = defaultCustomVariables, | ||
| ) |
There was a problem hiding this comment.
WebView URL variable resolution incomplete
Medium Severity
The PR resolves web_view URL templates against paywall variables, but WebViewUrlResolver only passes custom variables and locale into VariableProcessorV2, omitting selected package, subscription option, variableDataProvider, currency locale, and date context. createWebViewComponentStyle also does not capture enclosing rcPackage like text/video components. WebViewComponentView caches the URL in remember keyed by template, state identity, and locale, so it does not refresh when the user changes the selected package.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit bc0f4e0. Configure here.
📸 Snapshot Test593 unchanged
🛸 Powered by Emerge Tools |
fa1fcdf to
a46325f
Compare
bc0f4e0 to
2634d3b
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ 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 2634d3b. Configure here.
| // URL. We deliberately do NOT reload on every recomposition: in-page navigation changes WebView.url, | ||
| // and reloading whenever it differs from resolvedUrl would reset a multi-step web flow. The WebView | ||
| // is only recreated when the SDK-resolved URL itself changes (e.g. a locale-dependent template). | ||
| key(resolvedUrl) { |
There was a problem hiding this comment.
java.net.URL as Compose key triggers blocking DNS
Medium Severity
key(resolvedUrl) uses a java.net.URL object as a Compose key. URL.equals() and URL.hashCode() perform blocking DNS resolution on the calling thread. Compose's key() calls equals() on every recomposition to check whether the composition identity changed, causing a synchronous network operation on the main/UI thread. This is a well-known Java pitfall flagged by Google's ErrorProne checker (URLEqualsHashCode). Using resolvedUrl.toString() as the key (or returning a URI/String from WebViewUrlResolver) avoids the blocking call entirely.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 2634d3b. Configure here.
Adds the Compose rendering path for the Paywalls V2 `web_view` component: a `WebView`-backed `WebViewComponentView`, the `WebViewComponentStyle`, the `StyleFactory` mapping, `ComponentView` dispatch, and `WebViewUrlResolver` (template resolution + HTTPS/host validation). When the URL is missing or invalid the component renders its fallback stack. No CSP, messaging, or pre-warming yet. Recommended labels: pr:other, pr:RevenueCatUI, feat:Paywalls_V2
2634d3b to
4fb9844
Compare
a46325f to
40615bf
Compare



Checklist
purchases-iosand hybridsMotivation
With the
web_viewschema in place, the component needs to actually render its hosted content in a Paywalls V2 paywall.Part of PWENG-98.
Description
WebViewComponentView(aWebViewhosted viaAndroidView),WebViewComponentStyle, theStyleFactorymapping, andComponentViewdispatch.WebViewUrlResolver: resolves the URL template against paywall variables natively, then validates it is an HTTPS URL with a host. If it does not resolve, the component renders nothing (availability is gated by SDK version on the frontend).StyleFactoryTestsandWebViewUrlResolverTest.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
Medium Risk
Introduces WebView with JavaScript enabled and external URL loading in the paywall surface; mitigations are HTTPS-only validation and navigation blocking, but CSP/bridge are still out of scope for this PR.
Overview
Paywalls V2
web_viewcomponents now render hosted HTTPS content instead of being dropped during style creation.Style pipeline:
StyleFactorymapsWebViewComponenttoWebViewComponentStyle(URL template, visibility, size), andComponentViewdispatches to the new composable.Rendering:
WebViewComponentViewhosts anAndroidViewWebViewthat resolves the URL viaWebViewUrlResolver(paywall variables + locale), accepts only HTTPS URLs with a host, and renders nothing on failure. The WebView is keyed on the resolved URL so in-page navigation is not reset on recomposition; locale changes still refresh locale-dependent templates. Settings restrict file/content access, disallow mixed content, enable JS/DOM storage, and block non-HTTPS navigations inshouldOverrideUrlLoading.Tests:
StyleFactoryTestsfor style mapping andWebViewUrlResolverTestfor URL resolution and rejection of non-HTTPS/malformed URLs.Reviewed by Cursor Bugbot for commit 4fb9844. Bugbot is set up for automated code reviews on this repo. Configure here.