Skip to content

fix(android): scope WebView teardown to the owning Activity#131

Merged
ethanpschoen merged 4 commits into
justin/feat/cross-activity-lifecyclefrom
ethan/fix/cross-activity-load-teardown
Jul 21, 2026
Merged

fix(android): scope WebView teardown to the owning Activity#131
ethanpschoen merged 4 commits into
justin/feat/cross-activity-lifecyclefrom
ethan/fix/cross-activity-load-teardown

Conversation

@ethanpschoen

@ethanpschoen ethanpschoen commented Jul 21, 2026

Copy link
Copy Markdown

Description of this change

Ketch.onHostDestroyed() tore down the in-flight activeWebView boot whenever any Activity in the app was destroyed while !isShowingExperience, with no check that the destroyed Activity was the one that actually owned the WebView's context. A transient Activity that calls load() and finishes quickly (a splash screen, a redirect Activity, or navigating away before boot completes) would silently kill a boot that could belong to a completely different, still-alive Activity — no error, no callback, just a dropped load(). This adds activeWebViewHost, recorded at WebView-creation time, and scopes teardown to only fire when the destroyed Activity is that recorded owner — mirroring the early-return-when-no-owner behavior the pre-existing dialogHost ownership check already uses a few lines above it. Also corrects two integration tests (KetchSdkIntegrationTest.testConsentBannerUserInteraction, ZTriggerFunctionTest.warmWebView_dispatchesTriggerWithoutError) whose assumptions no longer matched the live ketch_samples/android deployment plan's actual banner button semantics and trigger()'s documented behavior while an experience is showing.

Why is this change being made?

  • Chore (non-functional changes)
  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

How was this tested? How can the reviewer verify your testing?

Reproduced the failure live by adding a TransientLoadActivity to sample-app-compose that calls load() then finishes immediately; logcat showed the boot progress to 80% then webViewClient coroutines cancelled, with onConfigUpdated never firing, pre-fix. Added ZTransientActivityLoadSurvivesTest (integration-tests) reproducing the same mechanism via ActivityScenario — fails pre-fix (30s timeout), passes post-fix. Verified the fix wasn't a false positive by stashing just the Ketch.kt change and re-running the full 39-test instrumentation suite — identical failure set with/without it, confirming nothing else in the suite depends on the old unconditional-teardown behavior. Full suite (:integration-tests:connectedDebugAndroidTest) is 39/39 passing, and :ketchsdk:testDebugUnitTest passes.

Related issues

N/A — no tracked issue; found and fixed while investigating a customer-reported early-load() failure.

Checklist

  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have evaluated the security impact of this change, and OWASP Secure Coding Practices have been observed.
  • I have informed stakeholders of my changes.

@ethanpschoen
ethanpschoen requested a review from jboileau99 July 21, 2026 00:51
@ethanpschoen
ethanpschoen merged commit a47d4c6 into justin/feat/cross-activity-lifecycle Jul 21, 2026
4 checks passed
@ethanpschoen
ethanpschoen deleted the ethan/fix/cross-activity-load-teardown branch July 21, 2026 01:30
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.

1 participant