| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /** |
| * @fileoverview 'settings-autofill-ai-section' contains configuration options |
| * for Autofill AI. |
| */ |
| |
| import 'chrome://resources/cr_elements/cr_icon/cr_icon.js'; |
| import 'chrome://resources/cr_elements/cr_icons.css.js'; |
| import 'chrome://resources/cr_elements/cr_shared_style.css.js'; |
| import '/shared/settings/prefs/prefs.js'; |
| import 'chrome://resources/cr_elements/icons.html.js'; |
| import '../controls/settings_toggle_button.js'; |
| import '../icons.html.js'; |
| import '../settings_columned_section.css.js'; |
| import '../settings_page/settings_subpage.js'; |
| import '../settings_shared.css.js'; |
| import './autofill_ai_entries_list.js'; |
| // <if expr="_google_chrome"> |
| import '../internal/icons.html.js'; |
| |
| // </if> |
| |
| import {PrefsMixin} from '/shared/settings/prefs/prefs_mixin.js'; |
| import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; |
| import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; |
| |
| import {AiEnterpriseFeaturePrefName, ModelExecutionEnterprisePolicyValue} from '../ai_page/constants.js'; |
| import type {SettingsToggleButtonElement} from '../controls/settings_toggle_button.js'; |
| import {loadTimeData} from '../i18n_setup.js'; |
| import {SettingsViewMixin} from '../settings_page/settings_view_mixin.js'; |
| |
| import {getTemplate} from './autofill_ai_section.html.js'; |
| import type {EntityDataManagerProxy} from './entity_data_manager_proxy.js'; |
| import {EntityDataManagerProxyImpl} from './entity_data_manager_proxy.js'; |
| |
| export interface SettingsAutofillAiSectionElement { |
| $: { |
| prefToggle: SettingsToggleButtonElement, |
| }; |
| } |
| |
| const SettingsAutofillAiSectionElementBase = |
| SettingsViewMixin(I18nMixin(PrefsMixin(PolymerElement))); |
| |
| export class SettingsAutofillAiSectionElement extends |
| SettingsAutofillAiSectionElementBase { |
| static get is() { |
| return 'settings-autofill-ai-section'; |
| } |
| |
| static get template() { |
| return getTemplate(); |
| } |
| |
| static get properties() { |
| return { |
| /** |
| If a user is not eligible for Autofill with Ai, but they have data |
| saved, the code allows them only to edit and delete their data. They |
| are not allowed to add new data, or to opt-in or opt-out of Autofill |
| with Ai using the toggle at the top of this page. |
| If a user is not eligible for Autofill with Ai and they also have no |
| data saved, then they cannot access this page at all. |
| */ |
| ineligibleUser: { |
| type: Boolean, |
| value() { |
| return !loadTimeData.getBoolean('userEligibleForAutofillAi'); |
| }, |
| }, |
| |
| /** |
| A "fake" preference object that reflects the state of the opt-in |
| toggle and the presence/absence of an enterprise policy. |
| This allows leveraging the settings-toggle-button component |
| to reflect enterprise enabled/disabled states. |
| */ |
| optedIn_: { |
| type: Object, |
| value: () => ({ |
| // Does not correspond to an actual pref - this is faked to allow |
| // writing it into a GAIA-id keyed dictionary of opt-ins. |
| type: chrome.settingsPrivate.PrefType.BOOLEAN, |
| value: false, |
| }), |
| }, |
| |
| /** |
| If reflects whether Wallet server data is available for storage. |
| */ |
| isWalletServerStorageEnabled_: { |
| type: Boolean, |
| value() { |
| return loadTimeData.getBoolean('isWalletServerStorageEnabled'); |
| }, |
| }, |
| }; |
| } |
| |
| static get observers() { |
| return [ |
| `onAutofillAiPrefChanged_( |
| prefs.autofill.profile_enabled.value)`, |
| ]; |
| } |
| |
| declare ineligibleUser: boolean; |
| declare private optedIn_: chrome.settingsPrivate.PrefObject; |
| declare private isWalletServerStorageEnabled_: boolean; |
| |
| private entityDataManager_: EntityDataManagerProxy = |
| EntityDataManagerProxyImpl.getInstance(); |
| |
| override connectedCallback() { |
| super.connectedCallback(); |
| |
| this.entityDataManager_.getOptInStatus().then( |
| optedIn => this.set('optedIn_.value', !this.ineligibleUser && optedIn)); |
| const policyDisabled = |
| this.getPref(AiEnterpriseFeaturePrefName.AUTOFILL_AI).value === |
| ModelExecutionEnterprisePolicyValue.DISABLE; |
| if (policyDisabled) { |
| this.set( |
| 'optedIn_.enforcement', chrome.settingsPrivate.Enforcement.ENFORCED); |
| this.set( |
| 'optedIn_.controlledBy', |
| chrome.settingsPrivate.ControlledBy.USER_POLICY); |
| } |
| } |
| |
| override disconnectedCallback() { |
| super.disconnectedCallback(); |
| } |
| |
| private async onOptInToggleChange_() { |
| // `setOptInStatus` returns false when the user tries to toggle the opt-in |
| // status when they're ineligible. This shouldn't happen usually but in |
| // some cases it can happen (see crbug.com/408145195). |
| this.ineligibleUser = !(await this.entityDataManager_.setOptInStatus( |
| this.$.prefToggle.checked)); |
| if (this.ineligibleUser) { |
| this.set('optedIn_.value', false); |
| } |
| } |
| |
| /** |
| * Whether an info bullet regarding logging is shown. Autofill Ai only shows |
| * logging behaviour information for enterprise clients who have either the |
| * feature disabled or just logging disabled. |
| */ |
| private showLoggingInfoBullet_(pref: number) { |
| return pref !== ModelExecutionEnterprisePolicyValue.ALLOW; |
| } |
| |
| // Adjusts the opt-in state when address autofill status changes. |
| // |
| // This covers the case where a user disables address autofill and then checks |
| // the AutofillAI opt-in status. In this case, we do not remove the AutofillAI |
| // entry, but just set the opt-in to false. Note that other |
| // preconditions (e.g., sync) are not covered. |
| private async onAutofillAiPrefChanged_(prefValue: boolean) { |
| const optedIn = await this.entityDataManager_.getOptInStatus(); |
| this.set('optedIn_.value', !this.ineligibleUser && optedIn && prefValue); |
| } |
| |
| // SettingsViewMixin implementation. |
| override focusBackButton() { |
| this.shadowRoot!.querySelector('settings-subpage')!.focusBackButton(); |
| } |
| } |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| 'settings-autofill-ai-section': SettingsAutofillAiSectionElement; |
| } |
| } |
| |
| customElements.define( |
| SettingsAutofillAiSectionElement.is, SettingsAutofillAiSectionElement); |