mirror of
https://github.com/bitwarden/android.git
synced 2025-03-16 03:08:50 +03:00
PM-10140: Add caching for large string resources to avoid delays and reduce timeout when retrieving ciphers (#3638)
This commit is contained in:
parent
74132de8ed
commit
39250e5cb4
12 changed files with 230 additions and 100 deletions
|
@ -21,7 +21,7 @@ private const val VAULT_LOCKED_TIMEOUT_MS: Long = 500L
|
|||
/**
|
||||
* The duration, in milliseconds, we should wait while retrieving ciphers before proceeding.
|
||||
*/
|
||||
private const val GET_CIPHERS_TIMEOUT_MS: Long = 5_000L
|
||||
private const val GET_CIPHERS_TIMEOUT_MS: Long = 2_000L
|
||||
|
||||
/**
|
||||
* The default [AutofillCipherProvider] implementation. This service is used for getting current
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package com.x8bit.bitwarden.data.platform.manager
|
||||
|
||||
/**
|
||||
* A manager for caching resources that are large and could be performance impacting to load
|
||||
* multiple times.
|
||||
*/
|
||||
interface ResourceCacheManager {
|
||||
/**
|
||||
* Retrieves the exception suffix list used for matching a cipher against a domain.
|
||||
*/
|
||||
val domainExceptionSuffixes: List<String>
|
||||
|
||||
/**
|
||||
* Retrieves the normal suffix list used for matching a cipher against a domain.
|
||||
*/
|
||||
val domainNormalSuffixes: List<String>
|
||||
|
||||
/**
|
||||
* Retrieves the wild card suffix list used for matching a cipher against a domain.
|
||||
*/
|
||||
val domainWildCardSuffixes: List<String>
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.x8bit.bitwarden.data.platform.manager
|
||||
|
||||
import android.content.Context
|
||||
import com.x8bit.bitwarden.R
|
||||
|
||||
/**
|
||||
* Primary implementation of [ResourceCacheManager].
|
||||
*/
|
||||
class ResourceCacheManagerImpl(
|
||||
private val context: Context,
|
||||
) : ResourceCacheManager {
|
||||
override val domainExceptionSuffixes: List<String> by lazy {
|
||||
context
|
||||
.resources
|
||||
.getStringArray(R.array.exception_suffixes)
|
||||
.toList()
|
||||
}
|
||||
|
||||
override val domainNormalSuffixes: List<String> by lazy {
|
||||
context
|
||||
.resources
|
||||
.getStringArray(R.array.normal_suffixes)
|
||||
.toList()
|
||||
}
|
||||
|
||||
override val domainWildCardSuffixes: List<String> by lazy {
|
||||
context
|
||||
.resources
|
||||
.getStringArray(R.array.wild_card_suffixes)
|
||||
.toList()
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
package com.x8bit.bitwarden.data.platform.manager.ciphermatching
|
||||
|
||||
import android.content.Context
|
||||
import com.bitwarden.vault.CipherView
|
||||
import com.bitwarden.vault.LoginUriView
|
||||
import com.bitwarden.vault.UriMatchType
|
||||
import com.x8bit.bitwarden.data.platform.manager.ResourceCacheManager
|
||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||
import com.x8bit.bitwarden.data.platform.util.firstWithTimeoutOrNull
|
||||
import com.x8bit.bitwarden.data.platform.util.getDomainOrNull
|
||||
|
@ -31,7 +31,7 @@ private const val GET_DOMAINS_TIMEOUT_MS: Long = 1_000L
|
|||
* ciphers based on special criteria.
|
||||
*/
|
||||
class CipherMatchingManagerImpl(
|
||||
private val context: Context,
|
||||
private val resourceCacheManager: ResourceCacheManager,
|
||||
private val settingsRepository: SettingsRepository,
|
||||
private val vaultRepository: VaultRepository,
|
||||
) : CipherMatchingManager {
|
||||
|
@ -48,7 +48,7 @@ class CipherMatchingManagerImpl(
|
|||
val isAndroidApp = matchUri.isAndroidApp()
|
||||
val defaultUriMatchType = settingsRepository.defaultUriMatchType.toSdkUriMatchType()
|
||||
val domain = matchUri
|
||||
.getDomainOrNull(context = context)
|
||||
.getDomainOrNull(resourceCacheManager = resourceCacheManager)
|
||||
?.lowercase()
|
||||
|
||||
// Retrieve domains that are considered equivalent to the specified matchUri for cipher
|
||||
|
@ -67,8 +67,8 @@ class CipherMatchingManagerImpl(
|
|||
ciphers
|
||||
.forEach { cipherView ->
|
||||
val matchResult = checkForCipherMatch(
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
cipherView = cipherView,
|
||||
context = context,
|
||||
defaultUriMatchType = defaultUriMatchType,
|
||||
isAndroidApp = isAndroidApp,
|
||||
matchUri = matchUri,
|
||||
|
@ -142,7 +142,7 @@ private fun getMatchingDomains(
|
|||
* provide details on the match quality.
|
||||
*
|
||||
* @param cipherView The cipher to be judged for a match.
|
||||
* @param context A context for getting string resources.
|
||||
* @param resourceCacheManager The [ResourceCacheManager] for fetching cached resources.
|
||||
* @param defaultUriMatchType The global default [UriMatchType].
|
||||
* @param isAndroidApp Whether or not the [matchUri] belongs to an Android app.
|
||||
* @param matchingDomains The set of domains that match the domain of [matchUri].
|
||||
|
@ -150,8 +150,8 @@ private fun getMatchingDomains(
|
|||
*/
|
||||
@Suppress("LongParameterList")
|
||||
private fun checkForCipherMatch(
|
||||
resourceCacheManager: ResourceCacheManager,
|
||||
cipherView: CipherView,
|
||||
context: Context,
|
||||
defaultUriMatchType: UriMatchType,
|
||||
isAndroidApp: Boolean,
|
||||
matchingDomains: MatchingDomains,
|
||||
|
@ -162,7 +162,7 @@ private fun checkForCipherMatch(
|
|||
?.uris
|
||||
?.map { loginUriView ->
|
||||
loginUriView.checkForMatch(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
defaultUriMatchType = defaultUriMatchType,
|
||||
isAndroidApp = isAndroidApp,
|
||||
matchingDomains = matchingDomains,
|
||||
|
@ -180,14 +180,14 @@ private fun checkForCipherMatch(
|
|||
/**
|
||||
* Check to see how well this [LoginUriView] matches [matchUri].
|
||||
*
|
||||
* @param context A context for getting app information.
|
||||
* @param resourceCacheManager The [ResourceCacheManager] for fetching cached resources.
|
||||
* @param defaultUriMatchType The global default [UriMatchType].
|
||||
* @param isAndroidApp Whether or not the [matchUri] belongs to an Android app.
|
||||
* @param matchingDomains The set of domains that match the domain of [matchUri].
|
||||
* @param matchUri The uri that this [LoginUriView] is being matched to.
|
||||
*/
|
||||
private fun LoginUriView.checkForMatch(
|
||||
context: Context,
|
||||
resourceCacheManager: ResourceCacheManager,
|
||||
defaultUriMatchType: UriMatchType,
|
||||
isAndroidApp: Boolean,
|
||||
matchingDomains: MatchingDomains,
|
||||
|
@ -200,7 +200,7 @@ private fun LoginUriView.checkForMatch(
|
|||
when (matchType) {
|
||||
UriMatchType.DOMAIN -> {
|
||||
checkUriForDomainMatch(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
isAndroidApp = isAndroidApp,
|
||||
matchingDomains = matchingDomains,
|
||||
uri = loginViewUri,
|
||||
|
@ -234,8 +234,8 @@ private fun LoginUriView.checkForMatch(
|
|||
* Check to see if [uri] matches [matchingDomains] in some way.
|
||||
*/
|
||||
private fun checkUriForDomainMatch(
|
||||
resourceCacheManager: ResourceCacheManager,
|
||||
isAndroidApp: Boolean,
|
||||
context: Context,
|
||||
matchingDomains: MatchingDomains,
|
||||
uri: String,
|
||||
): MatchResult = when {
|
||||
|
@ -243,7 +243,7 @@ private fun checkUriForDomainMatch(
|
|||
isAndroidApp && matchingDomains.fuzzyMatches.contains(uri) -> MatchResult.FUZZY
|
||||
else -> {
|
||||
val domain = uri
|
||||
.getDomainOrNull(context = context)
|
||||
.getDomainOrNull(resourceCacheManager = resourceCacheManager)
|
||||
?.lowercase()
|
||||
|
||||
// We only care about fuzzy matches if we are isAndroidApp is true because the fuzzu
|
||||
|
|
|
@ -30,6 +30,8 @@ import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
|||
import com.x8bit.bitwarden.data.platform.manager.PolicyManagerImpl
|
||||
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.PushManagerImpl
|
||||
import com.x8bit.bitwarden.data.platform.manager.ResourceCacheManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.ResourceCacheManagerImpl
|
||||
import com.x8bit.bitwarden.data.platform.manager.SdkClientManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.SdkClientManagerImpl
|
||||
import com.x8bit.bitwarden.data.platform.manager.ciphermatching.CipherMatchingManager
|
||||
|
@ -90,12 +92,12 @@ object PlatformManagerModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun providesCipherMatchingManager(
|
||||
@ApplicationContext context: Context,
|
||||
resourceCacheManager: ResourceCacheManager,
|
||||
settingsRepository: SettingsRepository,
|
||||
vaultRepository: VaultRepository,
|
||||
): CipherMatchingManager =
|
||||
CipherMatchingManagerImpl(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
settingsRepository = settingsRepository,
|
||||
vaultRepository = vaultRepository,
|
||||
)
|
||||
|
@ -229,4 +231,10 @@ object PlatformManagerModule {
|
|||
environmentRepository = environmentRepository,
|
||||
restrictionsManager = requireNotNull(context.getSystemService()),
|
||||
)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideResourceCacheManager(
|
||||
@ApplicationContext context: Context,
|
||||
): ResourceCacheManager = ResourceCacheManagerImpl(context = context)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.x8bit.bitwarden.data.platform.util
|
||||
|
||||
import android.content.Context
|
||||
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
|
||||
import com.x8bit.bitwarden.data.platform.manager.ResourceCacheManager
|
||||
import java.net.URI
|
||||
import java.net.URISyntaxException
|
||||
|
||||
|
@ -47,10 +47,10 @@ fun String.getWebHostFromAndroidUriOrNull(): String? =
|
|||
/**
|
||||
* Extract the domain name from this [String] if possible, otherwise return null.
|
||||
*/
|
||||
fun String.getDomainOrNull(context: Context): String? =
|
||||
fun String.getDomainOrNull(resourceCacheManager: ResourceCacheManager): String? =
|
||||
this
|
||||
.toUriOrNull()
|
||||
?.parseDomainOrNull(context = context)
|
||||
?.parseDomainOrNull(resourceCacheManager = resourceCacheManager)
|
||||
|
||||
/**
|
||||
* Extract the host with optional port from this [String] if possible, otherwise return null.
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.x8bit.bitwarden.data.platform.util
|
||||
|
||||
import android.content.Context
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.platform.manager.ResourceCacheManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.model.DomainName
|
||||
import java.net.URI
|
||||
|
||||
|
@ -17,7 +16,7 @@ private const val IP_REGEX: String =
|
|||
/**
|
||||
* Parses the base domain from the URL. Returns null if unavailable.
|
||||
*/
|
||||
fun URI.parseDomainOrNull(context: Context): String? {
|
||||
fun URI.parseDomainOrNull(resourceCacheManager: ResourceCacheManager): String? {
|
||||
val host = this.host ?: return null
|
||||
val isIpAddress = host.matches(IP_REGEX.toRegex())
|
||||
|
||||
|
@ -25,7 +24,7 @@ fun URI.parseDomainOrNull(context: Context): String? {
|
|||
host
|
||||
} else {
|
||||
parseDomainNameOrNullInternal(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
host = host,
|
||||
)
|
||||
?.domain
|
||||
|
@ -35,13 +34,13 @@ fun URI.parseDomainOrNull(context: Context): String? {
|
|||
/**
|
||||
* Parses a URL to get the breakdown of a URL's domain. Returns null if invalid.
|
||||
*/
|
||||
fun URI.parseDomainNameOrNull(context: Context): DomainName? =
|
||||
fun URI.parseDomainNameOrNull(resourceCacheManager: ResourceCacheManager): DomainName? =
|
||||
this
|
||||
// URI is a platform type and host can be null.
|
||||
.host
|
||||
?.let { nonNullHost ->
|
||||
parseDomainNameOrNullInternal(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
host = nonNullHost,
|
||||
)
|
||||
}
|
||||
|
@ -53,21 +52,12 @@ fun URI.parseDomainNameOrNull(context: Context): DomainName? =
|
|||
*/
|
||||
@Suppress("LongMethod")
|
||||
private fun parseDomainNameOrNullInternal(
|
||||
context: Context,
|
||||
resourceCacheManager: ResourceCacheManager,
|
||||
host: String,
|
||||
): DomainName? {
|
||||
val exceptionSuffixes = context
|
||||
.resources
|
||||
.getStringArray(R.array.exception_suffixes)
|
||||
.toList()
|
||||
val normalSuffixes = context
|
||||
.resources
|
||||
.getStringArray(R.array.normal_suffixes)
|
||||
.toList()
|
||||
val wildCardSuffixes = context
|
||||
.resources
|
||||
.getStringArray(R.array.wild_card_suffixes)
|
||||
.toList()
|
||||
val exceptionSuffixes = resourceCacheManager.domainExceptionSuffixes
|
||||
val normalSuffixes = resourceCacheManager.domainNormalSuffixes
|
||||
val wildCardSuffixes = resourceCacheManager.domainWildCardSuffixes
|
||||
|
||||
// Split the host into parts separated by a period. Start with the last part and incrementally
|
||||
// add back the earlier parts to build a list of any matching domains in the data set.
|
||||
|
|
|
@ -196,7 +196,7 @@ class AutofillCipherProviderTest {
|
|||
|
||||
testScheduler.runCurrent()
|
||||
assertFalse(actual.isCompleted)
|
||||
testScheduler.advanceTimeBy(delayTimeMillis = 5_000L)
|
||||
testScheduler.advanceTimeBy(delayTimeMillis = 2_000L)
|
||||
testScheduler.runCurrent()
|
||||
|
||||
// Verify
|
||||
|
@ -268,7 +268,7 @@ class AutofillCipherProviderTest {
|
|||
|
||||
testScheduler.runCurrent()
|
||||
assertFalse(actual.isCompleted)
|
||||
testScheduler.advanceTimeBy(delayTimeMillis = 5_000L)
|
||||
testScheduler.advanceTimeBy(delayTimeMillis = 2_000L)
|
||||
testScheduler.runCurrent()
|
||||
|
||||
// Verify
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
package com.x8bit.bitwarden.data.platform.manager
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import com.x8bit.bitwarden.R
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class ResourceCacheManagerTest {
|
||||
private val resources: Resources = mockk {
|
||||
every { getStringArray(R.array.exception_suffixes) } returns arrayOf("uk")
|
||||
every { getStringArray(R.array.normal_suffixes) } returns arrayOf("co.uk")
|
||||
every { getStringArray(R.array.wild_card_suffixes) } returns arrayOf("amazonaws.com")
|
||||
}
|
||||
private val context: Context = mockk {
|
||||
every { this@mockk.resources } returns this@ResourceCacheManagerTest.resources
|
||||
}
|
||||
|
||||
private val resourceCacheManager: ResourceCacheManager = ResourceCacheManagerImpl(
|
||||
context = context,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `domainExceptionSuffixes should return cached value the second time`() {
|
||||
val expected = listOf("uk")
|
||||
|
||||
val firstResult = resourceCacheManager.domainExceptionSuffixes
|
||||
|
||||
assertEquals(expected, firstResult)
|
||||
verify(exactly = 1) {
|
||||
context.resources
|
||||
resources.getStringArray(R.array.exception_suffixes)
|
||||
}
|
||||
clearMocks(context, resources)
|
||||
|
||||
val secondResult = resourceCacheManager.domainExceptionSuffixes
|
||||
|
||||
assertEquals(expected, secondResult)
|
||||
verify(exactly = 0) {
|
||||
context.resources
|
||||
resources.getStringArray(R.array.exception_suffixes)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `domainNormalSuffixes should return cached value the second time`() {
|
||||
val expected = listOf("co.uk")
|
||||
|
||||
val firstResult = resourceCacheManager.domainNormalSuffixes
|
||||
|
||||
assertEquals(expected, firstResult)
|
||||
verify(exactly = 1) {
|
||||
context.resources
|
||||
resources.getStringArray(R.array.normal_suffixes)
|
||||
}
|
||||
clearMocks(context, resources)
|
||||
|
||||
val secondResult = resourceCacheManager.domainNormalSuffixes
|
||||
|
||||
assertEquals(expected, secondResult)
|
||||
verify(exactly = 0) {
|
||||
context.resources
|
||||
resources.getStringArray(R.array.normal_suffixes)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `domainWildCardSuffixes should return cached value the second time`() {
|
||||
val expected = listOf("amazonaws.com")
|
||||
|
||||
val firstResult = resourceCacheManager.domainWildCardSuffixes
|
||||
|
||||
assertEquals(expected, firstResult)
|
||||
verify(exactly = 1) {
|
||||
context.resources
|
||||
resources.getStringArray(R.array.wild_card_suffixes)
|
||||
}
|
||||
clearMocks(context, resources)
|
||||
|
||||
val secondResult = resourceCacheManager.domainWildCardSuffixes
|
||||
|
||||
assertEquals(expected, secondResult)
|
||||
verify(exactly = 0) {
|
||||
context.resources
|
||||
resources.getStringArray(R.array.wild_card_suffixes)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package com.x8bit.bitwarden.data.platform.manager.ciphermatching
|
||||
|
||||
import android.content.Context
|
||||
import com.bitwarden.vault.CipherView
|
||||
import com.bitwarden.vault.LoginUriView
|
||||
import com.bitwarden.vault.LoginView
|
||||
import com.bitwarden.vault.UriMatchType
|
||||
import com.x8bit.bitwarden.data.platform.manager.ResourceCacheManager
|
||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||
import com.x8bit.bitwarden.data.platform.util.getDomainOrNull
|
||||
|
@ -33,7 +33,7 @@ class CipherMatchingManagerTest {
|
|||
private lateinit var cipherMatchingManager: CipherMatchingManager
|
||||
|
||||
// Setup dependencies
|
||||
private val context: Context = mockk()
|
||||
private val resourceCacheManager: ResourceCacheManager = mockk()
|
||||
private val settingsRepository: SettingsRepository = mockk {
|
||||
every { defaultUriMatchType } returns DEFAULT_URI_MATCH_TYPE
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ class CipherMatchingManagerTest {
|
|||
String::getWebHostFromAndroidUriOrNull,
|
||||
)
|
||||
cipherMatchingManager = CipherMatchingManagerImpl(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
settingsRepository = settingsRepository,
|
||||
vaultRepository = vaultRepository,
|
||||
)
|
||||
|
@ -333,7 +333,7 @@ class CipherMatchingManagerTest {
|
|||
)
|
||||
with(uri) {
|
||||
every { isAndroidApp() } returns false
|
||||
every { getDomainOrNull(context = context) } returns this
|
||||
every { getDomainOrNull(resourceCacheManager = resourceCacheManager) } returns this
|
||||
every { getWebHostFromAndroidUriOrNull() } returns null
|
||||
}
|
||||
|
||||
|
@ -356,26 +356,30 @@ class CipherMatchingManagerTest {
|
|||
) {
|
||||
with(uri) {
|
||||
every { isAndroidApp() } returns isAndroidApp
|
||||
every { getDomainOrNull(context = context) } returns this.takeIf { isAndroidApp }
|
||||
every {
|
||||
getDomainOrNull(resourceCacheManager = resourceCacheManager)
|
||||
} returns this.takeIf { isAndroidApp }
|
||||
every { getHostWithPortOrNull() } returns HOST_WITH_PORT
|
||||
every {
|
||||
getWebHostFromAndroidUriOrNull()
|
||||
} returns ANDROID_APP_WEB_URL.takeIf { isAndroidApp }
|
||||
}
|
||||
every {
|
||||
DEFAULT_LOGIN_VIEW_URI_ONE.getDomainOrNull(context = context)
|
||||
DEFAULT_LOGIN_VIEW_URI_ONE.getDomainOrNull(resourceCacheManager = resourceCacheManager)
|
||||
} returns DEFAULT_LOGIN_VIEW_URI_ONE
|
||||
every {
|
||||
DEFAULT_LOGIN_VIEW_URI_TWO.getDomainOrNull(context = context)
|
||||
DEFAULT_LOGIN_VIEW_URI_TWO.getDomainOrNull(resourceCacheManager = resourceCacheManager)
|
||||
} returns null
|
||||
every {
|
||||
DEFAULT_LOGIN_VIEW_URI_THREE.getDomainOrNull(context = context)
|
||||
DEFAULT_LOGIN_VIEW_URI_THREE.getDomainOrNull(
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
)
|
||||
} returns uri
|
||||
every {
|
||||
DEFAULT_LOGIN_VIEW_URI_FOUR.getDomainOrNull(context = context)
|
||||
DEFAULT_LOGIN_VIEW_URI_FOUR.getDomainOrNull(resourceCacheManager = resourceCacheManager)
|
||||
} returns "bitwarden.com"
|
||||
every {
|
||||
DEFAULT_LOGIN_VIEW_URI_FIVE.getDomainOrNull(context = context)
|
||||
DEFAULT_LOGIN_VIEW_URI_FIVE.getDomainOrNull(resourceCacheManager = resourceCacheManager)
|
||||
} returns null
|
||||
|
||||
every { HOST_LOGIN_VIEW_URI_MATCHING.getHostWithPortOrNull() } returns HOST_WITH_PORT
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.x8bit.bitwarden.data.util
|
||||
|
||||
import android.content.Context
|
||||
import com.x8bit.bitwarden.data.platform.manager.ResourceCacheManager
|
||||
import com.x8bit.bitwarden.data.platform.util.findLastSubstringIndicesOrNull
|
||||
import com.x8bit.bitwarden.data.platform.util.getDomainOrNull
|
||||
import com.x8bit.bitwarden.data.platform.util.getWebHostFromAndroidUriOrNull
|
||||
|
@ -74,21 +74,21 @@ class StringExtensionsTest {
|
|||
fun `getDomainOrNull should invoke parseDomainOrNull when URI is created`() {
|
||||
// Setup
|
||||
mockkStatic(URI::parseDomainOrNull)
|
||||
val context: Context = mockk()
|
||||
val resourceCacheManager: ResourceCacheManager = mockk()
|
||||
val expected = "google.com"
|
||||
every {
|
||||
any<URI>().parseDomainOrNull(context = context)
|
||||
any<URI>().parseDomainOrNull(resourceCacheManager = resourceCacheManager)
|
||||
} returns expected
|
||||
|
||||
// Test
|
||||
val actual = "www.google.com".getDomainOrNull(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
)
|
||||
|
||||
// Verify
|
||||
assertEquals(expected, actual)
|
||||
verify(exactly = 1) {
|
||||
any<URI>().parseDomainOrNull(context = context)
|
||||
any<URI>().parseDomainOrNull(resourceCacheManager = resourceCacheManager)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,17 +96,17 @@ class StringExtensionsTest {
|
|||
fun `getDomainOrNull should not invoke parseDomainOrNull when URI is not created`() {
|
||||
// Setup
|
||||
mockkStatic(URI::parseDomainOrNull)
|
||||
val context: Context = mockk()
|
||||
val resourceCacheManager: ResourceCacheManager = mockk()
|
||||
|
||||
// Test
|
||||
val actual = "not a URI".getDomainOrNull(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
)
|
||||
|
||||
// Verify
|
||||
assertNull(actual)
|
||||
verify(exactly = 0) {
|
||||
any<URI>().parseDomainOrNull(context = context)
|
||||
any<URI>().parseDomainOrNull(resourceCacheManager = resourceCacheManager)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package com.x8bit.bitwarden.data.util
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.platform.manager.ResourceCacheManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.model.DomainName
|
||||
import com.x8bit.bitwarden.data.platform.util.parseDomainNameOrNull
|
||||
import com.x8bit.bitwarden.data.platform.util.parseDomainOrNull
|
||||
|
@ -14,13 +12,10 @@ import org.junit.jupiter.api.Test
|
|||
import java.net.URI
|
||||
|
||||
class UriExtensionsTest {
|
||||
private val resources: Resources = mockk {
|
||||
every { getStringArray(R.array.exception_suffixes) } returns emptyArray()
|
||||
every { getStringArray(R.array.normal_suffixes) } returns emptyArray()
|
||||
every { getStringArray(R.array.wild_card_suffixes) } returns emptyArray()
|
||||
}
|
||||
private val context: Context = mockk {
|
||||
every { this@mockk.resources } returns this@UriExtensionsTest.resources
|
||||
private val resourceCacheManager: ResourceCacheManager = mockk {
|
||||
every { domainExceptionSuffixes } returns emptyList()
|
||||
every { domainNormalSuffixes } returns emptyList()
|
||||
every { domainWildCardSuffixes } returns emptyList()
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -32,7 +27,7 @@ class UriExtensionsTest {
|
|||
|
||||
// Test
|
||||
val actual = uri.parseDomainOrNull(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
)
|
||||
|
||||
// Verify
|
||||
|
@ -49,7 +44,7 @@ class UriExtensionsTest {
|
|||
|
||||
// Test
|
||||
val actual = uri.parseDomainOrNull(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
)
|
||||
|
||||
// Verify
|
||||
|
@ -66,7 +61,7 @@ class UriExtensionsTest {
|
|||
|
||||
// Test
|
||||
val actual = uri.parseDomainOrNull(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
)
|
||||
|
||||
// Verify
|
||||
|
@ -83,9 +78,7 @@ class UriExtensionsTest {
|
|||
"example.uk",
|
||||
null,
|
||||
)
|
||||
every {
|
||||
resources.getStringArray(R.array.exception_suffixes)
|
||||
} returns arrayOf("co.uk", "uk")
|
||||
every { resourceCacheManager.domainExceptionSuffixes } returns listOf("co.uk", "uk")
|
||||
|
||||
// Test & Verify
|
||||
listOf(
|
||||
|
@ -100,7 +93,7 @@ class UriExtensionsTest {
|
|||
|
||||
// Test
|
||||
val actual = uri.parseDomainOrNull(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
)
|
||||
|
||||
// Verify
|
||||
|
@ -118,10 +111,7 @@ class UriExtensionsTest {
|
|||
"example.uk",
|
||||
null,
|
||||
)
|
||||
every { resources.getStringArray(R.array.exception_suffixes) } returns arrayOf(
|
||||
"co.uk",
|
||||
"uk",
|
||||
)
|
||||
every { resourceCacheManager.domainExceptionSuffixes } returns listOf("co.uk", "uk")
|
||||
|
||||
// Test & Verify
|
||||
listOf(
|
||||
|
@ -136,7 +126,7 @@ class UriExtensionsTest {
|
|||
|
||||
// Test
|
||||
val actual = uri.parseDomainOrNull(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
)
|
||||
|
||||
// Verify
|
||||
|
@ -154,10 +144,9 @@ class UriExtensionsTest {
|
|||
"example.foo.amazonaws.com",
|
||||
null,
|
||||
)
|
||||
every { resources.getStringArray(R.array.wild_card_suffixes) } returns arrayOf(
|
||||
"compute.amazonaws.com",
|
||||
"amazonaws.com",
|
||||
)
|
||||
every {
|
||||
resourceCacheManager.domainWildCardSuffixes
|
||||
} returns listOf("compute.amazonaws.com", "amazonaws.com")
|
||||
|
||||
// Test & Verify
|
||||
listOf(
|
||||
|
@ -172,7 +161,7 @@ class UriExtensionsTest {
|
|||
|
||||
// Test
|
||||
val actual = uri.parseDomainOrNull(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
)
|
||||
|
||||
// Verify
|
||||
|
@ -189,7 +178,7 @@ class UriExtensionsTest {
|
|||
|
||||
// Test
|
||||
val actual = uri.parseDomainNameOrNull(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
)
|
||||
|
||||
// Verify
|
||||
|
@ -218,10 +207,7 @@ class UriExtensionsTest {
|
|||
),
|
||||
null,
|
||||
)
|
||||
every { resources.getStringArray(R.array.exception_suffixes) } returns arrayOf(
|
||||
"co.uk",
|
||||
"uk",
|
||||
)
|
||||
every { resourceCacheManager.domainExceptionSuffixes } returns listOf("co.uk", "uk")
|
||||
|
||||
// Test & Verify
|
||||
listOf(
|
||||
|
@ -236,7 +222,7 @@ class UriExtensionsTest {
|
|||
|
||||
// Test
|
||||
val actual = uri.parseDomainNameOrNull(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
)
|
||||
|
||||
// Verify
|
||||
|
@ -266,10 +252,7 @@ class UriExtensionsTest {
|
|||
),
|
||||
null,
|
||||
)
|
||||
every { resources.getStringArray(R.array.exception_suffixes) } returns arrayOf(
|
||||
"co.uk",
|
||||
"uk",
|
||||
)
|
||||
every { resourceCacheManager.domainExceptionSuffixes } returns listOf("co.uk", "uk")
|
||||
|
||||
// Test & Verify
|
||||
listOf(
|
||||
|
@ -284,7 +267,7 @@ class UriExtensionsTest {
|
|||
|
||||
// Test
|
||||
val actual = uri.parseDomainNameOrNull(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
)
|
||||
|
||||
// Verify
|
||||
|
@ -314,10 +297,9 @@ class UriExtensionsTest {
|
|||
),
|
||||
null,
|
||||
)
|
||||
every { resources.getStringArray(R.array.wild_card_suffixes) } returns arrayOf(
|
||||
"compute.amazonaws.com",
|
||||
"amazonaws.com",
|
||||
)
|
||||
every {
|
||||
resourceCacheManager.domainWildCardSuffixes
|
||||
} returns listOf("compute.amazonaws.com", "amazonaws.com")
|
||||
|
||||
// Test & Verify
|
||||
listOf(
|
||||
|
@ -332,7 +314,7 @@ class UriExtensionsTest {
|
|||
|
||||
// Test
|
||||
val actual = uri.parseDomainNameOrNull(
|
||||
context = context,
|
||||
resourceCacheManager = resourceCacheManager,
|
||||
)
|
||||
|
||||
// Verify
|
||||
|
|
Loading…
Add table
Reference in a new issue