Catch TransactionTooLargeExceptions in autofill (#3569)
Some checks failed
Crowdin Push / Crowdin Push (push) Waiting to run
Scan / Check PR run (push) Failing after 0s
Scan / SAST scan (push) Has been skipped
Scan / Quality scan (push) Has been skipped
Test / Check PR run (push) Failing after 0s
Test / Test (push) Has been skipped

This commit is contained in:
David Perez 2024-07-19 09:31:17 -05:00 committed by GitHub
parent 9ffc0360bd
commit 4abf907dc5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 90 additions and 1 deletions

View file

@ -19,6 +19,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.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
@ -101,6 +102,7 @@ object AutofillModule {
policyManager: PolicyManager, policyManager: PolicyManager,
saveInfoBuilder: SaveInfoBuilder, saveInfoBuilder: SaveInfoBuilder,
settingsRepository: SettingsRepository, settingsRepository: SettingsRepository,
crashLogsManager: CrashLogsManager,
): AutofillProcessor = ): AutofillProcessor =
AutofillProcessorImpl( AutofillProcessorImpl(
dispatcherManager = dispatcherManager, dispatcherManager = dispatcherManager,
@ -110,6 +112,7 @@ object AutofillModule {
policyManager = policyManager, policyManager = policyManager,
saveInfoBuilder = saveInfoBuilder, saveInfoBuilder = saveInfoBuilder,
settingsRepository = settingsRepository, settingsRepository = settingsRepository,
crashLogsManager = crashLogsManager,
) )
@Provides @Provides

View file

@ -13,6 +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.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
@ -34,6 +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,
) : AutofillProcessor { ) : AutofillProcessor {
/** /**
@ -139,7 +141,14 @@ class AutofillProcessorImpl(
saveInfo = saveInfo, saveInfo = saveInfo,
) )
fillCallback.onSuccess(response) @Suppress("TooGenericExceptionCaught")
try {
fillCallback.onSuccess(response)
} catch (e: RuntimeException) {
// This is to catch any TransactionTooLargeExceptions that could occur here.
// These exceptions get wrapped as a RuntimeException.
crashLogsManager.trackNonFatalException(e)
}
} }
AutofillRequest.Unfillable -> { AutofillRequest.Unfillable -> {

View file

@ -22,6 +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.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
@ -56,6 +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 appInfo: AutofillAppInfo = AutofillAppInfo( private val appInfo: AutofillAppInfo = AutofillAppInfo(
context = mockk(), context = mockk(),
@ -77,6 +79,7 @@ class AutofillProcessorTest {
policyManager = policyManager, policyManager = policyManager,
saveInfoBuilder = saveInfoBuilder, saveInfoBuilder = saveInfoBuilder,
settingsRepository = settingsRepository, settingsRepository = settingsRepository,
crashLogsManager = crashLogsManager,
) )
} }
@ -200,6 +203,80 @@ class AutofillProcessorTest {
} }
} }
@Suppress("MaxLineLength")
@Test
fun `processFillRequest should invoke callback with filled response when has filledItems and track exceptions thrown by callback`() =
runTest {
// Setup
val fillRequest: FillRequest = mockk()
val filledData = FilledData(
filledPartitions = listOf(mockk()),
ignoreAutofillIds = emptyList(),
originalPartition = mockk(),
uri = null,
vaultItemInlinePresentationSpec = null,
isVaultLocked = false,
)
val fillResponse: FillResponse = mockk()
val autofillPartition: AutofillPartition = mockk()
val autofillRequest: AutofillRequest.Fillable = mockk {
every { packageName } returns PACKAGE_NAME
every { partition } returns autofillPartition
}
val saveInfo: SaveInfo = mockk()
coEvery {
filledDataBuilder.build(autofillRequest = autofillRequest)
} returns filledData
every { cancellationSignal.setOnCancelListener(any()) } just runs
every {
parser.parse(autofillAppInfo = appInfo, fillRequest = fillRequest)
} returns autofillRequest
every {
saveInfoBuilder.build(
autofillAppInfo = appInfo,
autofillPartition = autofillPartition,
fillRequest = fillRequest,
packageName = PACKAGE_NAME,
)
} returns saveInfo
every {
fillResponseBuilder.build(
autofillAppInfo = appInfo,
filledData = filledData,
saveInfo = saveInfo,
)
} returns fillResponse
val runtimeException = RuntimeException("TransactionToLarge")
every { fillCallback.onSuccess(fillResponse) } throws runtimeException
every { crashLogsManager.trackNonFatalException(runtimeException) } just runs
// Test
autofillProcessor.processFillRequest(
autofillAppInfo = appInfo,
cancellationSignal = cancellationSignal,
fillCallback = fillCallback,
request = fillRequest,
)
testDispatcher.scheduler.runCurrent()
// Verify
coVerify(exactly = 1) {
filledDataBuilder.build(autofillRequest = autofillRequest)
}
verify(exactly = 1) {
cancellationSignal.setOnCancelListener(any())
parser.parse(autofillAppInfo = appInfo, fillRequest = fillRequest)
fillResponseBuilder.build(
autofillAppInfo = appInfo,
filledData = filledData,
saveInfo = saveInfo,
)
fillCallback.onSuccess(fillResponse)
crashLogsManager.trackNonFatalException(runtimeException)
}
}
@Test @Test
fun `processSaveRequest should invoke empty callback when autofill prompt disabled`() { fun `processSaveRequest should invoke empty callback when autofill prompt disabled`() {
// Setup // Setup