Coverage Summary for Class: InAppWebViewCachePolicy (cloud.mindbox.mobile_sdk.inapp.presentation)

Class Class, % Method, % Branch, % Line, % Instruction, %
InAppWebViewCachePolicy 100% (1/1) 100% (5/5) 87.5% (14/16) 100% (8/8) 100% (66/66)


 package cloud.mindbox.mobile_sdk.inapp.presentation
 
 import cloud.mindbox.mobile_sdk.inapp.data.managers.CACHE_INAPP_WEBVIEW_FEATURE
 import cloud.mindbox.mobile_sdk.inapp.data.managers.FEATURE_TOGGLE_DEFAULT
 import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.MobileConfigSerializationManager
 import cloud.mindbox.mobile_sdk.models.operation.response.InAppConfigResponseBlank
 import cloud.mindbox.mobile_sdk.repository.MindboxPreferences
 
 /**
  * The cache half of the WebView feature toggles (`MobileSdkShouldCacheInAppWebView`),
  * latched once per process from the cached config on disk — mirrors iOS's
  * `InAppWebViewDataStore.isCacheFeatureEnabled`.
  *
  * Read from the cache, not [cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.FeatureToggleManager]:
  * the prewarm's first WebView is created at SDK init, before any fresh config can populate
  * the manager — reading the live toggle there always sees the default (enabled), even when
  * the cached config already says otherwise. The decision is latched for the whole launch by
  * design: prewarm and every later show must agree, or the cache would be split between two
  * behaviors for the same session. This is also why the value can't just live in
  * [cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.FeatureToggleManager]'s toggle
  * map: that map is cleared and repopulated from the fresh config on every fetch, which would
  * silently un-latch this decision the first time a fresh config disagreed with the cache.
  */
 internal class InAppWebViewCachePolicy(
     private val mobileConfigSerializationManager: MobileConfigSerializationManager
 ) {
 
     @Volatile
     private var latched: Boolean? = null
 
     val isCacheEnabled: Boolean
         @Synchronized get() = latched ?: extract(parseCachedConfigBlank()).also { latched = it }
 
     /**
      * Lets a caller that already parsed the cached config blank for its own purposes (the
      * prewarm manager, which needs the same blank for its layers and prewarm-toggle checks)
      * hand it over instead of this class deserializing the same JSON a second time.
      *
      * First value wins: a call after the toggle has already latched — from here or from
      * [isCacheEnabled] itself — is a no-op.
      */
     @Synchronized
     fun prime(configBlank: InAppConfigResponseBlank?) {
         if (latched == null) latched = extract(configBlank)
     }
 
     private fun extract(configBlank: InAppConfigResponseBlank?): Boolean =
         configBlank?.settings?.featureToggles?.toggles?.get(CACHE_INAPP_WEBVIEW_FEATURE) ?: FEATURE_TOGGLE_DEFAULT
 
     private fun parseCachedConfigBlank(): InAppConfigResponseBlank? {
         val configString = MindboxPreferences.inAppConfig
         if (configString.isBlank()) return null
         return mobileConfigSerializationManager.deserializeToConfigDtoBlank(configString)
     }
 }