Skip to content

[PM-38966] feat: Add fill assist opt-in setting and privacy gate - #7075

Merged
aj-rosado merged 47 commits into
mainfrom
PM-38966/add-fill-assist-option-settings
Jul 20, 2026
Merged

[PM-38966] feat: Add fill assist opt-in setting and privacy gate#7075
aj-rosado merged 47 commits into
mainfrom
PM-38966/add-fill-assist-option-settings

Conversation

@aj-rosado

Copy link
Copy Markdown
Contributor

🎟️ Tracking

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

📔 Objective

Settings UI

  • Adds a "Turn on fill assist" toggle to Settings → Autofill → Additional options, visible only when the FillAssistTargetingRules feature flag is enabled
  • Toggle is off by default (explicit opt-in)
  • Includes an info icon linking to https://bitwarden.com/help/fill-assist/

Privacy gate

  • FillAssistManagerImpl.syncIfNecessary() now exits early when the user has not opted in — no background CDN requests while the feature is disabled
  • Toggling the setting on triggers an immediate syncIfNecessary() call so rules are available without waiting for the next server-config emission

Autofill integration

  • AutofillParserImpl applies fill-assist rules only when both the feature flag and isFillAssistEnabled are true
  • When rules match the current host, site-specific field targeting replaces heuristics entirely; unmatched nodes are excluded (no heuristic fallback)

Data layer

  • New isFillAssistEnabled per-user preference in SettingsDiskSource / SettingsRepository (keyed with appendIdentifier(userId), stored unencrypted)
  • Full network stack: FillAssistService, manifest + forms JSON parsing, 6-hour re-fetch throttle with CID-based deduplication

CSS selector matching

  • Parses tag#id, [attr='value'], CSS descendant selectors, and Shadow DOM (>>>) notation
  • Descendant-selector splitting is bracket-aware so attribute values containing spaces (e.g. [placeholder='Email address']) are preserved
  • HtmlInfo.matchesSelectorClause() extracted to HtmlInfoExtensions following the existing android.util.Pair isolation pattern

Tests

  • FillAssistManagerTest: new case — sync does nothing when isFillAssistEnabled = false
  • AutoFillViewModelTest: toggle-on persists setting and calls syncIfNecessary(); toggle-off persists setting and skips sync; info-click emits NavigateToFillAssistHelp
  • AutoFillScreenTest: switch hidden when flag off, switch visible when flag on, toggle sends FillAssistToggleClick, NavigateToFillAssistHelp calls intentManager.launchUri
  • FillAssistViewNodeExtensionsTest: all previously commented-out tests now pass via mockkStatic(HtmlInfo::matchesSelectorClause)

📸 Screenshots

Autofill settings with fill assist option

aj-rosado added 21 commits May 29, 2026 12:03
…ow updates

Updating code to schema with required values
@github-actions github-actions Bot added app:password-manager Bitwarden Password Manager app context app:authenticator Bitwarden Authenticator app context t:feature Change Type - Feature Development labels Jun 18, 2026
aj-rosado added 2 commits July 7, 2026 15:44
…l-assist-option-settings

# Conflicts:
#	app/src/main/kotlin/com/x8bit/bitwarden/data/autofill/parser/AutofillParserImpl.kt
#	app/src/test/kotlin/com/x8bit/bitwarden/data/autofill/manager/FillAssistManagerTest.kt
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.70115% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.09%. Comparing base (109470e) to head (3002113).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...data/platform/repository/SettingsRepositoryImpl.kt 83.33% 0 Missing and 1 partial ⚠️
...ure/settings/autofill/handlers/AutoFillHandlers.kt 83.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7075      +/-   ##
==========================================
+ Coverage   86.02%   86.09%   +0.06%     
==========================================
  Files         927      885      -42     
  Lines       66227    64733    -1494     
  Branches     9670     9638      -32     
==========================================
- Hits        56974    55729    -1245     
+ Misses       5788     5547     -241     
+ Partials     3465     3457       -8     
Flag Coverage Δ
app-data 17.73% <24.41%> (+0.22%) ⬆️
app-ui-auth-tools 18.73% <0.00%> (-0.05%) ⬇️
app-ui-platform 16.58% <73.56%> (-0.44%) ⬇️
app-ui-vault 27.39% <0.00%> (-0.60%) ⬇️
authenticator 6.11% <0.00%> (-0.01%) ⬇️
lib-core-network-bridge 4.01% <0.00%> (-0.02%) ⬇️
lib-data-ui 1.13% <0.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

if (!syncJob.isCompleted) return
if (clock.millis() - lastFetch < UPDATE_INTERVAL_MS ||
!syncJob.isCompleted
) {

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 identical functionality?

Why change this?

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.

I guess this has changed since this PR was created. Will revert the change as it does not make sense anymore

?.takeUnless { it.startsWith("androidapp://") }
?.toUri()
?.host
?.takeIf { featureFlagManager.getFeatureFlag(FlagKey.FillAssistTargetingRules) }

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 firstTimeState = firstTimeActionManager.currentOrDefaultUserFirstTimeState
AutoFillState(
showFillAssistOption = featureFlagManager
.getFeatureFlag(FlagKey.FillAssistTargetingRules),

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 add logic to observe the feature flag state, so it can update in realtime.

Base automatically changed from PM-37256/apply-fill-assist-rules to main July 17, 2026 15:53

private fun handleFillAssistToggleClick(action: AutoFillAction.FillAssistToggleClick) {
settingsRepository.isFillAssistEnabled = action.isEnabled
mutableStateFlow.update { it.copy(isFillAssistEnabled = action.isEnabled) }

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 observe this state directly from the repo as well?


featureFlagManager
.getFeatureFlagFlow(FlagKey.FillAssistTargetingRules)
.map { AutoFillAction.Internal.FillAssistTargetingRulesFlagUpdateReceive(it) }

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.

👍

class AutoFillViewModel @Inject constructor(
authRepository: AuthRepository,
browserThirdPartyAutofillEnabledManager: BrowserThirdPartyAutofillEnabledManager,
private val featureFlagManager: FeatureFlagManager,

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 does not need to be a private val right?

@aj-rosado
aj-rosado marked this pull request as ready for review July 20, 2026 12:54
@aj-rosado
aj-rosado requested a review from a team as a code owner July 20, 2026 12:54
@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

Reviewed the fill-assist opt-in setting and privacy gate. Changes add a per-user isFillAssistEnabled preference through the disk source, repository, and a reactive flow, wire an opt-in toggle into the Autofill settings screen behind the FillAssistTargetingRules flag, and gate rule application in AutofillParserImpl on both the flag and the setting. The ViewModel observes both the flag and the setting via flows, and the toggle-on path triggers an immediate syncIfNecessary(). Test coverage is thorough across the disk source, repository, ViewModel, and screen.

Code Review Details

No blocking findings. The implementation follows established codebase conventions: the new isFillAssistEnabledFlow mirrors the existing per-user flow pattern (onSubscription replay, getOrPut mutable map), state updates flow through internal actions rather than direct mutation inside the toggle handler, and the parser gating is a clean refactor of the prior feature-flag check.

Prior reviewer feedback in the existing threads appears addressed: the FillAssistManagerImpl change was reverted, and the feature flag and setting are now observed reactively so the UI updates in realtime.

@aj-rosado
aj-rosado added this pull request to the merge queue Jul 20, 2026
Merged via the queue into main with commit bd9c761 Jul 20, 2026
26 checks passed
@aj-rosado
aj-rosado deleted the PM-38966/add-fill-assist-option-settings branch July 20, 2026 15:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app:authenticator Bitwarden Authenticator app context 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