1
0
Fork 0

For #7048: Network info migration (#7091)

* Fixes #7048.
Adds extension function to check if online or not based on capabilities
Modified `buildDeviceList`
Modifies tests

* Fixing lint error for max length
Fixing test in AppRequestInterceptorTest.kt

* Adds suppression for deprecation
Moving away from using anko for ConnectivityManager instance

* Creates ConnectivityManager extension component

* Fixes #7180
Refactors test cases to fix static mocks
master
Suraj Shah 2019-12-17 06:03:11 +00:00 committed by Tiger Oakes
parent e727ae5d7e
commit 6cb3879caf
5 changed files with 58 additions and 17 deletions

View File

@ -6,8 +6,8 @@ package org.mozilla.fenix
import android.content.Context import android.content.Context
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.net.NetworkInfo
import androidx.annotation.RawRes import androidx.annotation.RawRes
import androidx.core.content.getSystemService
import mozilla.components.browser.errorpages.ErrorPages import mozilla.components.browser.errorpages.ErrorPages
import mozilla.components.browser.errorpages.ErrorType import mozilla.components.browser.errorpages.ErrorType
import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSession
@ -15,6 +15,7 @@ import mozilla.components.concept.engine.request.RequestInterceptor
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.isOnline
class AppRequestInterceptor(private val context: Context) : RequestInterceptor { class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
override fun onLoadRequest( override fun onLoadRequest(
@ -71,10 +72,8 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
private fun improveErrorType(errorType: ErrorType): ErrorType { private fun improveErrorType(errorType: ErrorType): ErrorType {
// This is not an ideal solution. For context, see: // This is not an ideal solution. For context, see:
// https://github.com/mozilla-mobile/android-components/pull/5068#issuecomment-558415367 // https://github.com/mozilla-mobile/android-components/pull/5068#issuecomment-558415367
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val activeNetwork: NetworkInfo? = cm.activeNetworkInfo val isConnected: Boolean = context.getSystemService<ConnectivityManager>()!!.isOnline()
@Suppress("DEPRECATION") // NetworkCallback is not appropriate for this use case
val isConnected: Boolean = activeNetwork?.isConnectedOrConnecting == true
return when { return when {
errorType == ErrorType.ERROR_UNKNOWN_HOST && !isConnected -> ErrorType.ERROR_NO_INTERNET errorType == ErrorType.ERROR_UNKNOWN_HOST && !isConnected -> ErrorType.ERROR_NO_INTERNET

View File

@ -0,0 +1,29 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.ext
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.os.Build
/**
* Checks for availability of network.
*
* For devices above [Build.VERSION_CODES.M] it even checks if there's internet flowing through it or not.
* */
fun ConnectivityManager.isOnline(network: Network? = null): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getNetworkCapabilities(network ?: activeNetwork)?.let {
it.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
it.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
} ?: false
} else {
// for devices below android M, there's no better way to get this.
// active network info can be null if there are no active networks.
@Suppress("Deprecation")
activeNetworkInfo?.isConnected ?: false
}
}

View File

@ -23,6 +23,7 @@ import kotlinx.coroutines.launch
import mozilla.components.concept.sync.DeviceCapability import mozilla.components.concept.sync.DeviceCapability
import mozilla.components.service.fxa.manager.FxaAccountManager import mozilla.components.service.fxa.manager.FxaAccountManager
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.isOnline
import org.mozilla.fenix.share.listadapters.AppShareOption import org.mozilla.fenix.share.listadapters.AppShareOption
import org.mozilla.fenix.share.listadapters.SyncShareOption import org.mozilla.fenix.share.listadapters.SyncShareOption
@ -36,17 +37,17 @@ class ShareViewModel(application: Application) : AndroidViewModel(application) {
@VisibleForTesting @VisibleForTesting
internal val networkCallback = object : ConnectivityManager.NetworkCallback() { internal val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onLost(network: Network?) = reloadDevices() override fun onLost(network: Network?) = reloadDevices(network)
override fun onAvailable(network: Network?) = reloadDevices() override fun onAvailable(network: Network?) = reloadDevices(network)
private fun reloadDevices() { private fun reloadDevices(network: Network?) {
viewModelScope.launch(IO) { viewModelScope.launch(IO) {
fxaAccountManager.authenticatedAccount() fxaAccountManager.authenticatedAccount()
?.deviceConstellation() ?.deviceConstellation()
?.refreshDevicesAsync() ?.refreshDevicesAsync()
?.await() ?.await()
val devicesShareOptions = buildDeviceList(fxaAccountManager) val devicesShareOptions = buildDeviceList(fxaAccountManager, network)
devicesListLiveData.postValue(devicesShareOptions) devicesListLiveData.postValue(devicesShareOptions)
} }
} }
@ -128,13 +129,12 @@ class ShareViewModel(application: Application) : AndroidViewModel(application) {
*/ */
@VisibleForTesting @VisibleForTesting
@WorkerThread @WorkerThread
internal fun buildDeviceList(accountManager: FxaAccountManager): List<SyncShareOption> { internal fun buildDeviceList(accountManager: FxaAccountManager, network: Network? = null): List<SyncShareOption> {
val activeNetwork = connectivityManager?.activeNetworkInfo
val account = accountManager.authenticatedAccount() val account = accountManager.authenticatedAccount()
return when { return when {
// No network // No network
activeNetwork?.isConnected != true -> listOf(SyncShareOption.Offline) connectivityManager?.isOnline(network) != true -> listOf(SyncShareOption.Offline)
// No account signed in // No account signed in
account == null -> listOf(SyncShareOption.SignIn) account == null -> listOf(SyncShareOption.SignIn)
// Account needs to be re-authenticated // Account needs to be re-authenticated

View File

@ -4,10 +4,14 @@
package org.mozilla.fenix package org.mozilla.fenix
import android.net.ConnectivityManager
import androidx.annotation.RawRes import androidx.annotation.RawRes
import androidx.core.content.getSystemService
import assertk.assertThat import assertk.assertThat
import assertk.assertions.isEqualTo import assertk.assertions.isEqualTo
import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
import io.mockk.mockkStatic
import kotlinx.coroutines.ObsoleteCoroutinesApi import kotlinx.coroutines.ObsoleteCoroutinesApi
import mozilla.components.browser.errorpages.ErrorPages import mozilla.components.browser.errorpages.ErrorPages
import mozilla.components.browser.errorpages.ErrorType import mozilla.components.browser.errorpages.ErrorType
@ -16,6 +20,7 @@ import mozilla.components.support.test.robolectric.testContext
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mozilla.fenix.ext.isOnline
import org.robolectric.RobolectricTestRunner import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config import org.robolectric.annotation.Config
@ -28,6 +33,11 @@ class AppRequestInterceptorTest {
@Before @Before
fun setUp() { fun setUp() {
mockkStatic("org.mozilla.fenix.ext.ConnectivityManagerKt")
every { testContext.getSystemService<ConnectivityManager>()!!.isOnline() } returns true
interceptor = AppRequestInterceptor(testContext) interceptor = AppRequestInterceptor(testContext)
} }

View File

@ -15,6 +15,7 @@ import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
import io.mockk.spyk import io.mockk.spyk
import io.mockk.verify import io.mockk.verify
import io.mockk.mockkStatic
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import mozilla.components.service.fxa.manager.FxaAccountManager import mozilla.components.service.fxa.manager.FxaAccountManager
import mozilla.components.support.test.robolectric.testContext import mozilla.components.support.test.robolectric.testContext
@ -25,6 +26,7 @@ import org.junit.runner.RunWith
import org.mozilla.fenix.TestApplication import org.mozilla.fenix.TestApplication
import org.mozilla.fenix.ext.application import org.mozilla.fenix.ext.application
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.isOnline
import org.mozilla.fenix.share.listadapters.AppShareOption import org.mozilla.fenix.share.listadapters.AppShareOption
import org.mozilla.fenix.share.listadapters.SyncShareOption import org.mozilla.fenix.share.listadapters.SyncShareOption
import org.robolectric.RobolectricTestRunner import org.robolectric.RobolectricTestRunner
@ -48,11 +50,12 @@ class ShareViewModelTest {
connectivityManager = mockk(relaxed = true) connectivityManager = mockk(relaxed = true)
fxaAccountManager = mockk(relaxed = true) fxaAccountManager = mockk(relaxed = true)
mockkStatic("org.mozilla.fenix.ext.ConnectivityManagerKt")
every { application.packageName } returns packageName every { application.packageName } returns packageName
every { application.packageManager } returns packageManager every { application.packageManager } returns packageManager
every { application.getSystemService<ConnectivityManager>() } returns connectivityManager every { application.getSystemService<ConnectivityManager>() } returns connectivityManager
every { application.components.backgroundServices.accountManager } returns fxaAccountManager every { application.components.backgroundServices.accountManager } returns fxaAccountManager
every { connectivityManager.activeNetworkInfo } returns mockk(relaxed = true)
viewModel = ShareViewModel(application) viewModel = ShareViewModel(application)
} }
@ -91,16 +94,16 @@ class ShareViewModelTest {
@Test @Test
fun `buildDevicesList returns offline option`() { fun `buildDevicesList returns offline option`() {
every { connectivityManager.activeNetworkInfo.isConnected } returns false every { connectivityManager.isOnline() } returns false
assertEquals(listOf(SyncShareOption.Offline), viewModel.buildDeviceList(fxaAccountManager)) assertEquals(listOf(SyncShareOption.Offline), viewModel.buildDeviceList(fxaAccountManager))
every { connectivityManager.activeNetworkInfo } returns null every { connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork) } returns null
assertEquals(listOf(SyncShareOption.Offline), viewModel.buildDeviceList(fxaAccountManager)) assertEquals(listOf(SyncShareOption.Offline), viewModel.buildDeviceList(fxaAccountManager))
} }
@Test @Test
fun `buildDevicesList returns sign-in option`() { fun `buildDevicesList returns sign-in option`() {
every { connectivityManager.activeNetworkInfo.isConnected } returns true every { connectivityManager.isOnline() } returns true
every { fxaAccountManager.authenticatedAccount() } returns null every { fxaAccountManager.authenticatedAccount() } returns null
assertEquals(listOf(SyncShareOption.SignIn), viewModel.buildDeviceList(fxaAccountManager)) assertEquals(listOf(SyncShareOption.SignIn), viewModel.buildDeviceList(fxaAccountManager))
@ -108,7 +111,7 @@ class ShareViewModelTest {
@Test @Test
fun `buildDevicesList returns reconnect option`() { fun `buildDevicesList returns reconnect option`() {
every { connectivityManager.activeNetworkInfo.isConnected } returns true every { connectivityManager.isOnline() } returns true
every { fxaAccountManager.authenticatedAccount() } returns mockk() every { fxaAccountManager.authenticatedAccount() } returns mockk()
every { fxaAccountManager.accountNeedsReauth() } returns true every { fxaAccountManager.accountNeedsReauth() } returns true