mirror of
https://github.com/bitwarden/android.git
synced 2024-11-21 17:05:44 +03:00
This PR adds Timber to the app (#4116)
This commit is contained in:
parent
5d85060260
commit
002fd06b72
23 changed files with 202 additions and 112 deletions
|
@ -171,6 +171,11 @@ The following is a list of all third-party dependencies included as part of the
|
||||||
- Purpose: A networking layer interface.
|
- Purpose: A networking layer interface.
|
||||||
- License: Apache 2.0
|
- License: Apache 2.0
|
||||||
|
|
||||||
|
- **Timber**
|
||||||
|
- https://github.com/JakeWharton/timber
|
||||||
|
- Purpose: Extensible logging library for Android.
|
||||||
|
- License: Apache 2.0
|
||||||
|
|
||||||
- **zxcvbn4j**
|
- **zxcvbn4j**
|
||||||
- https://github.com/nulab/zxcvbn4j
|
- https://github.com/nulab/zxcvbn4j
|
||||||
- Purpose: Password strength estimation.
|
- Purpose: Password strength estimation.
|
||||||
|
|
|
@ -75,6 +75,7 @@ android {
|
||||||
isMinifyEnabled = false
|
isMinifyEnabled = false
|
||||||
|
|
||||||
buildConfigField(type = "boolean", name = "HAS_DEBUG_MENU", value = "true")
|
buildConfigField(type = "boolean", name = "HAS_DEBUG_MENU", value = "true")
|
||||||
|
buildConfigField(type = "boolean", name = "HAS_LOGS_ENABLED", value = "true")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Beta and Release variants are identical except beta has a different package name
|
// Beta and Release variants are identical except beta has a different package name
|
||||||
|
@ -88,6 +89,7 @@ android {
|
||||||
)
|
)
|
||||||
|
|
||||||
buildConfigField(type = "boolean", name = "HAS_DEBUG_MENU", value = "false")
|
buildConfigField(type = "boolean", name = "HAS_DEBUG_MENU", value = "false")
|
||||||
|
buildConfigField(type = "boolean", name = "HAS_LOGS_ENABLED", value = "false")
|
||||||
}
|
}
|
||||||
release {
|
release {
|
||||||
isDebuggable = false
|
isDebuggable = false
|
||||||
|
@ -98,6 +100,7 @@ android {
|
||||||
)
|
)
|
||||||
|
|
||||||
buildConfigField(type = "boolean", name = "HAS_DEBUG_MENU", value = "false")
|
buildConfigField(type = "boolean", name = "HAS_DEBUG_MENU", value = "false")
|
||||||
|
buildConfigField(type = "boolean", name = "HAS_LOGS_ENABLED", value = "false")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,6 +203,7 @@ dependencies {
|
||||||
implementation(platform(libs.square.retrofit.bom))
|
implementation(platform(libs.square.retrofit.bom))
|
||||||
implementation(libs.square.retrofit)
|
implementation(libs.square.retrofit)
|
||||||
implementation(libs.square.retrofit.kotlinx.serialization)
|
implementation(libs.square.retrofit.kotlinx.serialization)
|
||||||
|
implementation(libs.timber)
|
||||||
implementation(libs.zxing.zxing.core)
|
implementation(libs.zxing.zxing.core)
|
||||||
|
|
||||||
// For now we are restricted to running Compose tests for debug builds only
|
// For now we are restricted to running Compose tests for debug builds only
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
package com.x8bit.bitwarden.data.platform.manager
|
|
||||||
|
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacyAppCenterMigrator
|
|
||||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CrashLogsManager implementation for F-droid flavor builds.
|
|
||||||
*/
|
|
||||||
class CrashLogsManagerImpl(
|
|
||||||
settingsRepository: SettingsRepository,
|
|
||||||
legacyAppCenterMigrator: LegacyAppCenterMigrator,
|
|
||||||
) : CrashLogsManager {
|
|
||||||
override var isEnabled: Boolean = true
|
|
||||||
|
|
||||||
override fun trackNonFatalException(throwable: Throwable) = Unit
|
|
||||||
}
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.x8bit.bitwarden.data.platform.manager
|
||||||
|
|
||||||
|
import com.x8bit.bitwarden.BuildConfig
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacyAppCenterMigrator
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [LogsManager] implementation for F-droid flavor builds.
|
||||||
|
*/
|
||||||
|
class LogsManagerImpl(
|
||||||
|
settingsRepository: SettingsRepository,
|
||||||
|
legacyAppCenterMigrator: LegacyAppCenterMigrator,
|
||||||
|
) : LogsManager {
|
||||||
|
init {
|
||||||
|
if (BuildConfig.HAS_LOGS_ENABLED) {
|
||||||
|
Timber.plant(Timber.DebugTree())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override var isEnabled: Boolean = false
|
||||||
|
|
||||||
|
override fun setUserData(userId: String?, environmentType: Environment.Type) = Unit
|
||||||
|
|
||||||
|
override fun trackNonFatalException(throwable: Throwable) = Unit
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ package com.x8bit.bitwarden
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import com.x8bit.bitwarden.data.auth.manager.AuthRequestNotificationManager
|
import com.x8bit.bitwarden.data.auth.manager.AuthRequestNotificationManager
|
||||||
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
|
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
|
||||||
import com.x8bit.bitwarden.data.platform.manager.CrashLogsManager
|
import com.x8bit.bitwarden.data.platform.manager.LogsManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.NetworkConfigManager
|
import com.x8bit.bitwarden.data.platform.manager.NetworkConfigManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.event.OrganizationEventManager
|
import com.x8bit.bitwarden.data.platform.manager.event.OrganizationEventManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.restriction.RestrictionManager
|
import com.x8bit.bitwarden.data.platform.manager.restriction.RestrictionManager
|
||||||
|
@ -19,10 +19,10 @@ class BitwardenApplication : Application() {
|
||||||
// Inject classes here that must be triggered on startup but are not otherwise consumed by
|
// Inject classes here that must be triggered on startup but are not otherwise consumed by
|
||||||
// other callers.
|
// other callers.
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var networkConfigManager: NetworkConfigManager
|
lateinit var logsManager: LogsManager
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var crashLogsManager: CrashLogsManager
|
lateinit var networkConfigManager: NetworkConfigManager
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var authRequestNotificationManager: AuthRequestNotificationManager
|
lateinit var authRequestNotificationManager: AuthRequestNotificationManager
|
||||||
|
|
|
@ -95,6 +95,7 @@ import com.x8bit.bitwarden.data.auth.util.toSdkParams
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.disk.ConfigDiskSource
|
import com.x8bit.bitwarden.data.platform.datasource.disk.ConfigDiskSource
|
||||||
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
|
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
|
||||||
|
import com.x8bit.bitwarden.data.platform.manager.LogsManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
||||||
|
@ -104,6 +105,7 @@ import com.x8bit.bitwarden.data.platform.manager.util.getActivePolicies
|
||||||
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
|
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
|
||||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||||
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.util.toEnvironmentUrls
|
||||||
import com.x8bit.bitwarden.data.platform.util.asFailure
|
import com.x8bit.bitwarden.data.platform.util.asFailure
|
||||||
import com.x8bit.bitwarden.data.platform.util.asSuccess
|
import com.x8bit.bitwarden.data.platform.util.asSuccess
|
||||||
import com.x8bit.bitwarden.data.platform.util.flatMap
|
import com.x8bit.bitwarden.data.platform.util.flatMap
|
||||||
|
@ -164,7 +166,8 @@ class AuthRepositoryImpl(
|
||||||
private val userLogoutManager: UserLogoutManager,
|
private val userLogoutManager: UserLogoutManager,
|
||||||
private val policyManager: PolicyManager,
|
private val policyManager: PolicyManager,
|
||||||
private val featureFlagManager: FeatureFlagManager,
|
private val featureFlagManager: FeatureFlagManager,
|
||||||
private val firstTimeActionManager: FirstTimeActionManager,
|
firstTimeActionManager: FirstTimeActionManager,
|
||||||
|
logsManager: LogsManager,
|
||||||
pushManager: PushManager,
|
pushManager: PushManager,
|
||||||
dispatcherManager: DispatcherManager,
|
dispatcherManager: DispatcherManager,
|
||||||
) : AuthRepository,
|
) : AuthRepository,
|
||||||
|
@ -363,6 +366,24 @@ class AuthRepositoryImpl(
|
||||||
featureFlagManager.getFeatureFlag(FlagKey.OnboardingCarousel)
|
featureFlagManager.getFeatureFlag(FlagKey.OnboardingCarousel)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
combine(
|
||||||
|
mutableHasPendingAccountAdditionStateFlow,
|
||||||
|
authDiskSource.userStateFlow,
|
||||||
|
environmentRepository.environmentStateFlow,
|
||||||
|
) { hasPendingAddition, userState, environment ->
|
||||||
|
logsManager.setUserData(
|
||||||
|
userId = userState?.activeUserId.takeUnless { hasPendingAddition },
|
||||||
|
environmentType = userState
|
||||||
|
?.activeAccount
|
||||||
|
?.settings
|
||||||
|
?.environmentUrlData
|
||||||
|
?.toEnvironmentUrls()
|
||||||
|
?.type
|
||||||
|
.takeUnless { hasPendingAddition }
|
||||||
|
?: environment.type,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.launchIn(unconfinedScope)
|
||||||
pushManager
|
pushManager
|
||||||
.syncOrgKeysFlow
|
.syncOrgKeysFlow
|
||||||
.onEach {
|
.onEach {
|
||||||
|
|
|
@ -16,6 +16,7 @@ import com.x8bit.bitwarden.data.auth.repository.AuthRepositoryImpl
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.disk.ConfigDiskSource
|
import com.x8bit.bitwarden.data.platform.datasource.disk.ConfigDiskSource
|
||||||
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
|
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
|
||||||
|
import com.x8bit.bitwarden.data.platform.manager.LogsManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
||||||
|
@ -60,6 +61,7 @@ object AuthRepositoryModule {
|
||||||
policyManager: PolicyManager,
|
policyManager: PolicyManager,
|
||||||
featureFlagManager: FeatureFlagManager,
|
featureFlagManager: FeatureFlagManager,
|
||||||
firstTimeActionManager: FirstTimeActionManager,
|
firstTimeActionManager: FirstTimeActionManager,
|
||||||
|
logsManager: LogsManager,
|
||||||
): AuthRepository = AuthRepositoryImpl(
|
): AuthRepository = AuthRepositoryImpl(
|
||||||
accountsService = accountsService,
|
accountsService = accountsService,
|
||||||
devicesService = devicesService,
|
devicesService = devicesService,
|
||||||
|
@ -82,5 +84,6 @@ object AuthRepositoryModule {
|
||||||
policyManager = policyManager,
|
policyManager = policyManager,
|
||||||
featureFlagManager = featureFlagManager,
|
featureFlagManager = featureFlagManager,
|
||||||
firstTimeActionManager = firstTimeActionManager,
|
firstTimeActionManager = firstTimeActionManager,
|
||||||
|
logsManager = logsManager,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package com.x8bit.bitwarden.data.autofill.accessibility.manager
|
package com.x8bit.bitwarden.data.autofill.accessibility.manager
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Log
|
|
||||||
import android.view.accessibility.AccessibilityNodeInfo
|
import android.view.accessibility.AccessibilityNodeInfo
|
||||||
import com.x8bit.bitwarden.BuildConfig
|
|
||||||
import com.x8bit.bitwarden.data.autofill.accessibility.util.getKnownUsernameFieldNull
|
import com.x8bit.bitwarden.data.autofill.accessibility.util.getKnownUsernameFieldNull
|
||||||
import com.x8bit.bitwarden.data.autofill.accessibility.util.isUsername
|
import com.x8bit.bitwarden.data.autofill.accessibility.util.isUsername
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
private const val MAX_NODE_COUNT: Int = 100
|
private const val MAX_NODE_COUNT: Int = 100
|
||||||
|
|
||||||
|
@ -90,7 +89,6 @@ class AccessibilityNodeInfoManagerImpl : AccessibilityNodeInfoManager {
|
||||||
?.let { allNodes.getOrNull(index = allNodes.indexOf(element = it) - 1) }
|
?.let { allNodes.getOrNull(index = allNodes.indexOf(element = it) - 1) }
|
||||||
|
|
||||||
private fun log(message: String) {
|
private fun log(message: String) {
|
||||||
if (!BuildConfig.DEBUG) return
|
Timber.i(message)
|
||||||
Log.i("AccessibilityNodeInfoManager", message)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import com.x8bit.bitwarden.data.autofill.processor.AutofillProcessor
|
||||||
import com.x8bit.bitwarden.data.autofill.processor.AutofillProcessorImpl
|
import com.x8bit.bitwarden.data.autofill.processor.AutofillProcessorImpl
|
||||||
import com.x8bit.bitwarden.data.autofill.provider.AutofillCipherProvider
|
import com.x8bit.bitwarden.data.autofill.provider.AutofillCipherProvider
|
||||||
import com.x8bit.bitwarden.data.autofill.provider.AutofillCipherProviderImpl
|
import com.x8bit.bitwarden.data.autofill.provider.AutofillCipherProviderImpl
|
||||||
import com.x8bit.bitwarden.data.platform.manager.CrashLogsManager
|
import com.x8bit.bitwarden.data.platform.manager.LogsManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.ciphermatching.CipherMatchingManager
|
import com.x8bit.bitwarden.data.platform.manager.ciphermatching.CipherMatchingManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
||||||
|
@ -121,7 +121,7 @@ object AutofillModule {
|
||||||
policyManager: PolicyManager,
|
policyManager: PolicyManager,
|
||||||
saveInfoBuilder: SaveInfoBuilder,
|
saveInfoBuilder: SaveInfoBuilder,
|
||||||
settingsRepository: SettingsRepository,
|
settingsRepository: SettingsRepository,
|
||||||
crashLogsManager: CrashLogsManager,
|
logsManager: LogsManager,
|
||||||
): AutofillProcessor =
|
): AutofillProcessor =
|
||||||
AutofillProcessorImpl(
|
AutofillProcessorImpl(
|
||||||
dispatcherManager = dispatcherManager,
|
dispatcherManager = dispatcherManager,
|
||||||
|
@ -131,7 +131,7 @@ object AutofillModule {
|
||||||
policyManager = policyManager,
|
policyManager = policyManager,
|
||||||
saveInfoBuilder = saveInfoBuilder,
|
saveInfoBuilder = saveInfoBuilder,
|
||||||
settingsRepository = settingsRepository,
|
settingsRepository = settingsRepository,
|
||||||
crashLogsManager = crashLogsManager,
|
logsManager = logsManager,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
|
|
|
@ -13,7 +13,7 @@ import com.x8bit.bitwarden.data.autofill.model.AutofillRequest
|
||||||
import com.x8bit.bitwarden.data.autofill.parser.AutofillParser
|
import com.x8bit.bitwarden.data.autofill.parser.AutofillParser
|
||||||
import com.x8bit.bitwarden.data.autofill.util.createAutofillSavedItemIntentSender
|
import com.x8bit.bitwarden.data.autofill.util.createAutofillSavedItemIntentSender
|
||||||
import com.x8bit.bitwarden.data.autofill.util.toAutofillSaveItem
|
import com.x8bit.bitwarden.data.autofill.util.toAutofillSaveItem
|
||||||
import com.x8bit.bitwarden.data.platform.manager.CrashLogsManager
|
import com.x8bit.bitwarden.data.platform.manager.LogsManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
||||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||||
|
@ -35,7 +35,7 @@ class AutofillProcessorImpl(
|
||||||
private val parser: AutofillParser,
|
private val parser: AutofillParser,
|
||||||
private val saveInfoBuilder: SaveInfoBuilder,
|
private val saveInfoBuilder: SaveInfoBuilder,
|
||||||
private val settingsRepository: SettingsRepository,
|
private val settingsRepository: SettingsRepository,
|
||||||
private val crashLogsManager: CrashLogsManager,
|
private val logsManager: LogsManager,
|
||||||
) : AutofillProcessor {
|
) : AutofillProcessor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -146,7 +146,7 @@ class AutofillProcessorImpl(
|
||||||
} catch (e: RuntimeException) {
|
} catch (e: RuntimeException) {
|
||||||
// This is to catch any TransactionTooLargeExceptions that could occur here.
|
// This is to catch any TransactionTooLargeExceptions that could occur here.
|
||||||
// These exceptions get wrapped as a RuntimeException.
|
// These exceptions get wrapped as a RuntimeException.
|
||||||
crashLogsManager.trackNonFatalException(e)
|
logsManager.trackNonFatalException(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import retrofit2.Call
|
||||||
import retrofit2.Callback
|
import retrofit2.Callback
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
|
import timber.log.Timber
|
||||||
import java.lang.reflect.Type
|
import java.lang.reflect.Type
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,6 +20,7 @@ private const val NO_CONTENT_RESPONSE_CODE: Int = 204
|
||||||
/**
|
/**
|
||||||
* A [Call] for wrapping a network request into a [Result].
|
* A [Call] for wrapping a network request into a [Result].
|
||||||
*/
|
*/
|
||||||
|
@Suppress("TooManyFunctions")
|
||||||
class ResultCall<T>(
|
class ResultCall<T>(
|
||||||
private val backingCall: Call<T>,
|
private val backingCall: Call<T>,
|
||||||
private val successType: Type,
|
private val successType: Type,
|
||||||
|
@ -34,7 +36,7 @@ class ResultCall<T>(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<T>, t: Throwable) {
|
override fun onFailure(call: Call<T>, t: Throwable) {
|
||||||
callback.onResponse(this@ResultCall, Response.success(t.asFailure()))
|
callback.onResponse(this@ResultCall, Response.success(t.toFailure()))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -44,9 +46,9 @@ class ResultCall<T>(
|
||||||
try {
|
try {
|
||||||
Response.success(backingCall.execute().toResult())
|
Response.success(backingCall.execute().toResult())
|
||||||
} catch (ioException: IOException) {
|
} catch (ioException: IOException) {
|
||||||
Response.success(ioException.asFailure())
|
Response.success(ioException.toFailure())
|
||||||
} catch (runtimeException: RuntimeException) {
|
} catch (runtimeException: RuntimeException) {
|
||||||
Response.success(runtimeException.asFailure())
|
Response.success(runtimeException.toFailure())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isCanceled(): Boolean = backingCall.isCanceled
|
override fun isCanceled(): Boolean = backingCall.isCanceled
|
||||||
|
@ -62,9 +64,14 @@ class ResultCall<T>(
|
||||||
*/
|
*/
|
||||||
fun executeForResult(): Result<T> = requireNotNull(execute().body())
|
fun executeForResult(): Result<T> = requireNotNull(execute().body())
|
||||||
|
|
||||||
|
private fun Throwable.toFailure(): Result<T> =
|
||||||
|
this
|
||||||
|
.also { Timber.w(it, "Network Error: ${backingCall.request().url}") }
|
||||||
|
.asFailure()
|
||||||
|
|
||||||
private fun Response<T>.toResult(): Result<T> =
|
private fun Response<T>.toResult(): Result<T> =
|
||||||
if (!this.isSuccessful) {
|
if (!this.isSuccessful) {
|
||||||
HttpException(this).asFailure()
|
HttpException(this).toFailure()
|
||||||
} else {
|
} else {
|
||||||
val body = this.body()
|
val body = this.body()
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
@ -76,7 +83,7 @@ class ResultCall<T>(
|
||||||
// We allow null for 204's, just return null.
|
// We allow null for 204's, just return null.
|
||||||
this.code() == NO_CONTENT_RESPONSE_CODE -> (null as T).asSuccess()
|
this.code() == NO_CONTENT_RESPONSE_CODE -> (null as T).asSuccess()
|
||||||
// All other null bodies result in an error.
|
// All other null bodies result in an error.
|
||||||
else -> IllegalStateException("Unexpected null body!").asFailure()
|
else -> IllegalStateException("Unexpected null body!").toFailure()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package com.x8bit.bitwarden.data.platform.datasource.network.retrofit
|
package com.x8bit.bitwarden.data.platform.datasource.network.retrofit
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import com.x8bit.bitwarden.BuildConfig
|
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.authenticator.RefreshAuthenticator
|
import com.x8bit.bitwarden.data.platform.datasource.network.authenticator.RefreshAuthenticator
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.core.ResultCallAdapterFactory
|
import com.x8bit.bitwarden.data.platform.datasource.network.core.ResultCallAdapterFactory
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.AuthTokenInterceptor
|
import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.AuthTokenInterceptor
|
||||||
|
@ -15,8 +13,7 @@ import okhttp3.OkHttpClient
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.kotlinx.serialization.asConverterFactory
|
import retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||||||
|
import timber.log.Timber
|
||||||
private const val MAX_LOG_MESSAGE_LENGTH: Int = 4000
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Primary implementation of [Retrofits].
|
* Primary implementation of [Retrofits].
|
||||||
|
@ -79,20 +76,10 @@ class RetrofitsImpl(
|
||||||
|
|
||||||
//region Helper properties and functions
|
//region Helper properties and functions
|
||||||
private val loggingInterceptor: HttpLoggingInterceptor by lazy {
|
private val loggingInterceptor: HttpLoggingInterceptor by lazy {
|
||||||
HttpLoggingInterceptor { message ->
|
HttpLoggingInterceptor { message -> Timber.tag("BitwardenNetworkClient").d(message) }
|
||||||
message.chunked(size = MAX_LOG_MESSAGE_LENGTH).forEach { chunk ->
|
|
||||||
Log.d("BitwardenNetworkClient", chunk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.apply {
|
.apply {
|
||||||
redactHeader(name = HEADER_KEY_AUTHORIZATION)
|
redactHeader(name = HEADER_KEY_AUTHORIZATION)
|
||||||
setLevel(
|
setLevel(HttpLoggingInterceptor.Level.BODY)
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
HttpLoggingInterceptor.Level.BODY
|
|
||||||
} else {
|
|
||||||
HttpLoggingInterceptor.Level.NONE
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package com.x8bit.bitwarden.data.platform.datasource.sdk
|
package com.x8bit.bitwarden.data.platform.datasource.sdk
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import com.bitwarden.sdk.Client
|
import com.bitwarden.sdk.Client
|
||||||
import com.x8bit.bitwarden.BuildConfig
|
|
||||||
import com.x8bit.bitwarden.data.platform.manager.SdkClientManager
|
import com.x8bit.bitwarden.data.platform.manager.SdkClientManager
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for simplifying sdk interactions.
|
* Base class for simplifying sdk interactions.
|
||||||
|
@ -27,9 +26,5 @@ abstract class BaseSdkSource(
|
||||||
protected inline fun <T, R> T.runCatchingWithLogs(
|
protected inline fun <T, R> T.runCatchingWithLogs(
|
||||||
block: T.() -> R,
|
block: T.() -> R,
|
||||||
): Result<R> = runCatching(block = block)
|
): Result<R> = runCatching(block = block)
|
||||||
.onFailure {
|
.onFailure { Timber.w(it) }
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.w(this@BaseSdkSource::class.java.simpleName, it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package com.x8bit.bitwarden.data.platform.manager
|
package com.x8bit.bitwarden.data.platform.manager
|
||||||
|
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementations of this interface provide a way to enable or disable the collection of crash
|
* Implementations of this interface provide a way to enable or disable the collection of crash
|
||||||
* logs, giving control over whether crash logs are generated and stored.
|
* logs, giving control over whether crash logs are generated and stored.
|
||||||
*/
|
*/
|
||||||
interface CrashLogsManager {
|
interface LogsManager {
|
||||||
/**
|
/**
|
||||||
* Gets or sets whether the collection of crash logs is enabled.
|
* Gets or sets whether the collection of crash logs is enabled.
|
||||||
*/
|
*/
|
||||||
|
@ -14,4 +16,9 @@ interface CrashLogsManager {
|
||||||
* Tracks a [Throwable] if logs are enabled.
|
* Tracks a [Throwable] if logs are enabled.
|
||||||
*/
|
*/
|
||||||
fun trackNonFatalException(throwable: Throwable)
|
fun trackNonFatalException(throwable: Throwable)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks the current user data.
|
||||||
|
*/
|
||||||
|
fun setUserData(userId: String?, environmentType: Environment.Type)
|
||||||
}
|
}
|
|
@ -19,13 +19,13 @@ import com.x8bit.bitwarden.data.platform.manager.AssetManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.AssetManagerImpl
|
import com.x8bit.bitwarden.data.platform.manager.AssetManagerImpl
|
||||||
import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManager
|
import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManagerImpl
|
import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManagerImpl
|
||||||
import com.x8bit.bitwarden.data.platform.manager.CrashLogsManager
|
|
||||||
import com.x8bit.bitwarden.data.platform.manager.CrashLogsManagerImpl
|
|
||||||
import com.x8bit.bitwarden.data.platform.manager.DebugMenuFeatureFlagManagerImpl
|
import com.x8bit.bitwarden.data.platform.manager.DebugMenuFeatureFlagManagerImpl
|
||||||
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManagerImpl
|
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManagerImpl
|
||||||
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
|
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManagerImpl
|
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManagerImpl
|
||||||
|
import com.x8bit.bitwarden.data.platform.manager.LogsManager
|
||||||
|
import com.x8bit.bitwarden.data.platform.manager.LogsManagerImpl
|
||||||
import com.x8bit.bitwarden.data.platform.manager.NetworkConfigManager
|
import com.x8bit.bitwarden.data.platform.manager.NetworkConfigManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.NetworkConfigManagerImpl
|
import com.x8bit.bitwarden.data.platform.manager.NetworkConfigManagerImpl
|
||||||
import com.x8bit.bitwarden.data.platform.manager.NetworkConnectionManager
|
import com.x8bit.bitwarden.data.platform.manager.NetworkConnectionManager
|
||||||
|
@ -238,10 +238,10 @@ object PlatformManagerModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideCrashLogsManager(
|
fun provideLogsManager(
|
||||||
legacyAppCenterMigrator: LegacyAppCenterMigrator,
|
legacyAppCenterMigrator: LegacyAppCenterMigrator,
|
||||||
settingsRepository: SettingsRepository,
|
settingsRepository: SettingsRepository,
|
||||||
): CrashLogsManager = CrashLogsManagerImpl(
|
): LogsManager = LogsManagerImpl(
|
||||||
settingsRepository = settingsRepository,
|
settingsRepository = settingsRepository,
|
||||||
legacyAppCenterMigrator = legacyAppCenterMigrator,
|
legacyAppCenterMigrator = legacyAppCenterMigrator,
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,7 +5,7 @@ import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.x8bit.bitwarden.BuildConfig
|
import com.x8bit.bitwarden.BuildConfig
|
||||||
import com.x8bit.bitwarden.R
|
import com.x8bit.bitwarden.R
|
||||||
import com.x8bit.bitwarden.data.platform.manager.CrashLogsManager
|
import com.x8bit.bitwarden.data.platform.manager.LogsManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
||||||
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
|
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
|
||||||
import com.x8bit.bitwarden.data.platform.repository.util.baseWebVaultUrlOrDefault
|
import com.x8bit.bitwarden.data.platform.repository.util.baseWebVaultUrlOrDefault
|
||||||
|
@ -33,12 +33,12 @@ class AboutViewModel @Inject constructor(
|
||||||
private val savedStateHandle: SavedStateHandle,
|
private val savedStateHandle: SavedStateHandle,
|
||||||
private val clipboardManager: BitwardenClipboardManager,
|
private val clipboardManager: BitwardenClipboardManager,
|
||||||
clock: Clock,
|
clock: Clock,
|
||||||
private val crashLogsManager: CrashLogsManager,
|
private val logsManager: LogsManager,
|
||||||
private val environmentRepository: EnvironmentRepository,
|
private val environmentRepository: EnvironmentRepository,
|
||||||
) : BaseViewModel<AboutState, AboutEvent, AboutAction>(
|
) : BaseViewModel<AboutState, AboutEvent, AboutAction>(
|
||||||
initialState = savedStateHandle[KEY_STATE] ?: createInitialState(
|
initialState = savedStateHandle[KEY_STATE] ?: createInitialState(
|
||||||
clock = clock,
|
clock = clock,
|
||||||
isCrashLoggingEnabled = crashLogsManager.isEnabled,
|
isCrashLoggingEnabled = logsManager.isEnabled,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
init {
|
init {
|
||||||
|
@ -84,7 +84,7 @@ class AboutViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSubmitCrashLogsClick(action: AboutAction.SubmitCrashLogsClick) {
|
private fun handleSubmitCrashLogsClick(action: AboutAction.SubmitCrashLogsClick) {
|
||||||
crashLogsManager.isEnabled = action.enabled
|
logsManager.isEnabled = action.enabled
|
||||||
mutableStateFlow.update { currentState ->
|
mutableStateFlow.update { currentState ->
|
||||||
currentState.copy(isSubmitCrashLogsEnabled = action.enabled)
|
currentState.copy(isSubmitCrashLogsEnabled = action.enabled)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
package com.x8bit.bitwarden.data.platform.manager
|
|
||||||
|
|
||||||
import com.google.firebase.crashlytics.ktx.crashlytics
|
|
||||||
import com.google.firebase.ktx.Firebase
|
|
||||||
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
|
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacyAppCenterMigrator
|
|
||||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CrashLogsManager implementation for standard flavor builds.
|
|
||||||
*/
|
|
||||||
@OmitFromCoverage
|
|
||||||
class CrashLogsManagerImpl(
|
|
||||||
private val settingsRepository: SettingsRepository,
|
|
||||||
legacyAppCenterMigrator: LegacyAppCenterMigrator,
|
|
||||||
) : CrashLogsManager {
|
|
||||||
|
|
||||||
override var isEnabled: Boolean
|
|
||||||
get() = settingsRepository.isCrashLoggingEnabled
|
|
||||||
set(value) {
|
|
||||||
settingsRepository.isCrashLoggingEnabled = value
|
|
||||||
Firebase.crashlytics.isCrashlyticsCollectionEnabled = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun trackNonFatalException(throwable: Throwable) {
|
|
||||||
if (settingsRepository.isCrashLoggingEnabled) {
|
|
||||||
Firebase.crashlytics.recordException(throwable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
legacyAppCenterMigrator.migrateIfNecessary()
|
|
||||||
isEnabled = settingsRepository.isCrashLoggingEnabled
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
package com.x8bit.bitwarden.data.platform.manager
|
||||||
|
|
||||||
|
import com.google.firebase.crashlytics.ktx.crashlytics
|
||||||
|
import com.google.firebase.ktx.Firebase
|
||||||
|
import com.x8bit.bitwarden.BuildConfig
|
||||||
|
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacyAppCenterMigrator
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [LogsManager] implementation for standard flavor builds.
|
||||||
|
*/
|
||||||
|
@OmitFromCoverage
|
||||||
|
class LogsManagerImpl(
|
||||||
|
private val settingsRepository: SettingsRepository,
|
||||||
|
legacyAppCenterMigrator: LegacyAppCenterMigrator,
|
||||||
|
) : LogsManager {
|
||||||
|
|
||||||
|
private val nonfatalErrorTree: NonfatalErrorTree = NonfatalErrorTree()
|
||||||
|
|
||||||
|
override var isEnabled: Boolean
|
||||||
|
get() = settingsRepository.isCrashLoggingEnabled
|
||||||
|
set(value) {
|
||||||
|
settingsRepository.isCrashLoggingEnabled = value
|
||||||
|
Firebase.crashlytics.isCrashlyticsCollectionEnabled = value
|
||||||
|
if (BuildConfig.HAS_LOGS_ENABLED) {
|
||||||
|
Timber.plant(Timber.DebugTree())
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
|
Timber.plant(nonfatalErrorTree)
|
||||||
|
} else {
|
||||||
|
Timber.uproot(nonfatalErrorTree)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setUserData(userId: String?, environmentType: Environment.Type) {
|
||||||
|
Firebase.crashlytics.setUserId(userId.orEmpty())
|
||||||
|
Firebase.crashlytics.setCustomKey(
|
||||||
|
if (userId == null) "PreAuthRegion" else "Region",
|
||||||
|
environmentType.toString(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun trackNonFatalException(throwable: Throwable) {
|
||||||
|
if (isEnabled) {
|
||||||
|
Firebase.crashlytics.recordException(throwable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
legacyAppCenterMigrator.migrateIfNecessary()
|
||||||
|
isEnabled = settingsRepository.isCrashLoggingEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class NonfatalErrorTree : Timber.Tree() {
|
||||||
|
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||||
|
t?.let { trackNonFatalException(BitwardenNonfatalException(message, it)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BitwardenNonfatalException(
|
||||||
|
message: String,
|
||||||
|
throwable: Throwable,
|
||||||
|
) : Exception(message, throwable)
|
|
@ -102,6 +102,7 @@ import com.x8bit.bitwarden.data.platform.datasource.disk.util.FakeConfigDiskSour
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.model.ConfigResponseJson
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.ConfigResponseJson
|
||||||
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
|
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
|
||||||
|
import com.x8bit.bitwarden.data.platform.manager.LogsManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
||||||
|
@ -249,6 +250,9 @@ class AuthRepositoryTest {
|
||||||
every { currentOrDefaultUserFirstTimeState } returns FIRST_TIME_STATE
|
every { currentOrDefaultUserFirstTimeState } returns FIRST_TIME_STATE
|
||||||
every { firstTimeStateFlow } returns MutableStateFlow(FIRST_TIME_STATE)
|
every { firstTimeStateFlow } returns MutableStateFlow(FIRST_TIME_STATE)
|
||||||
}
|
}
|
||||||
|
private val logsManager: LogsManager = mockk {
|
||||||
|
every { setUserData(userId = any(), environmentType = any()) } just runs
|
||||||
|
}
|
||||||
|
|
||||||
private val repository = AuthRepositoryImpl(
|
private val repository = AuthRepositoryImpl(
|
||||||
accountsService = accountsService,
|
accountsService = accountsService,
|
||||||
|
@ -272,6 +276,7 @@ class AuthRepositoryTest {
|
||||||
policyManager = policyManager,
|
policyManager = policyManager,
|
||||||
featureFlagManager = featureFlagManager,
|
featureFlagManager = featureFlagManager,
|
||||||
firstTimeActionManager = firstTimeActionManager,
|
firstTimeActionManager = firstTimeActionManager,
|
||||||
|
logsManager = logsManager,
|
||||||
)
|
)
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
|
|
@ -22,7 +22,7 @@ import com.x8bit.bitwarden.data.autofill.parser.AutofillParser
|
||||||
import com.x8bit.bitwarden.data.autofill.util.createAutofillSavedItemIntentSender
|
import com.x8bit.bitwarden.data.autofill.util.createAutofillSavedItemIntentSender
|
||||||
import com.x8bit.bitwarden.data.autofill.util.toAutofillSaveItem
|
import com.x8bit.bitwarden.data.autofill.util.toAutofillSaveItem
|
||||||
import com.x8bit.bitwarden.data.platform.base.FakeDispatcherManager
|
import com.x8bit.bitwarden.data.platform.base.FakeDispatcherManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.CrashLogsManager
|
import com.x8bit.bitwarden.data.platform.manager.LogsManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
||||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
|
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
|
||||||
|
@ -57,7 +57,7 @@ class AutofillProcessorTest {
|
||||||
private val policyManager: PolicyManager = mockk()
|
private val policyManager: PolicyManager = mockk()
|
||||||
private val saveInfoBuilder: SaveInfoBuilder = mockk()
|
private val saveInfoBuilder: SaveInfoBuilder = mockk()
|
||||||
private val settingsRepository: SettingsRepository = mockk()
|
private val settingsRepository: SettingsRepository = mockk()
|
||||||
private val crashLogsManager: CrashLogsManager = mockk()
|
private val logsManager: LogsManager = mockk()
|
||||||
|
|
||||||
private val appInfo: AutofillAppInfo = AutofillAppInfo(
|
private val appInfo: AutofillAppInfo = AutofillAppInfo(
|
||||||
context = mockk(),
|
context = mockk(),
|
||||||
|
@ -79,7 +79,7 @@ class AutofillProcessorTest {
|
||||||
policyManager = policyManager,
|
policyManager = policyManager,
|
||||||
saveInfoBuilder = saveInfoBuilder,
|
saveInfoBuilder = saveInfoBuilder,
|
||||||
settingsRepository = settingsRepository,
|
settingsRepository = settingsRepository,
|
||||||
crashLogsManager = crashLogsManager,
|
logsManager = logsManager,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ class AutofillProcessorTest {
|
||||||
} returns fillResponse
|
} returns fillResponse
|
||||||
val runtimeException = RuntimeException("TransactionToLarge")
|
val runtimeException = RuntimeException("TransactionToLarge")
|
||||||
every { fillCallback.onSuccess(fillResponse) } throws runtimeException
|
every { fillCallback.onSuccess(fillResponse) } throws runtimeException
|
||||||
every { crashLogsManager.trackNonFatalException(runtimeException) } just runs
|
every { logsManager.trackNonFatalException(runtimeException) } just runs
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
autofillProcessor.processFillRequest(
|
autofillProcessor.processFillRequest(
|
||||||
|
@ -271,7 +271,7 @@ class AutofillProcessorTest {
|
||||||
saveInfo = saveInfo,
|
saveInfo = saveInfo,
|
||||||
)
|
)
|
||||||
fillCallback.onSuccess(fillResponse)
|
fillCallback.onSuccess(fillResponse)
|
||||||
crashLogsManager.trackNonFatalException(runtimeException)
|
logsManager.trackNonFatalException(runtimeException)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.platform.datasource.network.util
|
||||||
import com.x8bit.bitwarden.data.platform.util.asSuccess
|
import com.x8bit.bitwarden.data.platform.util.asSuccess
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
|
import okhttp3.Request
|
||||||
import okhttp3.ResponseBody.Companion.toResponseBody
|
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
import org.junit.jupiter.api.Assertions.assertTrue
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
|
@ -15,7 +16,11 @@ class CallExtensionsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `executeForResult returns failure when execute throws IOException`() {
|
fun `executeForResult returns failure when execute throws IOException`() {
|
||||||
|
val request = mockk<Request> {
|
||||||
|
every { url } returns mockk()
|
||||||
|
}
|
||||||
val call = mockk<Call<Unit>> {
|
val call = mockk<Call<Unit>> {
|
||||||
|
every { request() } returns request
|
||||||
every { execute() } throws IOException("Fail")
|
every { execute() } throws IOException("Fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +31,11 @@ class CallExtensionsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `executeForResult returns failure when execute throws RuntimeException`() {
|
fun `executeForResult returns failure when execute throws RuntimeException`() {
|
||||||
|
val request = mockk<Request> {
|
||||||
|
every { url } returns mockk()
|
||||||
|
}
|
||||||
val call = mockk<Call<Unit>> {
|
val call = mockk<Call<Unit>> {
|
||||||
|
every { request() } returns request
|
||||||
every { execute() } throws RuntimeException("Fail")
|
every { execute() } throws RuntimeException("Fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +46,11 @@ class CallExtensionsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `executeForResult returns failure when response is failure`() {
|
fun `executeForResult returns failure when response is failure`() {
|
||||||
|
val request = mockk<Request> {
|
||||||
|
every { url } returns mockk()
|
||||||
|
}
|
||||||
val call = mockk<Call<Unit>> {
|
val call = mockk<Call<Unit>> {
|
||||||
|
every { request() } returns request
|
||||||
every { execute() } returns Response.error(400, "".toResponseBody())
|
every { execute() } returns Response.error(400, "".toResponseBody())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ package com.x8bit.bitwarden.ui.platform.feature.settings.about
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import app.cash.turbine.test
|
import app.cash.turbine.test
|
||||||
import com.x8bit.bitwarden.BuildConfig
|
import com.x8bit.bitwarden.BuildConfig
|
||||||
import com.x8bit.bitwarden.data.platform.manager.CrashLogsManager
|
import com.x8bit.bitwarden.data.platform.manager.LogsManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
||||||
import com.x8bit.bitwarden.data.platform.repository.util.FakeEnvironmentRepository
|
import com.x8bit.bitwarden.data.platform.repository.util.FakeEnvironmentRepository
|
||||||
import com.x8bit.bitwarden.data.platform.repository.util.baseWebVaultUrlOrDefault
|
import com.x8bit.bitwarden.data.platform.repository.util.baseWebVaultUrlOrDefault
|
||||||
|
@ -30,7 +30,7 @@ class AboutViewModelTest : BaseViewModelTest() {
|
||||||
|
|
||||||
private val environmentRepository = FakeEnvironmentRepository()
|
private val environmentRepository = FakeEnvironmentRepository()
|
||||||
private val clipboardManager: BitwardenClipboardManager = mockk()
|
private val clipboardManager: BitwardenClipboardManager = mockk()
|
||||||
private val crashLogsManager: CrashLogsManager = mockk {
|
private val logsManager: LogsManager = mockk {
|
||||||
every { isEnabled } returns false
|
every { isEnabled } returns false
|
||||||
every { isEnabled = any() } just runs
|
every { isEnabled = any() } just runs
|
||||||
}
|
}
|
||||||
|
@ -99,12 +99,12 @@ class AboutViewModelTest : BaseViewModelTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `on SubmitCrashLogsClick should update crashLogsManager isEnabled`() = runTest {
|
fun `on SubmitCrashLogsClick should update LogsManager isEnabled`() = runTest {
|
||||||
val viewModel = createViewModel(DEFAULT_ABOUT_STATE)
|
val viewModel = createViewModel(DEFAULT_ABOUT_STATE)
|
||||||
|
|
||||||
viewModel.trySendAction(AboutAction.SubmitCrashLogsClick(true))
|
viewModel.trySendAction(AboutAction.SubmitCrashLogsClick(true))
|
||||||
|
|
||||||
coVerify(exactly = 1) { crashLogsManager.isEnabled = true }
|
coVerify(exactly = 1) { logsManager.isEnabled = true }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -153,7 +153,7 @@ class AboutViewModelTest : BaseViewModelTest() {
|
||||||
clipboardManager = clipboardManager,
|
clipboardManager = clipboardManager,
|
||||||
clock = fixedClock,
|
clock = fixedClock,
|
||||||
environmentRepository = environmentRepository,
|
environmentRepository = environmentRepository,
|
||||||
crashLogsManager = crashLogsManager,
|
logsManager = logsManager,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ okhttp = "4.12.0"
|
||||||
retrofitBom = "2.11.0"
|
retrofitBom = "2.11.0"
|
||||||
robolectric = "4.13"
|
robolectric = "4.13"
|
||||||
sonarqube = "5.1.0.4882"
|
sonarqube = "5.1.0.4882"
|
||||||
|
timber = "5.0.1"
|
||||||
turbine = "1.2.0"
|
turbine = "1.2.0"
|
||||||
zxcvbn4j = "1.9.0"
|
zxcvbn4j = "1.9.0"
|
||||||
zxing = "3.5.3"
|
zxing = "3.5.3"
|
||||||
|
@ -110,6 +111,7 @@ square-retrofit = { module = "com.squareup.retrofit2:retrofit" }
|
||||||
square-retrofit-bom = { module = "com.squareup.retrofit2:retrofit-bom", version.ref = "retrofitBom" }
|
square-retrofit-bom = { module = "com.squareup.retrofit2:retrofit-bom", version.ref = "retrofitBom" }
|
||||||
square-retrofit-kotlinx-serialization = { module = "com.squareup.retrofit2:converter-kotlinx-serialization" }
|
square-retrofit-kotlinx-serialization = { module = "com.squareup.retrofit2:converter-kotlinx-serialization" }
|
||||||
square-turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" }
|
square-turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" }
|
||||||
|
timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
|
||||||
zxing-zxing-core = { module = "com.google.zxing:core", version.ref = "zxing" }
|
zxing-zxing-core = { module = "com.google.zxing:core", version.ref = "zxing" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
|
|
Loading…
Reference in a new issue