Skip to content

Commit ce8935d

Browse files
committed
Simplify the availability check and data provider interface
1 parent 24fa1df commit ce8935d

5 files changed

Lines changed: 27 additions & 70 deletions

File tree

browser-mode/browser-mode-api/src/main/java/com/duckduckgo/browsermode/api/BrowserModeDataProvider.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ package com.duckduckgo.browsermode.api
2323
* [FIRE][BrowserMode.FIRE] variants without referencing either backing implementation directly.
2424
*/
2525
interface BrowserModeDataProvider<T> {
26-
/**
27-
* Returns the [T] bound to [mode]. Suspends until the underlying provider is ready.
28-
*/
29-
suspend fun forMode(mode: BrowserMode): T
26+
/** Returns the [T] bound to [mode]. */
27+
fun forMode(mode: BrowserMode): T
3028
}

browser-mode/browser-mode-impl/src/main/java/com/duckduckgo/browsermode/impl/RealFireModeAvailability.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import kotlinx.coroutines.launch
3131
import javax.inject.Inject
3232

3333
@SingleInstanceIn(AppScope::class)
34-
@ContributesBinding(AppScope::class)
34+
@ContributesBinding(AppScope::class, boundType = FireModeAvailability::class)
3535
@ContributesMultibinding(AppScope::class, boundType = MainProcessLifecycleObserver::class)
3636
class RealFireModeAvailability @Inject constructor(
3737
private val fireModeFeature: FireModeFeature,
@@ -48,10 +48,11 @@ class RealFireModeAvailability @Inject constructor(
4848

4949
override fun isAvailable(): Boolean = cachedAvailability ?: computeAndCache()
5050

51-
private fun computeAndCache(): Boolean =
52-
(
53-
WebViewFeature.isFeatureSupported(WebViewFeature.MULTI_PROFILE) &&
51+
private fun computeAndCache(): Boolean {
52+
cachedAvailability?.let { return it }
53+
val value = WebViewFeature.isFeatureSupported(WebViewFeature.MULTI_PROFILE) &&
5454
fireModeFeature.fireTabs().isEnabled()
55-
)
56-
.also { cachedAvailability = it }
55+
cachedAvailability = value
56+
return value
57+
}
5758
}

browser-mode/browser-mode-impl/src/main/java/com/duckduckgo/browsermode/impl/WebStorageProvider.kt

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,23 @@ package com.duckduckgo.browsermode.impl
1818

1919
import android.annotation.SuppressLint
2020
import android.webkit.WebStorage
21+
import androidx.annotation.UiThread
2122
import androidx.webkit.ProfileStore
2223
import com.duckduckgo.browsermode.api.BrowserMode
2324
import com.duckduckgo.browsermode.api.BrowserModeDataProvider
2425
import com.duckduckgo.browsermode.api.FireModeAvailability
25-
import com.duckduckgo.common.utils.DispatcherProvider
2626
import com.duckduckgo.di.scopes.AppScope
2727
import dagger.SingleInstanceIn
28-
import kotlinx.coroutines.withContext
2928
import javax.inject.Inject
3029

3130
@SuppressLint("RequiresFeature")
3231
@SingleInstanceIn(AppScope::class)
3332
class WebStorageProvider @Inject constructor(
3433
private val fireModeAvailability: FireModeAvailability,
35-
private val dispatchers: DispatcherProvider,
3634
) : BrowserModeDataProvider<WebStorage> {
37-
override suspend fun forMode(mode: BrowserMode): WebStorage {
35+
@UiThread
36+
override fun forMode(mode: BrowserMode): WebStorage {
3837
if (!fireModeAvailability.isAvailable()) return WebStorage.getInstance()
39-
return withContext(dispatchers.main()) {
40-
ProfileStore.getInstance().getOrCreateProfile(mode.profileName).webStorage
41-
}
38+
return ProfileStore.getInstance().getOrCreateProfile(mode.profileName).webStorage
4239
}
4340
}

browser-mode/browser-mode-impl/src/test/kotlin/com/duckduckgo/browsermode/impl/RealFireModeAvailabilityTest.kt

Lines changed: 10 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,74 +17,42 @@
1717
package com.duckduckgo.browsermode.impl
1818

1919
import android.annotation.SuppressLint
20-
import com.duckduckgo.app.browser.api.WebViewCapabilityChecker
21-
import com.duckduckgo.app.browser.api.WebViewCapabilityChecker.WebViewCapability.MultiProfile
20+
import androidx.test.ext.junit.runners.AndroidJUnit4
2221
import com.duckduckgo.common.test.CoroutineTestRule
2322
import com.duckduckgo.feature.toggles.api.FakeFeatureToggleFactory
2423
import com.duckduckgo.feature.toggles.api.Toggle
25-
import kotlinx.coroutines.test.runTest
2624
import org.junit.Assert.assertFalse
27-
import org.junit.Assert.assertTrue
2825
import org.junit.Rule
2926
import org.junit.Test
30-
import org.mockito.kotlin.mock
31-
import org.mockito.kotlin.stub
32-
import org.mockito.kotlin.times
33-
import org.mockito.kotlin.verifyBlocking
27+
import org.junit.runner.RunWith
3428

29+
@RunWith(AndroidJUnit4::class)
3530
@SuppressLint("DenyListedApi")
3631
class RealFireModeAvailabilityTest {
3732

3833
@get:Rule val coroutineRule = CoroutineTestRule()
3934

4035
private val fireModeFeature: FireModeFeature = FakeFeatureToggleFactory.create(FireModeFeature::class.java)
41-
private val webViewCapabilityChecker: WebViewCapabilityChecker = mock()
4236

43-
private val testee = RealFireModeAvailability(fireModeFeature, webViewCapabilityChecker, coroutineRule.testDispatcherProvider)
37+
private val testee = RealFireModeAvailability(
38+
fireModeFeature,
39+
coroutineRule.testDispatcherProvider,
40+
coroutineRule.testScope,
41+
)
4442

4543
@Test
46-
fun `is unavailable when fireTabs flag is disabled`() = runTest {
44+
fun `is unavailable when fireTabs flag is disabled`() {
4745
fireModeFeature.fireTabs().setRawStoredState(Toggle.State(enable = false))
48-
webViewCapabilityChecker.stub { onBlocking { isSupported(MultiProfile) }.thenReturn(true) }
4946

5047
assertFalse(testee.isAvailable())
5148
}
5249

5350
@Test
54-
fun `is unavailable when WebView does not support MultiProfile`() = runTest {
55-
fireModeFeature.fireTabs().setRawStoredState(Toggle.State(enable = true))
56-
webViewCapabilityChecker.stub { onBlocking { isSupported(MultiProfile) }.thenReturn(false) }
57-
58-
assertFalse(testee.isAvailable())
59-
}
60-
61-
@Test
62-
fun `is available when fireTabs is enabled and WebView supports MultiProfile`() = runTest {
63-
fireModeFeature.fireTabs().setRawStoredState(Toggle.State(enable = true))
64-
webViewCapabilityChecker.stub { onBlocking { isSupported(MultiProfile) }.thenReturn(true) }
65-
66-
assertTrue(testee.isAvailable())
67-
}
68-
69-
@Test
70-
fun `availability checks are cached across calls`() = runTest {
71-
fireModeFeature.fireTabs().setRawStoredState(Toggle.State(enable = true))
72-
webViewCapabilityChecker.stub { onBlocking { isSupported(MultiProfile) }.thenReturn(true) }
73-
74-
repeat(5) { testee.isAvailable() }
75-
76-
verifyBlocking(webViewCapabilityChecker, times(1)) { isSupported(MultiProfile) }
77-
}
78-
79-
@Test
80-
fun `availability is frozen on first computation even if flag flips later`() = runTest {
51+
fun `availability is frozen on first computation even if flag flips later`() {
8152
fireModeFeature.fireTabs().setRawStoredState(Toggle.State(enable = false))
82-
webViewCapabilityChecker.stub { onBlocking { isSupported(MultiProfile) }.thenReturn(true) }
83-
8453
assertFalse(testee.isAvailable())
8554

8655
fireModeFeature.fireTabs().setRawStoredState(Toggle.State(enable = true))
87-
8856
assertFalse(testee.isAvailable())
8957
}
9058
}

browser-mode/browser-mode-impl/src/test/kotlin/com/duckduckgo/browsermode/impl/WebStorageProviderTest.kt

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,21 @@ package com.duckduckgo.browsermode.impl
1919
import androidx.test.ext.junit.runners.AndroidJUnit4
2020
import com.duckduckgo.browsermode.api.BrowserMode
2121
import com.duckduckgo.browsermode.api.FireModeAvailability
22-
import com.duckduckgo.common.test.CoroutineTestRule
2322
import junit.framework.TestCase.assertNotNull
24-
import kotlinx.coroutines.test.runTest
25-
import org.junit.Rule
2623
import org.junit.Test
2724
import org.junit.runner.RunWith
2825
import org.mockito.kotlin.mock
29-
import org.mockito.kotlin.stub
26+
import org.mockito.kotlin.whenever
3027

3128
@RunWith(AndroidJUnit4::class)
3229
class WebStorageProviderTest {
3330

34-
@get:Rule
35-
val coroutineRule = CoroutineTestRule()
36-
3731
private val fireModeAvailability: FireModeAvailability = mock()
38-
private val testee =
39-
WebStorageProvider(fireModeAvailability, coroutineRule.testDispatcherProvider)
32+
private val testee = WebStorageProvider(fireModeAvailability)
4033

4134
@Test
42-
fun `forMode returns default WebStorage when multi-profile is unavailable`() = runTest {
43-
fireModeAvailability.stub { onBlocking { isAvailable() }.thenReturn(false) }
35+
fun `forMode returns default WebStorage when multi-profile is unavailable`() {
36+
whenever(fireModeAvailability.isAvailable()).thenReturn(false)
4437

4538
assertNotNull(testee.forMode(BrowserMode.REGULAR))
4639
assertNotNull(testee.forMode(BrowserMode.FIRE))

0 commit comments

Comments
 (0)