Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,45 +59,10 @@ class FilledDataBuilderImpl(
}
?.also { inlineSuggestionsAdded += 1 }

val filledPartitions = when (autofillRequest.partition) {
is AutofillPartition.Card -> {
autofillCipherProvider
.getCardAutofillCiphers()
.map { autofillCipher ->
fillCardPartition(
autofillCipher = autofillCipher,
autofillViews = autofillRequest.partition.views,
inlinePresentationSpec = getCipherInlinePresentationOrNull(),
)
}
}

is AutofillPartition.Login -> {
autofillRequest
.uri
?.let { nonNullUri ->
autofillCipherProvider
.getLoginAutofillCiphers(
uri = nonNullUri,
)
.map { autofillCipher ->
fillLoginPartition(
autofillCipher = autofillCipher,
autofillViews = autofillRequest.partition.views,
inlinePresentationSpec = getCipherInlinePresentationOrNull(),
packageName = autofillRequest.packageName,
)
}
}
.orEmpty()
}

is AutofillPartition.Identity -> {
// Filling an identity partition is wired up in a later phase; this is a no-op
// today since an identity partition is never constructed yet.
emptyList()
}
}
val filledPartitions = buildFilledPartitions(
autofillRequest = autofillRequest,
getCipherInlinePresentationOrNull = ::getCipherInlinePresentationOrNull,
)

// Use getOrLastOrNull so if the list has run dry take the last spec.
val vaultItemInlinePresentationSpec = autofillRequest
Expand All @@ -116,6 +81,59 @@ class FilledDataBuilderImpl(
)
}

/**
* Build the [FilledPartition]s for the [autofillRequest]'s partition by fetching the matching
* ciphers and fulfilling the partition's views with each cipher's data.
*/
private suspend fun buildFilledPartitions(
autofillRequest: AutofillRequest.Fillable,
getCipherInlinePresentationOrNull: () -> InlinePresentationSpec?,
): List<FilledPartition> = when (autofillRequest.partition) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ‘

is AutofillPartition.Card -> {
autofillCipherProvider
.getCardAutofillCiphers()
.map { autofillCipher ->
fillCardPartition(
autofillCipher = autofillCipher,
autofillViews = autofillRequest.partition.views,
inlinePresentationSpec = getCipherInlinePresentationOrNull(),
)
}
}

is AutofillPartition.Login -> {
autofillRequest
.uri
?.let { nonNullUri ->
autofillCipherProvider
.getLoginAutofillCiphers(
uri = nonNullUri,
)
.map { autofillCipher ->
fillLoginPartition(
autofillCipher = autofillCipher,
autofillViews = autofillRequest.partition.views,
inlinePresentationSpec = getCipherInlinePresentationOrNull(),
packageName = autofillRequest.packageName,
)
}
}
.orEmpty()
}

is AutofillPartition.Identity -> {
autofillCipherProvider
.getIdentityAutofillCiphers()
.map { autofillCipher ->
fillIdentityPartition(
autofillCipher = autofillCipher,
autofillViews = autofillRequest.partition.views,
inlinePresentationSpec = getCipherInlinePresentationOrNull(),
)
}
}
}

/**
* Construct a [FilledPartition] by fulfilling the card [autofillViews] with data from the
* card [autofillCipher].
Expand Down Expand Up @@ -181,6 +199,33 @@ class FilledDataBuilderImpl(
inlinePresentationSpec = inlinePresentationSpec,
)
}

/**
* Construct a [FilledPartition] by fulfilling the identity [autofillViews] with data from the
* identity [autofillCipher].
*/
private fun fillIdentityPartition(
autofillCipher: AutofillCipher.Identity,
autofillViews: List<AutofillView.Identity>,
inlinePresentationSpec: InlinePresentationSpec?,
): FilledPartition {
val filledItems = autofillViews
.mapNotNull { autofillView ->
autofillCipher
.getAutofillValueOrNull(autofillView)
?.let { value ->
autofillView.buildFilledItemOrNull(
value = value,
)
}
}

return FilledPartition(
autofillCipher = autofillCipher,
filledItems = filledItems,
inlinePresentationSpec = inlinePresentationSpec,
)
}
}

/**
Expand Down Expand Up @@ -225,6 +270,34 @@ private fun AutofillCipher.Card.getAutofillValueOrNull(autofillView: AutofillVie
}
}

/**
* Get the autofill value for the given [autofillView], or null if no value is available.
*/
@Suppress("CyclomaticComplexMethod")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed?

private fun AutofillCipher.Identity.getAutofillValueOrNull(
autofillView: AutofillView.Identity,
): String? =
when (autofillView) {
is AutofillView.Identity.PersonNameFull -> fullName
is AutofillView.Identity.PersonNamePrefix -> title
is AutofillView.Identity.PersonNameGiven -> firstName
is AutofillView.Identity.PersonNameMiddle -> middleName
is AutofillView.Identity.PersonNameFamily -> lastName
is AutofillView.Identity.PostalAddressFull -> fullAddress
is AutofillView.Identity.AddressStreet -> address1
is AutofillView.Identity.AddressLocality -> city
is AutofillView.Identity.AddressRegion -> state
is AutofillView.Identity.AddressCountry -> country
is AutofillView.Identity.PostalCode -> postalCode
is AutofillView.Identity.PhoneFull -> phone
is AutofillView.Identity.Company -> company
is AutofillView.Identity.Email -> email
is AutofillView.Identity.Ssn -> ssn
is AutofillView.Identity.PassportNumber -> passportNumber
is AutofillView.Identity.LicenseNumber -> licenseNumber
}
?.takeIf { it.isNotEmpty() }

/**
* Get the item at the [index]. If that fails, return the last item in the list. If that also fails,
* return null.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ private val URL_BARS: Map<String, String> = mapOf(
*/
private val LOGIN_FILL_ASSIST_CATEGORIES: List<String> = listOf(
"account-login",
"account-creation",
"account-update",
)

/**
Expand All @@ -73,6 +71,17 @@ private val CARD_FILL_ASSIST_CATEGORIES: List<String> = listOf(
"payment-card",
)

/**
* A list of categories from Fill Assist that are used for [AutofillView.Identity].
*
* Account creation and account update flows are where identity fields (name, address, phone,
* etc.) are curated alongside credential fields.
*/
private val IDENTITY_FILL_ASSIST_CATEGORIES: List<String> = listOf(
"account-creation",
"account-update",
)

/**
* The default [AutofillParser] implementation for the app. This is a tool for parsing autofill data
* from the OS into domain models.
Expand Down Expand Up @@ -132,15 +141,10 @@ class AutofillParserImpl(
.flatMap { it.urlBarWebsites }
.firstOrNull()
// Heuristic views: the focused node's candidates with unfillable (Unused) fields removed,
// falling back to all fillable views when nothing has focus. Identity is also excluded
// here for now -- Identity partition construction lands in Phase D, so until then a field
// classified as Identity must keep falling through exactly as it would have as Unused
// (e.g. resolving to a sibling Login/Card field on the same form, or its Unused-only
// promotion in updateForMissingUsernameFields), not become the focused view and force this
// request to Unfillable.
// falling back to all fillable views when nothing has focus.
val autofillViews = traversalDataList
.selectCandidateAutofillViews(urlBarWebsite = urlBarWebsite) {
it !is AutofillView.Unused && it !is AutofillView.Identity
it !is AutofillView.Unused

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ‘

}

val isFillAssistEnabled = featureFlagManager
Expand Down Expand Up @@ -183,9 +187,7 @@ class AutofillParserImpl(
autofillViews
}

val effectiveFocusedView = effectiveViews
.filterNot { it is AutofillView.Identity }
.firstFocusedOrNull()
val effectiveFocusedView = effectiveViews.effectiveFocusedViewOrNull()
?: return AutofillRequest.Unfillable

// Choose the first focused partition of data for fulfillment.
Expand All @@ -203,8 +205,12 @@ class AutofillParserImpl(
}

is AutofillView.Identity -> {
// Identity partition construction lands in Phase D. Unfillable until then.
return AutofillRequest.Unfillable
// Gated behind FlagKey.IdentityAutofill until the feature is ready for
// production; disabled matches this partition's pre-feature behavior.
if (!isIdentityAutofillEnabled) return AutofillRequest.Unfillable
AutofillPartition.Identity(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ IMPORTANT: Identity partitions become constructible here, but the vault-item dataset still maps them to Type.LOGIN.

Details and fix

FilledDataExtensions.kt:37-43 maps AutofillPartition.Identity to AutofillSelectionData.Type.LOGIN, justified by the comment "no-op placeholder today since nothing yet produces an Identity-only partition". This PR invalidates that premise, and nothing in the diff updates it.

Execution path once the flag is on and an Identity partition is built:

  1. FillResponseBuilderImpl.build unconditionally adds filledData.buildVaultItemDataset(...).
  2. That intent carries Type.LOGIN, which AutofillSelectionDataExtensions maps to VaultItemListingType.Login, so the "My vault" entry opens a Login-only item list on an identity form.
  3. Selecting a login there runs AutofillCompletionManagerImpl, which reparses the structure (still an Identity partition) and builds against cipherView.toAutofillCipherProvider(). getIdentityAutofillCiphers() returns emptyList() for a login cipher, so filledPartitions.firstOrNull() is null and the activity cancels with "Dataset not found" β€” nothing is filled.

When the vault is locked, getIdentityAutofillCiphers() returns empty, so the vault-item dataset is the only entry offered, and this is the whole identity-autofill experience for a locked vault.

Suggested fix: add an IDENTITY selection type (or omit the vault-item dataset for AutofillPartition.Identity while that type does not exist) so the fallback entry cannot route the user to a list that can never fulfil the request.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@claude this will be addressed in a future branch. Until the feature is fully ready feature flag won't be active

@claude claude Bot Sep 9, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude finished @aj-rosado's task in 1m 4s β€”β€” View job


Response

Understood β€” thanks for the context. Deferring the two flag-on findings to a follow-up branch makes sense given FlagKey.IdentityAutofill stays off through this rollout:

  • AutofillParserImpl.kt:211 β€” vault-item dataset mapping Identity β†’ Type.LOGIN (flag-gated, deferred)
  • AutofillParserImpl.kt:277 β€” Login fill-assist coverage on account-creation/account-update hosts (flag-gated, deferred)
  • HtmlInfoExtensions.kt:272 β€” not flag-gated

One item the flag doesn't cover

The "autocomplete" removal from SUPPORTED_HTML_ATTRIBUTE_HINTS ships to production with the flag off:

private val SUPPORTED_HTML_ATTRIBUTE_HINTS: List<String> = listOf(
    "name",
    "label",
    "type",
    "hint",
    "autofill",
)

hints() is called unconditionally from the HtmlInfo heuristics β€” isUsernameField(), isPasswordField(), and the card patterns all read the same values, and none of those paths check FlagKey.IdentityAutofill. containsAnyTerms matches on the attribute name, and "autocomplete" doesn't contain "autofill", so autocomplete="email" / "cc-number" / "new-password" on a web form now contributes no hint at all. That's a behavior change to Login and Card detection today, regardless of the flag.

It may still be the right call β€” if some autocomplete values were misclassifying identity fields, dropping the attribute is one way to fix it. Two things would help:

  1. A line in the PR description saying it's a deliberate revert of the autocomplete term added in d23d1d17, and why.
  2. Consider IGNORED_RAW_HINTS for the specific offending values instead, so the standard web attribute keeps contributing where it's correct. This file has no unit coverage, so a regression here wouldn't be caught by CI.

If it is intentional and scoped as-is, feel free to resolve β€” just wanted to make sure it wasn't swept in under the flag-off assumption alongside the other two.

Fix this β†’


β€’ PM-41294/identity-autofill-multi-partition-pipeline

views = effectiveViews.filterIsInstance<AutofillView.Identity>(),
)
}

is AutofillView.Unused -> {
Expand Down Expand Up @@ -262,16 +268,26 @@ class AutofillParserImpl(
}
?: return this

// Identity categories were Login categories before identity autofill, so with the flag
// off they must stay Login's to keep fill-assist coverage unchanged on those hosts.
val loginCategories = if (isIdentityAutofillEnabled) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename this to fillAssistCategories since it can now contain identity categories too

LOGIN_FILL_ASSIST_CATEGORIES
} else {
LOGIN_FILL_ASSIST_CATEGORIES + IDENTITY_FILL_ASSIST_CATEGORIES
}
Comment on lines +273 to +277

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ IMPORTANT: Turning the flag on removes fill-assist coverage for Login fields on account-creation/account-update hosts.

Details and fix

With isIdentityAutofillEnabled == true, loginCategories is just account-login. So when focusedView is an AutofillView.Login on a host whose rules are categorized only account-creation or account-update, coversCurrentPartition is false and the curated selectors are discarded in favour of heuristics β€” a regression against today's behavior, where both categories are Login categories.

Those categories carry Login field keys: FIELD_KEY_NEW_PASSWORD ("newPassword") only makes sense on a signup or change-password flow. So on a registration or account-settings host, focusing the password or username field is exactly where the authored rules were meant to apply, and is exactly where they now stop applying. The category describes the page flow, not the field type.

Suggested fix: keep the identity categories additive for the Login branch in both flag states (LOGIN_FILL_ASSIST_CATEGORIES + IDENTITY_FILL_ASSIST_CATEGORIES); the new is AutofillView.Identity branch already claims these categories when an identity field is what has focus, and effectiveFocusedViewOrNull keeps Login authoritative afterwards.

Note the new tests cover the flag-off case for this shape (...account-creation and a login view is focused with IdentityAutofill disabled) but not the flag-on case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@claude this will be addressed in a future branch. Until the feature is fully ready feature flag won't be active

@claude claude Bot Sep 9, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude finished @aj-rosado's task in 1m 19s β€”β€” View job


Understood β€” deferring the vault-item dataset routing

Thanks @aj-rosado, that disposition makes sense for that finding. AutofillPartition.Identity is only reachable when FlagKey.IdentityAutofill is on (AutofillParserImpl.kt:210 returns Unfillable otherwise), so with the flag inactive the Type.LOGIN mapping in FilledDataExtensions.kt:37-43 stays the no-op its comment describes. Nothing to change in this PR β€” worth carrying into the follow-up ticket so the placeholder comment gets retired alongside the new selection type.

The same reasoning covers my second comment (fill-assist categories on account-creation/account-update): the narrowing only takes effect with the flag on, so it can ride the same follow-up. One thing to note for when the flag flips β€” that one is a regression against today's shipped behavior rather than an incomplete new path, so it's easy to lose track of. If you'd rather not carry it, keeping the categories additive in both branches is a two-line change and the new is AutofillView.Identity branch already handles identity-focused fields.

Still open: the autocomplete removal is not flag-gated

This one isn't covered by the flag argument, so it's worth a decision before merge.

SUPPORTED_HTML_ATTRIBUTE_HINTS at HtmlInfoExtensions.kt:267-273 contains "autocomplete" on main (present at b1d6d6b); the first commit on this branch (f926f4c) drops it, and it's still absent at HEAD. hints() feeds every HtmlInfo heuristic β€” isPasswordField(), isUsernameField(), all seven card predicates β€” none of which consult the flag. So on web forms, autocomplete="new-password", "username", "cc-number" etc. stop contributing a hint today, flag off included.

If that was deliberate (some autocomplete values misclassifying identity fields), a one-line note here is enough and I'll drop it β€” though IGNORED_RAW_HINTS would scope the fix to the offending values rather than the whole attribute. If it was incidental to the heuristics work, restoring the entry is the safer call; there's no unit coverage on this file to catch the difference.

Restore the entry β†’

No code changes made β€” say the word if you'd like me to push either fix.
Β· branch PM-41294/identity-autofill-multi-partition-pipeline


val coversCurrentPartition = hostRules.any { rule ->
when (focusedView) {
is AutofillView.Card -> rule.category in CARD_FILL_ASSIST_CATEGORIES
is AutofillView.Login -> rule.category in LOGIN_FILL_ASSIST_CATEGORIES
is AutofillView.Login -> rule.category in loginCategories
is AutofillView.Identity -> rule.category in IDENTITY_FILL_ASSIST_CATEGORIES
is AutofillView.Unused -> {
rule.category in LOGIN_FILL_ASSIST_CATEGORIES ||
rule.category in CARD_FILL_ASSIST_CATEGORIES
val identityCoversRule = isIdentityAutofillEnabled &&
rule.category in IDENTITY_FILL_ASSIST_CATEGORIES
rule.category in loginCategories ||
rule.category in CARD_FILL_ASSIST_CATEGORIES ||
identityCoversRule
}
// Identity fill-assist categories land in a later phase.
is AutofillView.Identity -> false
}
}
if (!coversCurrentPartition) return this
Expand Down Expand Up @@ -337,6 +353,18 @@ private fun List<ViewNodeTraversalData>.selectCandidateAutofillViews(
private fun List<AutofillView>.firstFocusedOrNull(): AutofillView? =
firstOrNull { it.data.isFocused } ?: firstOrNull()

/**
* Returns the [AutofillView] that should win partition selection: a focused Login/Card view
* first, then any focused view (so a real Identity partition can still be built when Identity is
* the only classification available), then any Login/Card view, then any view at all.
*/
private fun List<AutofillView>.effectiveFocusedViewOrNull(): AutofillView? {
val focusedNonIdentity = firstOrNull { it.data.isFocused && it !is AutofillView.Identity }
val focusedAny = firstOrNull { it.data.isFocused }
val nonIdentity = firstOrNull { it !is AutofillView.Identity }
return focusedNonIdentity ?: focusedAny ?: nonIdentity ?: firstOrNull()
}

/**
* This helper function updates the [ViewNodeTraversalData] if necessary for missing password
* fields that were marked invalid because they contained a specific `hint` or `idEntry`. If the
Expand Down Expand Up @@ -452,9 +480,8 @@ private fun AssistStructure.ViewNode.traverse(
mutableAutofillViewList.add(AutofillView.Identity.Email(data = view.data))
}

// Some phone hints (e.g. "mobilephone") also match the username heuristic's
// "phone" term and resolve to Login.Username above, so they need the same
// dual-classification as email.
// A phone-hinted or phone-heuristic field resolves to Login.Username above (see
// supportedAutofillHint), so it needs the same dual-classification as email.
if (view is AutofillView.Login.Username && this.isPhoneField) {
mutableAutofillViewList.add(AutofillView.Identity.PhoneFull(data = view.data))
}
Expand All @@ -471,17 +498,29 @@ private fun AssistStructure.ViewNode.traverse(
isIdentityAutofillEnabled = isIdentityAutofillEnabled,
)
.let { viewNodeTraversalData ->
// Ids already claimed by an ancestor's own view (e.g. a container-redirect
// target) before this child's results are considered. A primary always precedes
// its Identity dual-classification sibling in this same child's results, so the
// sibling's id is still fresh here and passes the check below.
val idsClaimedByAncestor = claimedAutofillIds.toSet()
// Flatten child views into this node, keeping the first view seen for each autofill
// id and dropping later duplicates (e.g. a container-redirect leftover).
viewNodeTraversalData.autofillViews
// filter out existing AutofillIds to avoid duplicates
.filter { view ->
val id = view.data.autofillId
if (id in claimedAutofillIds) {
false
} else if (view !is AutofillView.Unused) {
claimedAutofillIds.add(id)
true
} else {
true
when (view) {
// Never claims an id, so a real view for that id can still be kept.
is AutofillView.Unused -> id !in claimedAutofillIds
// Kept if the id is fresh, i.e. it's a dual-classification sibling of
// a primary view from this same child. Dropped if the id was already
// claimed by an ancestor's own view -- that means this is a stale
// container-redirect leftover, not an intentional sibling.
is AutofillView.Identity -> {
(id !in idsClaimedByAncestor)
.also { keep -> if (keep) claimedAutofillIds.add(id) }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we just do this:

if (id !in idsClaimedByAncestor) {
    claimedAutofillIds.add(id)
}

That may be more straight forward to read.

}
// Kept only the first time its id is seen (add returns false if known).
else -> claimedAutofillIds.add(id)
}
}
.forEach(mutableAutofillViewList::add)
Expand Down Expand Up @@ -554,7 +593,6 @@ private fun AutofillView.updateWebsiteIfNecessary(website: String?): AutofillVie
is AutofillView.Identity.PostalAddressFull -> {
this.copy(data = this.data.copy(website = site))
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is supposed to be here, right?

is AutofillView.Identity.PostalCode -> this.copy(data = this.data.copy(website = site))
is AutofillView.Identity.Ssn -> this.copy(data = this.data.copy(website = site))
is AutofillView.Unused -> this.copy(data = this.data.copy(website = site))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ private fun AssistStructure.ViewNode.supportedAutofillHint(
this.isAddressRegionField -> AutofillHint.Identity.ADDRESS_REGION
this.isAddressCountryField -> AutofillHint.Identity.ADDRESS_COUNTRY
this.isPostalCodeField -> AutofillHint.Identity.POSTAL_CODE
this.isPhoneField -> AutofillHint.Identity.PHONE_FULL
this.isPhoneField -> AutofillHint.Login.USERNAME

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean that AutofillHint.Identity.PHONE_FULL is never used?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will autofill phone numbers, just not display the identity when pressing on a phone number

this.isCompanyField -> AutofillHint.Identity.COMPANY
this.isSsnField -> AutofillHint.Identity.SSN
this.isPassportNumberField -> AutofillHint.Identity.PASSPORT_NUMBER
Expand Down Expand Up @@ -239,7 +239,7 @@ private fun String.toBitwardenAutofillHintOrNull(): AutofillHint? =
}

View.AUTOFILL_HINT_POSTAL_CODE -> AutofillHint.Identity.POSTAL_CODE
View.AUTOFILL_HINT_PHONE -> AutofillHint.Identity.PHONE_FULL
View.AUTOFILL_HINT_PHONE -> AutofillHint.Login.USERNAME

else -> null
}
Expand Down Expand Up @@ -551,9 +551,10 @@ internal val AssistStructure.ViewNode.isPostalCodeField: Boolean
*/
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
internal val AssistStructure.ViewNode.isPhoneField: Boolean
get() = idEntry
?.toLowerCaseAndStripNonAlpha()
?.containsAnyTerms(SUPPORTED_RAW_PHONE_HINTS) == true ||
get() = autofillHints?.contains(View.AUTOFILL_HINT_PHONE) == true ||
idEntry
?.toLowerCaseAndStripNonAlpha()
?.containsAnyTerms(SUPPORTED_RAW_PHONE_HINTS) == true ||
hint
?.toLowerCaseAndStripNonAlpha()
?.containsAnyTerms(SUPPORTED_RAW_PHONE_HINTS) == true ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ val SUPPORTED_RAW_POSTAL_CODE_HINTS: List<String> = listOf(
* The supported phone number autofill hints.
*/
val SUPPORTED_RAW_PHONE_HINTS: List<String> = listOf(
"phone",
"phonenumber",
"telephone",
"mobilephone",
Expand Down
Loading
Loading