WebView bridge always advertises the "records" capability, forcing Browser SDK recording when Session Replay is not enabled
Maintainers usually reply within 1 day
Nobody has claimed this yet.
- #3937 by @notcool11 — closed without merging
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 76/100
Research direction
Start in features/dd-sdk-android-webview/src/main/kotlin/com/datadog/android/webview/internal/DatadogEventBridge.kt at getCapabilities(), then inspect how the Session Replay feature is registered and identified. Add unit tests covering registered and unregistered Session Replay states, including registration after WebViewTracking.enable(). Done means the bridge advertises records only when Session Replay is registered.
Written by the indexing model from the issue text.
Description
Describe the bug
DatadogEventBridge.getCapabilities() always returns ["records"], whether or not Session Replay is enabled in the host app:
internal val capabilities = JsonArray().apply {
add("records")
}
The Browser SDK reads this value to decide whether to record. computeSessionReplayState() returns SAMPLED whenever the bridge supports RECORDS, ignoring sample rates, and makeRecorderApi() only turns into a no-op when that capability is missing. So in every tracked WebView of an app that does not use Session Replay, the Browser SDK still starts the recorder. It serializes the DOM, watches mutations, and sends record events over the bridge. The native side then drops them because there is no WebViewReplayFeature (NoOpDataWriter). The work costs CPU and bridge traffic in the WebView and produces nothing.
The Android SDK already knows about this case in another place. WebViewRumEventMapper strips _dd.replay_stats and session.has_replay when native SR is off (RUM-4084). The capability advertised to the Browser SDK was never made conditional in the same way.
The iOS SDK advertises the capability only when Session Replay is registered:
It checks core.feature(named: "session-replay", type: SessionReplayConfiguration.self) each time it injects the bridge script, and leaves the capabilities empty when that returns nil.
The hardcoded value was added in e22c43e44 (#1871, "RUM-3281 Implement webview bridge getCapabilities") and is unchanged on develop.
Reproduction steps
- In an app with RUM enabled but without
dd-sdk-android-session-replay, callWebViewTracking.enable(webView, allowedHosts)and load a page that initialises the Browser SDK (v5+). - Inspect the WebView with
chrome://inspectand runDatadogEventBridge.getCapabilities(). It returns["records"]. - Watch
DatadogEventBridge.send(...)traffic. Alongside the RUM events, the page emits{"eventType":"record",...}messages, and the native SDK discards them.
I'll follow up in a comment with measured before/after numbers from a real app.
Expected behavior
getCapabilities() returns ["records"] only when the Session Replay feature is registered, and [] otherwise, the same as iOS. The Browser SDK then keeps its recorder as a no-op when the host app has no Session Replay.
Affected SDK versions
3.11.0 through current develop (hardcoded since the capability was introduced)
Latest working SDK version
None known. The capability has been unconditional since it was added.
Did you confirm if the latest SDK version fixes the bug?
No. Confirmed by reading develop, where the code is unchanged.
Kotlin / Java version
Kotlin 2.2.0 / Java 21
Gradle / AGP version
Gradle 8.13 / AGP 8.11.0
Other dependencies versions
Browser SDK 7.8.0 on the embedded page
Device Information
Not device-specific; the value is hardcoded. Testing on a Pixel 6 emulator (API 36).
Other relevant information
I'd like to contribute the fix: check Feature.SESSION_REPLAY_FEATURE_NAME on every getCapabilities() call, because the bridge lives across page loads and SR may be registered after WebViewTracking.enable(). I'll open a PR from a fork that references this issue, with unit tests and before/after measurements.
- Dominant language
- Kotlin
- Stars
- 227
- Forks
- 88
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 61
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from DataDog/dd-sdk-android
-
Difficulty 4/5 1-2 days Newbie friendliness 48/100
DataDog/dd-sdk-android#4005 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
DataDog/dd-sdk-android#3976 · 1 comment ·
Maintainers usually reply within 1 day
-
question
Difficulty 4/5 3-5 days Newbie friendliness 45/100
DataDog/dd-sdk-android#3888 · 1 comment ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 32/100
DataDog/dd-sdk-android#3223 · 4 comments · 2 reactions ·
Maintainers usually reply within 1 day
-
automatically closed question stale
Difficulty 5/5 Over a week Newbie friendliness 25/100
DataDog/dd-sdk-android#2970 · 6 comments ·
Maintainers usually reply within 1 day
All issues in DataDog/dd-sdk-android
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
navikt/mock-oauth2-server#1129 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
world-federation-of-advertisers/cross-media-measurement#4709 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
mikepenz/AboutLibraries#1488 · 2 comments ·
Maintainers usually reply within 1 day