[Android] Replace JavascriptInterface with WebMessageListener#424
[Android] Replace JavascriptInterface with WebMessageListener#424kiftio wants to merge 1 commit into
Conversation
d97376b to
4f9359a
Compare
Package Size
Android file breakdown
Measured from the PR base SHA and PR head SHA. The file breakdown shows uncompressed sizes within each package artifact, so individual files do not sum to the compressed artifact total. This comment reports package artifact sizes only; it is not a final app binary-size report. |
f0c8de2 to
0b38f90
Compare
| } | ||
|
|
||
| internal fun receiveWebMessage(message: String?, isMainFrame: Boolean = true) { | ||
| if (!isMainFrame) { |
There was a problem hiding this comment.
This is a new check. Some potential for issues if we're relying on any sub-frames to emit message
I don't see why we would be though
0b38f90 to
d63a691
Compare
| private const val LOG_TAG = "CheckoutWebView" | ||
| private const val SHOPIFY_PURPOSE_HEADER = "Shopify-Purpose" | ||
| private const val PREFETCH_PURPOSE = "prefetch" | ||
| private val WEB_MESSAGE_ALLOWED_ORIGIN_RULES = setOf("*") |
There was a problem hiding this comment.
Beginning wide-open, but with the option to tighten up in the future.
We could either apply here or add a sourceOrigin check on receipt of each message
f14f9d6 to
1f74d2c
Compare
| private fun attachProtocolBridge() { | ||
| if (webMessageListenerAttached) return | ||
|
|
||
| if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) { |
There was a problem hiding this comment.
Should we be using CheckoutWebViewFeatureSupport here too?
There was a problem hiding this comment.
This direct check was to help out Android lint, added a comment
There was a problem hiding this comment.
Looks like its flagged because of the elvis override on webMessageListenerSupportedOverride, which seems to be there for testing
Instead of a property could the method be overridden for testing (either DI it or mock it? AI tells me mockito has Mockito.mockStatic(WebViewFeature) but that doesn't seem like something globally applied 🙃
Maybe this isn't worth fixing I just wanted to avoid properties there just for test to pass and these duplicated guards 🤔
There was a problem hiding this comment.
Tis a tricky one, as mocking statics isn't ideal
Updated to something else, will take a closer look thru on monday
|
|
||
| if (!CheckoutWebViewFeatureSupport.supportsWebMessageListener()) { |
There was a problem hiding this comment.
Would it make sense to centralise the logs in attachProtocolBridge instead of being an early return here
Cons would be that it runs a bit more work below to start creating a webview, but it'd throw at construction
Pros: Would be if the system webview is <83 no new paths can accidentally forget this check, checkout webview ensures it cannot be created if the feature isn't supported, whereas right now construction is still possible if not gated, and it'll silently fail to create the bridge?
There was a problem hiding this comment.
Now preload is updated this way, present is left asymmetric on the error handling as it still handles the early return via shouldAbortPresentation
If that fn is reverted we would be able to rely on the Checkout.start() failing to dispatch the checkoutDidFail?
f742452 to
f725a07
Compare
f725a07 to
83fa948
Compare



What changes are you making?
Replaces the
addJavascriptInterfacetransport for the Embedded Checkout Protocol (ECP) bridge withWebViewCompat.addWebMessageListener, a more secure and modern WebView API.See
https://developer.android.com/privacy-and-security/risks/insecure-webview-native-bridges
Recommended here. And addJavaScriptInterface is referred to as legacy further down on the same page.
The bridge is now registered via
WebViewCompat.addWebMessageListenerwhenWebViewFeature.WEB_MESSAGE_LISTENERis supported, and torn down viaWebViewCompat.removeWebMessageListeneron detach.EmbeddedCheckoutProtocolBridge.postMessagenow delegates to a new internalreceiveMessagemethod, andCheckoutWebViewexposes areceiveWebMessageentry point that filters out child-frame messages before forwarding to the bridge.A new
CheckoutWebViewFeatureSupportobject centralises feature detection, exposes theweb_view_not_supportederror code and exception, and provides test override/reset helpers. WhenWEB_MESSAGE_LISTENERis not available,presentimmediately callsonCheckoutFailedwith aCheckoutKitExceptioncarrying theweb_view_not_supportederror code and returnsnull, andpreloadexits early without creating a cached view.The Android README documents the new
web_view_not_supportederror code in the exceptions table and adds a troubleshooting entry advising callers to open the checkout URL in Chrome, Chrome Custom Tabs, or another full browser, or to prompt the buyer to update Android System WebView or Chrome. The minimum supported WebView version is Android System WebView / Chrome 83 (released May 2020).WebMessageListener Support
How to test
WebMessageListenertransport path and unsupported-WebView behaviour.web message is received by protocol bridgetest passes, confirming that messages delivered viareceiveWebMessageare correctly handled by the protocol bridge.web message from child frame is ignoredtest passes, confirming that messages from child frames are filtered out.present emits unsupported WebView error and returns nullandpreload does nothing when WebView is unsupportedpass, confirming early-exit behaviour when the feature is unavailable.WEB_MESSAGE_LISTENER, load a checkout and confirm that ECP messages are received and processed correctly.WEB_MESSAGE_LISTENERis not supported, confirm thatpresentcallsonCheckoutFailedwithweb_view_not_supportedand does not display the bottom sheet.Before you merge
Important
platforms/swift/README.mdand/orplatforms/android/README.md)Releasing a new Swift version?
ShopifyCheckoutKit.podspecplatforms/swift/Sources/ShopifyCheckoutKit/ShopifyCheckoutKit.swiftplatforms/swift/README.md(major version only)Releasing a new Embedded Checkout Protocol version?
embeddedCheckoutProtocolAndroidinplatforms/android/gradle/libs.versions.tomlprotocol/languages/kotlin/embedded-checkout-protocol/api/embedded-checkout-protocol.apiif the public API changedReleasing a new Android version?
checkoutKitAndroidinplatforms/android/gradle/libs.versions.tomlplatforms/android/README.mdTip
See the Contributing documentation for the full release process per platform.