Skip to content

[PM-37255] feat: Integrate fill-assist targeting rules into autofill parser - #7066

Merged
aj-rosado merged 37 commits into
mainfrom
PM-37256/apply-fill-assist-rules
Jul 17, 2026
Merged

[PM-37255] feat: Integrate fill-assist targeting rules into autofill parser#7066
aj-rosado merged 37 commits into
mainfrom
PM-37256/apply-fill-assist-rules

Conversation

@aj-rosado

Copy link
Copy Markdown
Contributor

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-37255

📔 Objective

Wires the fill-assist targeting-rules pipeline end-to-end into the Android autofill framework.

When the FillAssistTargetingRules feature flag is enabled and rules are available for the current host, the autofill parser replaces heuristic field detection with site-specific CSS-selector-based matching. Unmatched nodes are excluded entirely — there is no heuristic fallback when rules are active.

What's included:

  • Network layerFillAssistApi, FillAssistService, FillAssistManifestJson, FillAssistFormsJson: fetches a versioned manifest and forms JSON from the fill-assist CDN endpoint.
  • Data layerFillAssistManagerImpl, FillAssistDiskSource: parses CSS selectors into FillAssistRules (tag, id, name, type, role constraints per field), caches rules on disk, syncs on server-config change with a 6-hour re-fetch throttle.
  • CSS selector parser — handles >>> Shadow DOM notation, space-separated CSS descendant selectors (split on whitespace outside […] attribute brackets to preserve attribute values that contain spaces), #id shorthand, and [attr='value'] / [attr="value"] attribute selectors.
  • IntegrationAutofillParserImpl looks up host rules for the focused view's URI and calls AssistStructure.buildFillAssistViews to replace the heuristic view list when rules match.
  • View-node matchingFillAssistViewNodeExtensions.traverseForFillAssist traverses the AssistStructure tree; HtmlInfoExtensions.matchesSelectorClause does the per-node attribute comparison (kept in HtmlInfoExtensions alongside hints() since HtmlInfo.attributes uses android.util.Pair and is untestable in unit tests).
  • TestsFillAssistManagerTest, FillAssistServiceTest, FillAssistViewNodeExtensionsTest (all previously commented-out tests now passing via mockkStatic(HtmlInfo::matchesSelectorClause)), and AutofillParserTests updated for the new constructor parameters.

@aj-rosado aj-rosado added the ai-review-vnext Request a Claude code review using the vNext workflow label Jun 16, 2026
@github-actions github-actions Bot added the app:password-manager Bitwarden Password Manager app context label Jun 16, 2026
@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

Reviewed the net PR diff (11 files) wiring the fill-assist targeting-rules pipeline into the autofill parser. Focus was on the CSS selector parser in FillAssistManagerImpl.kt (new CLASS_QUALIFIER_REGEX / DESCENDANT_SEPARATOR_REGEX and the unsupported-attribute / class-qualifier rejection in parseSingleSelector), per-node matching in HtmlInfoExtensions.matchesSelectorClause, view-node classification in FillAssistViewNodeExtensions.traverseForFillAssist, and the partition gating in AutofillParserImpl.toEffectiveViews. I verified the latest commit's .class-qualifier fix rather than re-flagging the already-answered thread.

The CLASS_QUALIFIER_REGEX negative-lookahead heuristic correctly distinguishes a class qualifier (input.hidden) from a literal . inside an attribute value ([title='a.b']), and the noAttributeConstraints guard correctly rejects tag-only fallbacks while preserving clauses that retain a supported id/name/type/role constraint. The DESCENDANT_SEPARATOR_REGEX split correctly preserves attribute values containing spaces. The isUnconstrained guard in matchesSelectorClause prevents vacuous whole-tag matches. No new, unaddressed correctness or security issues found.

Code Review Details

No blocking findings.

Non-blocking observation (not posted inline): FillAssistManagerImpl.syncIfNecessary() is invoked from two scopes on a singleton — the serverConfigStateFlow collection (unconfined) and VaultSyncManagerImpl.syncInternal (io). The if (!syncJob.isCompleted) return / syncJob = launch{} check-then-act is not synchronized, so a near-simultaneous double-invocation after the 6-hour throttle could launch two concurrent syncs. Impact is limited to a duplicate, idempotent fetch/disk-write (same rules, same timestamp), so this is low priority and does not block.

@aj-rosado aj-rosado changed the title Add fill assist logic to Autofill [PM-37255] feat: Integrate fill-assist targeting rules into autofill parser Jun 17, 2026
@github-actions github-actions Bot added the t:feature Change Type - Feature Development label Jun 25, 2026
@aj-rosado
aj-rosado marked this pull request as ready for review June 30, 2026 10:04
val HtmlInfo?.isInputField: Boolean get() = this?.tag == "input"

/**
* Whether this [HtmlInfo] matches the given [SelectorClause].

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.

The link here is broken, can we make it [FillAssistRules.SelectorClause]

Comment thread app/src/main/kotlin/com/x8bit/bitwarden/data/autofill/util/HtmlInfoExtensions.kt Outdated
clause.type == null &&
clause.role == null
fun hasAttr(key: String, value: String) = attrs.any { it.first == key && it.second == value }
return listOf(

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.

This can be mapOf

val data = toAutofillViewData(autofillId = id, website = website)
matchingEntries.firstNotNullOfOrNull { (key, _) ->
key.toAutofillViewForFieldKey(
data,

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.

This should either have a name or be 1 line.

    key.toAutofillViewForFieldKey(data)

OR

    key.toAutofillViewForFieldKey(
        data = data,
    )

"cardholderName" -> AutofillView.Card.CardholderName(data = data)
"cardExpirationDate" -> AutofillView.Card.ExpirationDate(data = data)
"cardExpirationMonth" -> AutofillView.Card.ExpirationMonth(data = data, monthValue = null)
"cardExpirationYear" -> AutofillView.Card.ExpirationYear(data = data, yearValue = null)

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.

Can we make some consts for these magic strings?

clause.id to "id",
clause.name to "name",
clause.type to "type",
clause.role to "role",

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.

Can we make these consts?

Comment thread app/src/main/kotlin/com/x8bit/bitwarden/data/autofill/util/HtmlInfoExtensions.kt Outdated
@aj-rosado
aj-rosado requested a review from david-livefront July 7, 2026 15:15
# Conflicts:
#	app/src/test/kotlin/com/x8bit/bitwarden/data/autofill/parser/AutofillParserTests.kt
assertEquals(expected, actual)
}

@Suppress("MaxLineLength")

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 suppression actually needed?

assertEquals(expected, actual)
}

@Suppress("MaxLineLength")

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.

This suppression is not needed

@aj-rosado
aj-rosado added this pull request to the merge queue Jul 17, 2026
@aj-rosado

Copy link
Copy Markdown
Contributor Author

Thanks @david-livefront

Merged via the queue into main with commit 109470e Jul 17, 2026
47 checks passed
@aj-rosado
aj-rosado deleted the PM-37256/apply-fill-assist-rules branch July 17, 2026 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review-vnext Request a Claude code review using the vNext workflow app:password-manager Bitwarden Password Manager app context t:feature Change Type - Feature Development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants