PM-10855: Update the minimum SDK to API 29 (Android 10) (#3723)

This commit is contained in:
David Perez 2024-08-14 09:23:13 -05:00 committed by GitHub
parent 151b081161
commit 2bed4986a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 6 additions and 272 deletions

View file

@ -11,7 +11,7 @@
## Compatibility
- **Minimum SDK**: 28
- **Minimum SDK**: 29
- **Target SDK**: 34
- **Device Types Supported**: Phone and Tablet
- **Orientations Supported**: Portrait and Landscape

View file

@ -2,7 +2,6 @@ package com.x8bit.bitwarden.data.autofill.builder
import android.service.autofill.FillRequest
import android.service.autofill.SaveInfo
import com.x8bit.bitwarden.data.autofill.model.AutofillAppInfo
import com.x8bit.bitwarden.data.autofill.model.AutofillPartition
/**
@ -12,13 +11,11 @@ interface SaveInfoBuilder {
/**
* Build a save info out the provided data. If that isn't possible, return null.
*
* @param autofillAppInfo App data that is required for building the [SaveInfo].
* @param autofillPartition The portion of the processed [FillRequest] that will be filled.
* @param fillRequest The [FillRequest] that initiated the autofill flow.
* @param packageName The package name that was extracted from the [FillRequest].
*/
fun build(
autofillAppInfo: AutofillAppInfo,
autofillPartition: AutofillPartition,
fillRequest: FillRequest,
packageName: String?,

View file

@ -1,10 +1,7 @@
package com.x8bit.bitwarden.data.autofill.builder
import android.annotation.SuppressLint
import android.os.Build
import android.service.autofill.FillRequest
import android.service.autofill.SaveInfo
import com.x8bit.bitwarden.data.autofill.model.AutofillAppInfo
import com.x8bit.bitwarden.data.autofill.model.AutofillPartition
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
@ -16,9 +13,7 @@ class SaveInfoBuilderImpl(
val settingsRepository: SettingsRepository,
) : SaveInfoBuilder {
@SuppressLint("InlinedApi")
override fun build(
autofillAppInfo: AutofillAppInfo,
autofillPartition: AutofillPartition,
fillRequest: FillRequest,
packageName: String?,
@ -29,12 +24,8 @@ class SaveInfoBuilderImpl(
// Docs state that password fields cannot be reliably saved
// in Compat mode since they show as masked values.
val isInCompatMode = if (autofillAppInfo.sdkInt >= Build.VERSION_CODES.Q) {
// Attempt to automatically establish compat request mode on Android 10+
(fillRequest.flags or FillRequest.FLAG_COMPATIBILITY_MODE_REQUEST) == fillRequest.flags
} else {
COMPAT_BROWSERS.contains(packageName)
}
val isInCompatMode = (fillRequest.flags or
FillRequest.FLAG_COMPATIBILITY_MODE_REQUEST) == fillRequest.flags
// If login and compat mode, the password might be obfuscated,
// in which case we should skip the save request.
@ -58,103 +49,3 @@ class SaveInfoBuilderImpl(
}
}
}
/**
* These browsers function using the compatibility shim for the Autofill Framework.
*
* Ensure that these entries are sorted alphabetically and keep this list synchronized with the
* values in /xml/autofill_service_configuration.xml and
* /xml-v30/autofill_service_configuration.xml.
*/
private val COMPAT_BROWSERS: List<String> = listOf(
"alook.browser",
"alook.browser.google",
"app.vanadium.browser",
"com.amazon.cloud9",
"com.android.browser",
"com.android.chrome",
"com.android.htmlviewer",
"com.avast.android.secure.browser",
"com.avg.android.secure.browser",
"com.brave.browser",
"com.brave.browser_beta",
"com.brave.browser_default",
"com.brave.browser_dev",
"com.brave.browser_nightly",
"com.chrome.beta",
"com.chrome.canary",
"com.chrome.dev",
"com.cookiegames.smartcookie",
"com.cookiejarapps.android.smartcookieweb",
"com.ecosia.android",
"com.google.android.apps.chrome",
"com.google.android.apps.chrome_dev",
"com.google.android.captiveportallogin",
"com.iode.firefox",
"com.jamal2367.styx",
"com.kiwibrowser.browser",
"com.kiwibrowser.browser.dev",
"com.lemurbrowser.exts",
"com.microsoft.emmx",
"com.microsoft.emmx.beta",
"com.microsoft.emmx.canary",
"com.microsoft.emmx.dev",
"com.mmbox.browser",
"com.mmbox.xbrowser",
"com.mycompany.app.soulbrowser",
"com.naver.whale",
"com.neeva.app",
"com.opera.browser",
"com.opera.browser.beta",
"com.opera.gx",
"com.opera.mini.native",
"com.opera.mini.native.beta",
"com.opera.touch",
"com.qflair.browserq",
"com.qwant.liberty",
"com.rainsee.create",
"com.sec.android.app.sbrowser",
"com.sec.android.app.sbrowser.beta",
"com.stoutner.privacybrowser.free",
"com.stoutner.privacybrowser.standard",
"com.vivaldi.browser",
"com.vivaldi.browser.snapshot",
"com.vivaldi.browser.sopranos",
"com.yandex.browser",
"com.yjllq.internet",
"com.yjllq.kito",
"com.yujian.ResideMenuDemo",
"com.z28j.feel",
"idm.internet.download.manager",
"idm.internet.download.manager.adm.lite",
"idm.internet.download.manager.plus",
"io.github.forkmaintainers.iceraven",
"mark.via",
"mark.via.gp",
"net.dezor.browser",
"net.slions.fulguris.full.download",
"net.slions.fulguris.full.download.debug",
"net.slions.fulguris.full.playstore",
"net.slions.fulguris.full.playstore.debug",
"org.adblockplus.browser",
"org.adblockplus.browser.beta",
"org.bromite.bromite",
"org.bromite.chromium",
"org.chromium.chrome",
"org.codeaurora.swe.browser",
"org.cromite.cromite",
"org.gnu.icecat",
"org.mozilla.fenix",
"org.mozilla.fenix.nightly",
"org.mozilla.fennec_aurora",
"org.mozilla.fennec_fdroid",
"org.mozilla.firefox",
"org.mozilla.firefox_beta",
"org.mozilla.reference.browser",
"org.mozilla.rocket",
"org.torproject.torbrowser",
"org.torproject.torbrowser_alpha",
"org.ungoogled.chromium.extensions.stable",
"org.ungoogled.chromium.stable",
"us.spotco.fennec_dos",
)

View file

@ -128,7 +128,6 @@ class AutofillProcessorImpl(
autofillRequest = autofillRequest,
)
val saveInfo = saveInfoBuilder.build(
autofillAppInfo = autofillAppInfo,
autofillPartition = autofillRequest.partition,
fillRequest = fillRequest,
packageName = autofillRequest.packageName,

View file

@ -3,8 +3,7 @@
android:supportsInlineSuggestions="true">
<!--
"Maintain alphabetical order for these compatibility packages and ensure synchronization with
both /xml/autofill_service_configuration.xml and the COMPAT_BROWSERS list within
SaveInfoBuilderImpl.kt."
/xml/autofill_service_configuration.xml.
-->
<compatibility-package
android:name="alook.browser"

View file

@ -2,8 +2,7 @@
<autofill-service xmlns:android="http://schemas.android.com/apk/res/android">
<!--
"Maintain alphabetical order for these compatibility packages and ensure synchronization with
both /xml-v30/autofill_service_configuration.xml and the COMPAT_BROWSERS list within
SaveInfoBuilderImpl.kt."
/xml-v30/autofill_service_configuration.xml.
-->
<compatibility-package
android:name="alook.browser"

View file

@ -1,11 +1,9 @@
package com.x8bit.bitwarden.data.autofill.builder
import android.os.Build
import android.service.autofill.FillRequest
import android.service.autofill.SaveInfo
import android.view.View
import android.view.autofill.AutofillId
import com.x8bit.bitwarden.data.autofill.model.AutofillAppInfo
import com.x8bit.bitwarden.data.autofill.model.AutofillPartition
import com.x8bit.bitwarden.data.autofill.model.AutofillView
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
@ -26,7 +24,6 @@ class SaveInfoBuilderTest {
private val settingsRepository: SettingsRepository = mockk()
private val autofillAppInfo: AutofillAppInfo = mockk()
private val fillRequest: FillRequest = mockk()
private val autofillIdOptional: AutofillId = mockk()
private val autofillViewDataOptional = AutofillView.Data(
@ -89,7 +86,6 @@ class SaveInfoBuilderTest {
// Test
val actual = saveInfoBuilder.build(
autofillAppInfo = autofillAppInfo,
autofillPartition = autofillPartitionCard,
fillRequest = fillRequest,
packageName = PACKAGE_NAME,
@ -106,7 +102,6 @@ class SaveInfoBuilderTest {
// Test
val actual = saveInfoBuilder.build(
autofillAppInfo = autofillAppInfo,
autofillPartition = AUTOFILL_PARTITION_LOGIN_EMPTY,
fillRequest = fillRequest,
packageName = PACKAGE_NAME,
@ -122,11 +117,9 @@ class SaveInfoBuilderTest {
// Setup
every { settingsRepository.isAutofillSavePromptDisabled } returns false
every { fillRequest.flags } returns FillRequest.FLAG_COMPATIBILITY_MODE_REQUEST
every { autofillAppInfo.sdkInt } returns Build.VERSION_CODES.TIRAMISU
// Test
val actual = saveInfoBuilder.build(
autofillAppInfo = autofillAppInfo,
autofillPartition = autofillPartitionLogin,
fillRequest = fillRequest,
packageName = PACKAGE_NAME,
@ -136,35 +129,12 @@ class SaveInfoBuilderTest {
assertNull(actual)
}
@Suppress("MaxLineLength")
@Test
fun `build should return null if autofill possible but package name is in compat list and is login`() {
// Setup
every { settingsRepository.isAutofillSavePromptDisabled } returns false
every { autofillAppInfo.sdkInt } returns Build.VERSION_CODES.P
// Test
COMPAT_BROWSERS
.forEach { packageName ->
val actual = saveInfoBuilder.build(
autofillAppInfo = autofillAppInfo,
autofillPartition = autofillPartitionLogin,
fillRequest = fillRequest,
packageName = packageName,
)
// Verify
assertNull(actual)
}
}
@Suppress("MaxLineLength")
@Test
fun `build should return SaveInfo with flag set if autofill possible, flags indicate compat mode, and is card`() {
// Setup
every { settingsRepository.isAutofillSavePromptDisabled } returns false
every { fillRequest.flags } returns FillRequest.FLAG_COMPATIBILITY_MODE_REQUEST
every { autofillAppInfo.sdkInt } returns Build.VERSION_CODES.TIRAMISU
mockBuilder<SaveInfo.Builder> {
it.setOptionalIds(arrayOf(autofillIdOptional))
}
@ -174,7 +144,6 @@ class SaveInfoBuilderTest {
// Test
val actual = saveInfoBuilder.build(
autofillAppInfo = autofillAppInfo,
autofillPartition = autofillPartitionCard,
fillRequest = fillRequest,
packageName = PACKAGE_NAME,
@ -187,126 +156,9 @@ class SaveInfoBuilderTest {
anyConstructed<SaveInfo.Builder>().setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
}
}
@Suppress("MaxLineLength")
@Test
fun `build should return SaveInfo if autofill possible, packageName is not in compat list, and is login`() {
// Setup
every { settingsRepository.isAutofillSavePromptDisabled } returns false
every { autofillAppInfo.sdkInt } returns Build.VERSION_CODES.P
mockBuilder<SaveInfo.Builder> {
it.setOptionalIds(arrayOf(autofillIdOptional))
}
// Test
val actual = saveInfoBuilder.build(
autofillAppInfo = autofillAppInfo,
autofillPartition = autofillPartitionLogin,
fillRequest = fillRequest,
packageName = PACKAGE_NAME,
)
// Verify
assertEquals(saveInfo, actual)
verify(exactly = 1) {
anyConstructed<SaveInfo.Builder>().setOptionalIds(arrayOf(autofillIdOptional))
}
}
}
private const val PACKAGE_NAME: String = "com.google"
private val AUTOFILL_PARTITION_LOGIN_EMPTY: AutofillPartition.Login = AutofillPartition.Login(
views = listOf(),
)
private val COMPAT_BROWSERS: List<String> = listOf(
"alook.browser",
"alook.browser.google",
"app.vanadium.browser",
"com.amazon.cloud9",
"com.android.browser",
"com.android.chrome",
"com.android.htmlviewer",
"com.avast.android.secure.browser",
"com.avg.android.secure.browser",
"com.brave.browser",
"com.brave.browser_beta",
"com.brave.browser_default",
"com.brave.browser_dev",
"com.brave.browser_nightly",
"com.chrome.beta",
"com.chrome.canary",
"com.chrome.dev",
"com.cookiegames.smartcookie",
"com.cookiejarapps.android.smartcookieweb",
"com.ecosia.android",
"com.google.android.apps.chrome",
"com.google.android.apps.chrome_dev",
"com.google.android.captiveportallogin",
"com.iode.firefox",
"com.jamal2367.styx",
"com.kiwibrowser.browser",
"com.kiwibrowser.browser.dev",
"com.lemurbrowser.exts",
"com.microsoft.emmx",
"com.microsoft.emmx.beta",
"com.microsoft.emmx.canary",
"com.microsoft.emmx.dev",
"com.mmbox.browser",
"com.mmbox.xbrowser",
"com.mycompany.app.soulbrowser",
"com.naver.whale",
"com.neeva.app",
"com.opera.browser",
"com.opera.browser.beta",
"com.opera.gx",
"com.opera.mini.native",
"com.opera.mini.native.beta",
"com.opera.touch",
"com.qflair.browserq",
"com.qwant.liberty",
"com.rainsee.create",
"com.sec.android.app.sbrowser",
"com.sec.android.app.sbrowser.beta",
"com.stoutner.privacybrowser.free",
"com.stoutner.privacybrowser.standard",
"com.vivaldi.browser",
"com.vivaldi.browser.snapshot",
"com.vivaldi.browser.sopranos",
"com.yandex.browser",
"com.yjllq.internet",
"com.yjllq.kito",
"com.yujian.ResideMenuDemo",
"com.z28j.feel",
"idm.internet.download.manager",
"idm.internet.download.manager.adm.lite",
"idm.internet.download.manager.plus",
"io.github.forkmaintainers.iceraven",
"mark.via",
"mark.via.gp",
"net.dezor.browser",
"net.slions.fulguris.full.download",
"net.slions.fulguris.full.download.debug",
"net.slions.fulguris.full.playstore",
"net.slions.fulguris.full.playstore.debug",
"org.adblockplus.browser",
"org.adblockplus.browser.beta",
"org.bromite.bromite",
"org.bromite.chromium",
"org.chromium.chrome",
"org.codeaurora.swe.browser",
"org.cromite.cromite",
"org.gnu.icecat",
"org.mozilla.fenix",
"org.mozilla.fenix.nightly",
"org.mozilla.fennec_aurora",
"org.mozilla.fennec_fdroid",
"org.mozilla.firefox",
"org.mozilla.firefox_beta",
"org.mozilla.reference.browser",
"org.mozilla.rocket",
"org.torproject.torbrowser",
"org.torproject.torbrowser_alpha",
"org.ungoogled.chromium.extensions.stable",
"org.ungoogled.chromium.stable",
"us.spotco.fennec_dos",
)

View file

@ -157,7 +157,6 @@ class AutofillProcessorTest {
} returns autofillRequest
every {
saveInfoBuilder.build(
autofillAppInfo = appInfo,
autofillPartition = autofillPartition,
fillRequest = fillRequest,
packageName = PACKAGE_NAME,
@ -233,7 +232,6 @@ class AutofillProcessorTest {
} returns autofillRequest
every {
saveInfoBuilder.build(
autofillAppInfo = appInfo,
autofillPartition = autofillPartition,
fillRequest = fillRequest,
packageName = PACKAGE_NAME,
@ -494,7 +492,6 @@ class AutofillProcessorTest {
coEvery { filledDataBuilder.build(autofillRequest = autofillRequest) } returns filledData
every {
saveInfoBuilder.build(
autofillAppInfo = appInfo,
autofillPartition = autofillPartition,
fillRequest = fillRequest,
packageName = PACKAGE_NAME,

View file

@ -4,7 +4,7 @@
# SDK Versions
compileSdk = "34"
targetSdk = "34"
minSdk = "28"
minSdk = "29"
# Dependency Versions
androidGradlePlugin = "8.5.1"