// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/preferences/preferences.h"
#include <limits>
#include <memory>
#include <optional>
#include <vector>
#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/constants/ash_switches.h"
#include "ash/constants/geolocation_access_level.h"
#include "ash/public/ash_interfaces.h"
#include "ash/public/cpp/ash_prefs.h"
#include "ash/shell.h"
#include "ash/system/geolocation/geolocation_controller.h"
#include "ash/system/privacy_hub/privacy_hub_controller.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/i18n/time_formatting.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "base/time/time.h"
#include "base/types/cxx23_to_underlying.h"
#include "chrome/browser/ash/accessibility/magnification_manager.h"
#include "chrome/browser/ash/base/locale_util.h"
#include "chrome/browser/ash/child_accounts/parent_access_code/parent_access_service.h"
#include "chrome/browser/ash/crosapi/browser_util.h"
#include "chrome/browser/ash/drive/drive_integration_service.h"
#include "chrome/browser/ash/drive/file_system_util.h"
#include "chrome/browser/ash/input_method/editor_consent_enums.h"
#include "chrome/browser/ash/input_method/input_method_persistence.h"
#include "chrome/browser/ash/input_method/input_method_syncer.h"
#include "chrome/browser/ash/login/login_pref_names.h"
#include "chrome/browser/ash/login/session/user_session_manager.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/ash/system/input_device_settings.h"
#include "chrome/browser/ash/system/timezone_resolver_manager.h"
#include "chrome/browser/ash/system/timezone_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/prefs/pref_service_syncable_util.h"
#include "chrome/browser/ui/ash/system/system_tray_client_impl.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chromeos/ash/components/dbus/pciguard/pciguard_client.h"
#include "chromeos/ash/components/dbus/update_engine/update_engine.pb.h"
#include "chromeos/ash/components/dbus/update_engine/update_engine_client.h"
#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
#include "chromeos/ash/components/peripheral_notification/peripheral_notification_manager.h"
#include "chromeos/ash/components/settings/cros_settings.h"
#include "chromeos/ash/components/settings/cros_settings_names.h"
#include "chromeos/ash/components/standalone_browser/lacros_availability.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "chromeos/ash/components/system/statistics_provider.h"
#include "chromeos/ash/components/timezone/timezone_resolver.h"
#include "chromeos/components/disks/disks_prefs.h"
#include "chromeos/components/magic_boost/public/cpp/magic_boost_state.h"
#include "chromeos/constants/pref_names.h"
#include "components/feedback/content/content_tracing_manager.h"
#include "components/language/core/browser/pref_names.h"
#include "components/policy/proto/chrome_device_policy.pb.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_member.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "components/user_manager/known_user.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/blink/public/mojom/speech/speech_synthesis.mojom.h"
#include "third_party/cros_system_api/dbus/update_engine/dbus-constants.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
#include "ui/base/ime/ash/extension_ime_util.h"
#include "ui/base/ime/ash/ime_keyboard.h"
#include "ui/base/ime/ash/input_method_manager.h"
#include "ui/events/ash/mojom/extended_fkeys_modifier.mojom-shared.h"
#include "ui/events/ash/mojom/extended_fkeys_modifier.mojom.h"
#include "ui/events/ash/mojom/modifier_key.mojom.h"
#include "ui/events/ash/pref_names.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_utils.h"
#include "url/gurl.h"
namespace ash {
namespace {
// These preferences will be saved in global user preferences dictionary so that
// they can be used on the signin screen.
const char* const kCopyToKnownUserPrefs[] = {
// The keyboard preferences that determine how we remap modifier keys.
::prefs::kLanguageRemapSearchKeyTo,
::prefs::kLanguageRemapControlKeyTo,
::prefs::kLanguageRemapAltKeyTo,
::prefs::kLanguageRemapCapsLockKeyTo,
::prefs::kLanguageRemapEscapeKeyTo,
::prefs::kLanguageRemapBackspaceKeyTo,
::prefs::kLanguageRemapExternalCommandKeyTo,
::prefs::kLanguageRemapExternalMetaKeyTo,
prefs::kLoginDisplayPasswordButtonEnabled,
::prefs::kUse24HourClock,
prefs::kDarkModeEnabled};
bool AreScrollSettingsAllowed() {
return base::FeatureList::IsEnabled(features::kAllowScrollSettings);
}
} // namespace
Preferences::Preferences()
: Preferences(input_method::InputMethodManager::Get()) {}
Preferences::Preferences(input_method::InputMethodManager* input_method_manager)
: prefs_(nullptr),
input_method_manager_(input_method_manager),
user_(nullptr),
user_is_primary_(false) {
BindCrosDisplayConfigController(
cros_display_config_.BindNewPipeAndPassReceiver());
}
Preferences::~Preferences() {
prefs_->RemoveObserver(this);
user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
UpdateEngineClient::Get()->RemoveObserver(this);
}
// static
void Preferences::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(prefs::kOwnerPrimaryMouseButtonRight, false);
registry->RegisterBooleanPref(prefs::kOwnerPrimaryPointingStickButtonRight,
false);
registry->RegisterBooleanPref(prefs::kOwnerTapToClickEnabled, true);
// TODO(jamescook): Move ownership and registration into ash.
registry->RegisterStringPref(::prefs::kLogoutStartedLast, std::string());
registry->RegisterStringPref(::prefs::kSigninScreenTimezone, std::string());
registry->RegisterIntegerPref(
::prefs::kResolveDeviceTimezoneByGeolocationMethod,
static_cast<int>(
system::TimeZoneResolverManager::TimeZoneResolveMethod::IP_ONLY));
registry->RegisterIntegerPref(
::prefs::kSystemTimezoneAutomaticDetectionPolicy,
enterprise_management::SystemTimezoneProto::USERS_DECIDE);
registry->RegisterStringPref(::prefs::kMinimumAllowedChromeVersion, "");
registry->RegisterIntegerPref(
::prefs::kLacrosLaunchSwitch,
static_cast<int>(
ash::standalone_browser::LacrosAvailability::kUserChoice));
registry->RegisterIntegerPref(
::prefs::kLacrosSelection,
static_cast<int>(
ash::standalone_browser::LacrosSelectionPolicy::kUserChoice));
registry->RegisterStringPref(::prefs::kLacrosDataBackwardMigrationMode, "");
registry->RegisterBooleanPref(prefs::kDeviceSystemWideTracingEnabled, true);
registry->RegisterBooleanPref(
prefs::kLocalStateDevicePeripheralDataAccessEnabled, false);
registry->RegisterBooleanPref(prefs::kDeviceI18nShortcutsEnabled, true);
registry->RegisterBooleanPref(prefs::kLoginScreenWebUILazyLoading, false);
registry->RegisterBooleanPref(::prefs::kConsumerAutoUpdateToggle, true);
registry->RegisterBooleanPref(prefs::kDeviceEphemeralNetworkPoliciesEnabled,
false);
registry->RegisterBooleanPref(prefs::kDeviceSwitchFunctionKeysBehaviorEnabled,
false);
registry->RegisterBooleanPref(::prefs::kLocalUserFilesAllowed, true);
registry->RegisterStringPref(::prefs::kLocalUserFilesMigrationDestination,
"read_only");
registry->RegisterListPref(prefs::kDnsOverHttpsExcludedDomains,
base::Value::List());
registry->RegisterListPref(prefs::kDnsOverHttpsIncludedDomains,
base::Value::List());
RegisterLocalStatePrefs(registry);
}
// static
void Preferences::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
// Some classes register their own prefs.
input_method::InputMethodSyncer::RegisterProfilePrefs(registry);
crosapi::browser_util::RegisterProfilePrefs(registry);
::drive::DriveIntegrationService::RegisterProfilePrefs(registry);
std::string hardware_keyboard_id;
// TODO(yusukes): Remove the runtime hack.
if (base::SysInfo::IsRunningOnChromeOS()) {
DCHECK(g_browser_process);
PrefService* local_state = g_browser_process->local_state();
DCHECK(local_state);
hardware_keyboard_id =
local_state->GetString(::prefs::kHardwareKeyboardLayout);
} else {
hardware_keyboard_id = "xkb:us::eng"; // only for testing.
}
registry->RegisterBooleanPref(::prefs::kPerformanceTracingEnabled, false);
registry->RegisterBooleanPref(
prefs::kTapToClickEnabled, true,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterBooleanPref(prefs::kEnableTouchpadThreeFingerClick, false);
// This preference can only be set to true by policy or command_line flag
// and it should not carry over to sessions were neither of these is set.
registry->RegisterBooleanPref(::prefs::kUnifiedDesktopEnabledByDefault, false,
PrefRegistry::NO_REGISTRATION_FLAGS);
// TODO(anasalazar): Finish moving this to ash.
registry->RegisterBooleanPref(
prefs::kNaturalScroll,
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kNaturalScrollDefault),
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterBooleanPref(
prefs::kMouseReverseScroll, false,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterBooleanPref(
prefs::kPrimaryMouseButtonRight, false,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterBooleanPref(
prefs::kPrimaryPointingStickButtonRight, false,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterBooleanPref(
prefs::kMouseAcceleration, true,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterBooleanPref(
prefs::kMouseScrollAcceleration, true,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterBooleanPref(
prefs::kPointingStickAcceleration, true,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterBooleanPref(
prefs::kTouchpadAcceleration, true,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterBooleanPref(
prefs::kTouchpadScrollAcceleration, true,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterBooleanPref(
prefs::kTouchpadHapticFeedback, true,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterBooleanPref(::prefs::kLabsMediaplayerEnabled, false);
registry->RegisterBooleanPref(::prefs::kLabsAdvancedFilesystemEnabled, false);
registry->RegisterBooleanPref(::prefs::kAppReinstallRecommendationEnabled,
false);
registry->RegisterIntegerPref(
prefs::kMouseSensitivity, 3,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterIntegerPref(
prefs::kMouseScrollSensitivity, 3,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterIntegerPref(
prefs::kPointingStickSensitivity, 3,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterIntegerPref(
prefs::kTouchpadSensitivity, 3,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterIntegerPref(
prefs::kTouchpadScrollSensitivity, 3,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterIntegerPref(
prefs::kTouchpadHapticClickSensitivity, 3,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterBooleanPref(
::prefs::kUse24HourClock, base::GetHourClockType() == base::k24HourClock,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
// We don't sync ::prefs::kLanguageCurrentInputMethod and PreviousInputMethod
// because they're just used to track the logout state of the device.
registry->RegisterStringPref(::prefs::kLanguageCurrentInputMethod, "");
registry->RegisterStringPref(::prefs::kLanguagePreviousInputMethod, "");
registry->RegisterListPref(::prefs::kLanguageAllowedInputMethods);
registry->RegisterListPref(::prefs::kAllowedLanguages);
registry->RegisterStringPref(::prefs::kLanguagePreloadEngines,
hardware_keyboard_id);
registry->RegisterStringPref(::prefs::kLanguageEnabledImes, "");
registry->RegisterDictionaryPref(prefs::kAssistiveInputFeatureSettings);
registry->RegisterBooleanPref(prefs::kAssistPersonalInfoEnabled, true);
registry->RegisterBooleanPref(prefs::kAssistPredictiveWritingEnabled, true);
registry->RegisterBooleanPref(prefs::kEmojiSuggestionEnabled, true);
registry->RegisterBooleanPref(prefs::kEmojiSuggestionEnterpriseAllowed, true);
registry->RegisterBooleanPref(prefs::kOrcaEnabled, true);
registry->RegisterBooleanPref(prefs::kOrcaFeedbackEnabled, true);
registry->RegisterBooleanPref(prefs::kManagedOrcaEnabled, true);
registry->RegisterBooleanPref(
prefs::kManagedPhysicalKeyboardAutocorrectAllowed, true);
registry->RegisterBooleanPref(
prefs::kManagedPhysicalKeyboardPredictiveWritingAllowed, true);
registry->RegisterIntegerPref(
prefs::kOrcaConsentStatus,
base::to_underlying(input_method::ConsentStatus::kUnset));
registry->RegisterIntegerPref(prefs::kOrcaConsentWindowDismissCount, 0);
registry->RegisterBooleanPref(prefs::kEmojiPickerGifSupportEnabled, true);
registry->RegisterDictionaryPref(prefs::kEmojiPickerHistory);
registry->RegisterDictionaryPref(prefs::kEmojiPickerPreferences);
registry->RegisterDictionaryPref(
::prefs::kLanguageInputMethodSpecificSettings);
registry->RegisterBooleanPref(prefs::kLastUsedImeShortcutReminderDismissed,
false);
registry->RegisterBooleanPref(prefs::kNextImeShortcutReminderDismissed,
false);
registry->RegisterIntegerPref(prefs::kGenAIWallpaperSettings, /*enabled=*/1);
registry->RegisterIntegerPref(prefs::kGenAIVcBackgroundSettings,
/*enabled=*/1);
registry->RegisterIntegerPref(
::prefs::kLanguageRemapSearchKeyTo,
static_cast<int>(ui::mojom::ModifierKey::kMeta),
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterIntegerPref(
::prefs::kLanguageRemapControlKeyTo,
static_cast<int>(ui::mojom::ModifierKey::kControl),
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterIntegerPref(
::prefs::kLanguageRemapAltKeyTo,
static_cast<int>(ui::mojom::ModifierKey::kAlt),
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterIntegerPref(
::prefs::kLanguageRemapAssistantKeyTo,
static_cast<int>(ui::mojom::ModifierKey::kAssistant),
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
// Even though most of the Chrome OS devices don't have the CapsLock key - the
// user always could plug in an external keyboard with the CapsLock. So we're
// syncing the pref to support this case.
registry->RegisterIntegerPref(
::prefs::kLanguageRemapCapsLockKeyTo,
static_cast<int>(ui::mojom::ModifierKey::kCapsLock),
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterIntegerPref(
::prefs::kLanguageRemapEscapeKeyTo,
static_cast<int>(ui::mojom::ModifierKey::kEscape),
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
registry->RegisterIntegerPref(
::prefs::kLanguageRemapBackspaceKeyTo,
static_cast<int>(ui::mojom::ModifierKey::kBackspace),
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
// The Command key on external Apple keyboards is remapped by default to Ctrl
// until the user changes it from the keyboard settings.
registry->RegisterIntegerPref(
::prefs::kLanguageRemapExternalCommandKeyTo,
static_cast<int>(ui::mojom::ModifierKey::kControl),
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
// The Meta key (Search or Windows keys) on external keyboards is remapped by
// default to Search until the user changes it from the keyboard settings.
registry->RegisterIntegerPref(
::prefs::kLanguageRemapExternalMetaKeyTo,
static_cast<int>(ui::mojom::ModifierKey::kMeta),
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
// The following pref isn't synced since the user may desire a different value
// depending on whether an external keyboard is attached to a particular
// device.
registry->RegisterBooleanPref(prefs::kSendFunctionKeys, false);
registry->RegisterIntegerPref(prefs::kAltEventRemappedToRightClick, 0);
registry->RegisterIntegerPref(prefs::kSearchEventRemappedToRightClick, 0);
registry->RegisterIntegerPref(prefs::kKeyEventRemappedToSixPackDelete, 0);
registry->RegisterIntegerPref(prefs::kKeyEventRemappedToSixPackEnd, 0);
registry->RegisterIntegerPref(prefs::kKeyEventRemappedToSixPackHome, 0);
registry->RegisterIntegerPref(prefs::kKeyEventRemappedToSixPackPageUp, 0);
registry->RegisterIntegerPref(prefs::kKeyEventRemappedToSixPackPageDown, 0);
// Don't sync the note-taking app; it may not be installed on other devices.
registry->RegisterStringPref(::prefs::kNoteTakingAppId, std::string());
registry->RegisterBooleanPref(::prefs::kRestoreLastLockScreenNote, true);
registry->RegisterDictionaryPref(
::prefs::kNoteTakingAppsLockScreenToastShown);
registry->RegisterBooleanPref(::prefs::kLockScreenAutoStartOnlineReauth,
false);
registry->RegisterBooleanPref(::prefs::kShowMobileDataNotification, true);
// Initially all existing users would see "What's new" for current version
// after update.
registry->RegisterStringPref(
::prefs::kChromeOSReleaseNotesVersion, "0.0.0.0",
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
::disks::prefs::RegisterProfilePrefs(registry);
registry->RegisterStringPref(::prefs::kTermsOfServiceURL, "");
registry->RegisterBooleanPref(::prefs::kTouchVirtualKeyboardEnabled, false);
registry->RegisterBooleanPref(::prefs::kVirtualKeyboardSmartVisibilityEnabled,
true);
registry->RegisterStringPref(prefs::kCaptureModePolicySavePath,
std::string());
std::string current_timezone_id;
if (CrosSettings::IsInitialized()) {
// In unit tests CrosSettings is not always initialized.
CrosSettings::Get()->GetString(kSystemTimezone, ¤t_timezone_id);
}
// |current_timezone_id| will be empty if CrosSettings doesn't know the
// timezone yet.
registry->RegisterStringPref(::prefs::kUserTimezone, current_timezone_id);
registry->RegisterBooleanPref(
::prefs::kResolveTimezoneByGeolocationMigratedToMethod, false,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
bool allow_time_zone_resolve_by_default = true;
// CfM devices default to static timezone unless time zone resolving is
// explicitly enabled for the signin screen (usually by policy).
// We need local_state fully initialized, which does not happen in tests.
if (!g_browser_process->local_state() ||
g_browser_process->local_state()
->GetAllPrefStoresInitializationStatus() ==
PrefService::INITIALIZATION_STATUS_WAITING ||
system::InputDeviceSettings::Get()->ForceKeyboardDrivenUINavigation()) {
allow_time_zone_resolve_by_default = false;
}
registry->RegisterIntegerPref(
::prefs::kResolveTimezoneByGeolocationMethod,
static_cast<int>(
allow_time_zone_resolve_by_default
? system::TimeZoneResolverManager::TimeZoneResolveMethod::IP_ONLY
: system::TimeZoneResolverManager::TimeZoneResolveMethod::
DISABLED),
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
registry->RegisterBooleanPref(
chromeos::prefs::kCaptivePortalAuthenticationIgnoresProxy, true);
registry->RegisterBooleanPref(::prefs::kLanguageImeMenuActivated, false);
registry->RegisterInt64Pref(::prefs::kHatsLastInteractionTimestamp, 0);
registry->RegisterTimePref(::prefs::kHatsPrioritizedLastInteractionTimestamp,
base::Time());
registry->RegisterInt64Pref(::prefs::kHatsSurveyCycleEndTimestamp, 0);
registry->RegisterBooleanPref(::prefs::kHatsDeviceIsSelected, false);
registry->RegisterInt64Pref(::prefs::kHatsOnboardingSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsOnboardingDeviceIsSelected,
false);
registry->RegisterInt64Pref(::prefs::kHatsArcGamesSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsArcGamesDeviceIsSelected, false);
registry->RegisterInt64Pref(::prefs::kHatsAudioSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsAudioDeviceIsSelected, false);
registry->RegisterInt64Pref(::prefs::kHatsAudioOutputProcSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsAudioOutputProcDeviceIsSelected,
false);
registry->RegisterInt64Pref(::prefs::kHatsBluetoothAudioSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsBluetoothAudioDeviceIsSelected,
false);
registry->RegisterInt64Pref(::prefs::kHatsEntSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsEntDeviceIsSelected, false);
registry->RegisterInt64Pref(::prefs::kHatsStabilitySurveyCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsStabilityDeviceIsSelected, false);
registry->RegisterInt64Pref(::prefs::kHatsPerformanceSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsPerformanceDeviceIsSelected,
false);
registry->RegisterInt64Pref(::prefs::kHatsCameraAppSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsCameraAppDeviceIsSelected, false);
registry->RegisterInt64Pref(::prefs::kHatsGeneralCameraSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsGeneralCameraIsSelected, false);
registry->RegisterInt64Pref(
::prefs::kHatsGeneralCameraPrioritizedSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(
::prefs::kHatsGeneralCameraPrioritizedIsSelected, false);
registry->RegisterTimePref(
::prefs::kHatsGeneralCameraPrioritizedLastInteractionTimestamp,
base::Time());
registry->RegisterInt64Pref(::prefs::kHatsBluetoothRevampCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsBluetoothRevampIsSelected, false);
registry->RegisterInt64Pref(::prefs::kHatsBatteryLifeCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsBatteryLifeIsSelected, false);
registry->RegisterInt64Pref(::prefs::kHatsPeripheralsCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsPeripheralsIsSelected, false);
registry->RegisterBooleanPref(::prefs::kHatsPrivacyHubPostLaunchIsSelected,
false);
registry->RegisterInt64Pref(::prefs::kHatsPrivacyHubPostLaunchCycleEndTs, 0);
// Personalization HaTS survey prefs for avatar, screensaver, and wallpaper
// features.
registry->RegisterInt64Pref(
::prefs::kHatsPersonalizationAvatarSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(
::prefs::kHatsPersonalizationAvatarSurveyIsSelected, false);
registry->RegisterInt64Pref(
::prefs::kHatsPersonalizationScreensaverSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(
::prefs::kHatsPersonalizationScreensaverSurveyIsSelected, false);
registry->RegisterInt64Pref(
::prefs::kHatsPersonalizationWallpaperSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(
::prefs::kHatsPersonalizationWallpaperSurveyIsSelected, false);
// MediaApp HaTS prefs for Pdf and Photos experiences.
registry->RegisterInt64Pref(::prefs::kHatsMediaAppPdfCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsMediaAppPdfIsSelected, false);
registry->RegisterInt64Pref(::prefs::kHatsPhotosExperienceCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsPhotosExperienceIsSelected,
false);
// Office HaTS prefs.
registry->RegisterInt64Pref(::prefs::kHatsOfficeSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsOfficeSurveyIsSelected, false);
registry->RegisterBooleanPref(::prefs::kPinUnlockFeatureNotificationShown,
false);
registry->RegisterBooleanPref(
::prefs::kFingerprintUnlockFeatureNotificationShown, false);
// We don't sync EOL related prefs because they are device specific.
registry->RegisterBooleanPref(::prefs::kEolNotificationDismissed, false);
registry->RegisterTimePref(::prefs::kEndOfLifeDate, base::Time());
registry->RegisterBooleanPref(::prefs::kFirstEolWarningDismissed, false);
registry->RegisterBooleanPref(::prefs::kSecondEolWarningDismissed, false);
registry->RegisterBooleanPref(
::prefs::kEolApproachingIncentiveNotificationDismissed, false);
registry->RegisterBooleanPref(::prefs::kEolPassedFinalIncentiveDismissed,
false);
// Extended Updates prefs.
registry->RegisterBooleanPref(prefs::kExtendedUpdatesNotificationDismissed,
false);
registry->RegisterBooleanPref(::prefs::kCastReceiverEnabled, false);
registry->RegisterBooleanPref(::prefs::kShowArcSettingsOnSessionStart, false);
registry->RegisterBooleanPref(::prefs::kShowSyncSettingsOnSessionStart,
false);
// Text-to-speech prefs.
registry->RegisterDictionaryPref(
::prefs::kTextToSpeechLangToVoiceName,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
registry->RegisterDoublePref(
::prefs::kTextToSpeechRate, blink::mojom::kSpeechSynthesisDefaultRate,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
registry->RegisterDoublePref(
::prefs::kTextToSpeechPitch, blink::mojom::kSpeechSynthesisDefaultPitch,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
registry->RegisterDoublePref(
::prefs::kTextToSpeechVolume, blink::mojom::kSpeechSynthesisDefaultVolume,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
registry->RegisterBooleanPref(prefs::kSyncOobeCompleted, false);
registry->RegisterBooleanPref(prefs::kRecordArcAppSyncMetrics, false);
registry->RegisterBooleanPref(::prefs::kTPMFirmwareUpdateCleanupDismissed,
false);
registry->RegisterBooleanPref(::prefs::kStartupBrowserWindowLaunchSuppressed,
false);
registry->RegisterBooleanPref(prefs::kLoginDisplayPasswordButtonEnabled,
true);
registry->RegisterBooleanPref(
prefs::kSuggestedContentEnabled, true,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
registry->RegisterBooleanPref(prefs::kMagicBoostEnabled, true);
registry->RegisterBooleanPref(prefs::kHmrEnabled, true);
registry->RegisterBooleanPref(prefs::kHmrFeedbackAllowed, true);
registry->RegisterIntegerPref(prefs::kHmrManagedSettings, 0);
registry->RegisterIntegerPref(
prefs::kHMRConsentStatus,
base::to_underlying(chromeos::HMRConsentStatus::kUnset));
registry->RegisterIntegerPref(prefs::kHMRConsentWindowDismissCount, 0);
registry->RegisterBooleanPref(
prefs::kLauncherResultEverLaunched, false,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
registry->RegisterDictionaryPref(prefs::kLauncherSearchNormalizerParameters);
registry->RegisterListPref(
prefs::kFilesAppFolderShortcuts,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
registry->RegisterBooleanPref(
prefs::kFilesAppUIPrefsMigrated, false,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
registry->RegisterBooleanPref(
prefs::kFilesAppTrashEnabled, true,
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
registry->RegisterBooleanPref(prefs::kUsbDetectorNotificationEnabled, true);
registry->RegisterBooleanPref(prefs::kShowAiIntroScreenEnabled, true);
registry->RegisterBooleanPref(prefs::kShowGeminiIntroScreenEnabled, true);
registry->RegisterBooleanPref(prefs::kShowTouchpadScrollScreenEnabled, true);
// Settings HaTS survey prefs for Settings and Settings Search features.
registry->RegisterInt64Pref(::prefs::kHatsOsSettingsSearchSurveyCycleEndTs,
0);
registry->RegisterBooleanPref(::prefs::kHatsOsSettingsSearchSurveyIsSelected,
false);
// Borealis HaTS survey prefs for game satisfaction.
registry->RegisterInt64Pref(::prefs::kHatsBorealisGamesSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsBorealisGamesSurveyIsSelected,
false);
registry->RegisterTimePref(
::prefs::kHatsBorealisGamesLastInteractionTimestamp, base::Time());
// Launcher HaTS survey prefs.
registry->RegisterInt64Pref(::prefs::kHatsLauncherAppsSurveyCycleEndTs, 0);
registry->RegisterBooleanPref(::prefs::kHatsLauncherAppsSurveyIsSelected,
false);
registry->RegisterBooleanPref(prefs::kShowDisplaySizeScreenEnabled, true);
registry->RegisterDictionaryPref(::prefs::kTotalUniqueOsSettingsChanged);
registry->RegisterBooleanPref(::prefs::kHasResetFirst7DaysSettingsUsedCount,
false);
registry->RegisterBooleanPref(::prefs::kHasEverRevokedMetricsConsent, true);
registry->RegisterBooleanPref(prefs::kShowHumanPresenceSensorScreenEnabled,
true);
registry->RegisterListPref(prefs::kUserFeedbackWithLowLevelDebugDataAllowed);
registry->RegisterBooleanPref(prefs::kIsolatedWebAppsEnabled, false);
registry->RegisterDictionaryPref(prefs::kAshAppIconLightVibrantColorCache);
registry->RegisterDictionaryPref(prefs::kAshAppIconSortableColorGroupCache);
registry->RegisterDictionaryPref(prefs::kAshAppIconSortableColorHueCache);
registry->RegisterStringPref(::prefs::kFilesAppDefaultLocation,
std::string());
}
void Preferences::InitUserPrefs(sync_preferences::PrefServiceSyncable* prefs) {
prefs_ = prefs;
BooleanPrefMember::NamedChangeCallback callback = base::BindRepeating(
&Preferences::OnPreferenceChanged, base::Unretained(this));
performance_tracing_enabled_.Init(::prefs::kPerformanceTracingEnabled, prefs,
callback);
tap_to_click_enabled_.Init(prefs::kTapToClickEnabled, prefs, callback);
three_finger_click_enabled_.Init(prefs::kEnableTouchpadThreeFingerClick,
prefs, callback);
unified_desktop_enabled_by_default_.Init(
::prefs::kUnifiedDesktopEnabledByDefault, prefs, callback);
// TODO(anasalazar): Finish moving this to ash.
natural_scroll_.Init(prefs::kNaturalScroll, prefs, callback);
mouse_reverse_scroll_.Init(prefs::kMouseReverseScroll, prefs, callback);
mouse_sensitivity_.Init(prefs::kMouseSensitivity, prefs, callback);
mouse_scroll_sensitivity_.Init(prefs::kMouseScrollSensitivity, prefs,
callback);
touchpad_sensitivity_.Init(prefs::kTouchpadSensitivity, prefs, callback);
touchpad_scroll_sensitivity_.Init(prefs::kTouchpadScrollSensitivity, prefs,
callback);
pointing_stick_sensitivity_.Init(prefs::kPointingStickSensitivity, prefs,
callback);
primary_mouse_button_right_.Init(prefs::kPrimaryMouseButtonRight, prefs,
callback);
primary_pointing_stick_button_right_.Init(
prefs::kPrimaryPointingStickButtonRight, prefs, callback);
mouse_acceleration_.Init(prefs::kMouseAcceleration, prefs, callback);
mouse_scroll_acceleration_.Init(prefs::kMouseScrollAcceleration, prefs,
callback);
pointing_stick_acceleration_.Init(prefs::kPointingStickAcceleration, prefs,
callback);
touchpad_acceleration_.Init(prefs::kTouchpadAcceleration, prefs, callback);
touchpad_scroll_acceleration_.Init(prefs::kTouchpadScrollAcceleration, prefs,
callback);
touchpad_haptic_feedback_.Init(prefs::kTouchpadHapticFeedback, prefs,
callback);
touchpad_haptic_click_sensitivity_.Init(
prefs::kTouchpadHapticClickSensitivity, prefs, callback);
download_default_directory_.Init(::prefs::kDownloadDefaultDirectory, prefs,
callback);
preload_engines_.Init(::prefs::kLanguagePreloadEngines, prefs, callback);
enabled_imes_.Init(::prefs::kLanguageEnabledImes, prefs, callback);
current_input_method_.Init(::prefs::kLanguageCurrentInputMethod, prefs,
callback);
previous_input_method_.Init(::prefs::kLanguagePreviousInputMethod, prefs,
callback);
allowed_input_methods_.Init(::prefs::kLanguageAllowedInputMethods, prefs,
callback);
allowed_languages_.Init(::prefs::kAllowedLanguages, prefs, callback);
preferred_languages_.Init(language::prefs::kPreferredLanguages, prefs,
callback);
ime_menu_activated_.Init(::prefs::kLanguageImeMenuActivated, prefs, callback);
// Notifies the system tray to remove the IME items.
if (ime_menu_activated_.GetValue()) {
input_method::InputMethodManager::Get()->ImeMenuActivationChanged(true);
}
long_press_diacritics_enabled_.Init(prefs::kLongPressDiacriticsEnabled, prefs,
callback);
xkb_auto_repeat_enabled_.Init(prefs::kXkbAutoRepeatEnabled, prefs, callback);
xkb_auto_repeat_delay_pref_.Init(prefs::kXkbAutoRepeatDelay, prefs, callback);
xkb_auto_repeat_interval_pref_.Init(prefs::kXkbAutoRepeatInterval, prefs,
callback);
pci_data_access_enabled_pref_.Init(
prefs::kLocalStateDevicePeripheralDataAccessEnabled,
g_browser_process->local_state(), callback);
consumer_auto_update_toggle_pref_.Init(::prefs::kConsumerAutoUpdateToggle,
g_browser_process->local_state(),
callback);
pref_change_registrar_.Init(prefs);
pref_change_registrar_.Add(ash::prefs::kUserGeolocationAccessLevel, callback);
pref_change_registrar_.Add(ash::prefs::kUserPreviousGeolocationAccessLevel,
callback);
pref_change_registrar_.Add(::prefs::kUserTimezone, callback);
pref_change_registrar_.Add(::prefs::kResolveTimezoneByGeolocationMethod,
callback);
pref_change_registrar_.Add(::prefs::kParentAccessCodeConfig, callback);
for (auto* copy_pref : kCopyToKnownUserPrefs) {
pref_change_registrar_.Add(copy_pref, callback);
}
// Re-enable OTA update when feature flag is disabled by owner.
auto* update_engine_client = UpdateEngineClient::Get();
if (user_manager::UserManager::Get()->IsCurrentUserOwner() &&
!features::IsConsumerAutoUpdateToggleAllowed()) {
// Write into the platform will signal back so pref gets synced.
update_engine_client->ToggleFeature(
update_engine::kFeatureConsumerAutoUpdate, true);
} else {
// Otherwise, trigger a read + sync with signal.
update_engine_client->IsFeatureEnabled(
update_engine::kFeatureConsumerAutoUpdate,
base::BindOnce(&Preferences::OnIsConsumerAutoUpdateEnabled,
weak_ptr_factory_.GetWeakPtr()));
}
}
void Preferences::Init(Profile* profile, const user_manager::User* user) {
DCHECK(profile);
DCHECK(user);
sync_preferences::PrefServiceSyncable* prefs =
PrefServiceSyncableFromProfile(profile);
// This causes OnIsSyncingChanged to be called when the value of
// PrefService::IsSyncing() changes.
prefs->AddObserver(this);
UpdateEngineClient::Get()->AddObserver(this);
user_ = user;
user_is_primary_ =
user_manager::UserManager::Get()->GetPrimaryUser() == user_;
InitUserPrefs(prefs);
user_manager::UserManager::Get()->AddSessionStateObserver(this);
UserSessionManager* session_manager = UserSessionManager::GetInstance();
DCHECK(session_manager);
ime_state_ = session_manager->GetDefaultIMEState(profile);
if (user_is_primary_) {
g_browser_process->platform_part()
->GetTimezoneResolverManager()
->SetPrimaryUserPrefs(prefs_);
}
// Initialize preferences to currently saved state.
ApplyPreferences(REASON_INITIALIZATION, "");
const std::string& login_input_method_id_used =
session_manager->user_context().GetLoginInputMethodIdUsed();
if (user_is_primary_ && !login_input_method_id_used.empty()) {
// Persist input method when transitioning from Login screen into the
// session.
input_method::InputMethodPersistence::SetUserLastLoginInputMethodId(
login_input_method_id_used, input_method::InputMethodManager::Get(),
profile);
}
// Note that |ime_state_| was modified by ApplyPreferences(), and
// SetState() is modifying |current_input_method_| (via
// PersistUserInputMethod() ). This way SetState() here may be called only
// after ApplyPreferences().
// As InputMethodManager only holds the active state for the active user,
// SetState() is only called if the preferences belongs to the active user.
// See https://crbug.com/841112.
if (user->is_active()) {
input_method_manager_->SetState(ime_state_);
}
input_method_syncer_ =
std::make_unique<input_method::InputMethodSyncer>(prefs, ime_state_);
input_method_syncer_->Initialize();
// If a guest is logged in, initialize the prefs as if this is the first
// login. For a regular user this is done in
// UserSessionManager::InitProfilePreferences().
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kGuestSession)) {
session_manager->SetFirstLoginPrefs(profile, std::string(), std::string());
}
}
void Preferences::InitUserPrefsForTesting(
sync_preferences::PrefServiceSyncable* prefs,
const user_manager::User* user,
scoped_refptr<input_method::InputMethodManager::State> ime_state) {
user_ = user;
ime_state_ = ime_state;
if (ime_state.get()) {
input_method_manager_->SetState(ime_state);
}
InitUserPrefs(prefs);
UpdateEngineClient::Get()->AddObserver(this);
input_method_syncer_ =
std::make_unique<input_method::InputMethodSyncer>(prefs, ime_state_);
input_method_syncer_->Initialize();
}
void Preferences::SetInputMethodListForTesting() {
SetInputMethodList();
}
void Preferences::OnPreferenceChanged(const std::string& pref_name) {
ApplyPreferences(REASON_PREF_CHANGED, pref_name);
}
void Preferences::ReportBooleanPrefApplication(
ApplyReason reason,
const std::string& changed_histogram_name,
const std::string& started_histogram_name,
bool sample) {
if (reason == REASON_PREF_CHANGED) {
base::UmaHistogramBoolean(changed_histogram_name, sample);
} else if (reason == REASON_INITIALIZATION) {
base::UmaHistogramBoolean(started_histogram_name, sample);
}
}
void Preferences::ReportSensitivityPrefApplication(
ApplyReason reason,
const std::string& changed_histogram_name,
const std::string& started_histogram_name,
int sensitivity_int) {
system::PointerSensitivity sensitivity =
static_cast<system::PointerSensitivity>(sensitivity_int);
if (reason == REASON_PREF_CHANGED) {
base::UmaHistogramEnumeration(changed_histogram_name, sensitivity);
} else if (reason == REASON_INITIALIZATION) {
base::UmaHistogramEnumeration(started_histogram_name, sensitivity);
}
}
void Preferences::ReportTimePrefApplication(
ApplyReason reason,
const std::string& changed_histogram_name,
const std::string& started_histogram_name,
base::TimeDelta duration) {
if (reason == REASON_PREF_CHANGED) {
base::UmaHistogramTimes(changed_histogram_name, duration);
} else if (reason == REASON_INITIALIZATION) {
base::UmaHistogramTimes(started_histogram_name, duration);
}
}
void Preferences::ApplyPreferences(ApplyReason reason,
const std::string& pref_name) {
DCHECK(reason != REASON_PREF_CHANGED || !pref_name.empty());
const bool user_is_owner =
user_manager::UserManager::Get()->GetOwnerAccountId() ==
user_->GetAccountId();
const bool user_is_active = user_->is_active();
system::TouchpadSettings touchpad_settings;
system::MouseSettings mouse_settings;
system::PointingStickSettings pointing_stick_settings;
user_manager::KnownUser known_user(g_browser_process->local_state());
if (user_is_primary_ && (reason == REASON_INITIALIZATION ||
pref_name == ::prefs::kPerformanceTracingEnabled)) {
const bool enabled = performance_tracing_enabled_.GetValue();
if (enabled) {
tracing_manager_ = ContentTracingManager::Create();
} else {
tracing_manager_.reset();
}
SystemTrayClientImpl::Get()->SetPerformanceTracingIconVisible(enabled);
}
if (reason != REASON_PREF_CHANGED || pref_name == prefs::kTapToClickEnabled) {
const bool enabled = tap_to_click_enabled_.GetValue();
if (user_is_active) {
touchpad_settings.SetTapToClick(enabled);
}
ReportBooleanPrefApplication(reason, "Touchpad.TapToClick.Changed",
"Touchpad.TapToClick.Started", enabled);
// Save owner preference in local state to use on login screen.
if (user_is_owner) {
PrefService* prefs = g_browser_process->local_state();
if (prefs->GetBoolean(prefs::kOwnerTapToClickEnabled) != enabled) {
prefs->SetBoolean(prefs::kOwnerTapToClickEnabled, enabled);
}
}
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kEnableTouchpadThreeFingerClick) {
const bool enabled = three_finger_click_enabled_.GetValue();
if (user_is_active) {
touchpad_settings.SetThreeFingerClick(enabled);
}
}
if (reason != REASON_PREF_CHANGED ||
pref_name == ::prefs::kUnifiedDesktopEnabledByDefault) {
// "Unified Desktop" is a per-user policy setting which will not be applied
// until a user logs in.
if (cros_display_config_) { // May be null in tests.
cros_display_config_->SetUnifiedDesktopEnabled(
unified_desktop_enabled_by_default_.GetValue());
}
}
// TODO(anasalazar): Finish moving this to ash.
if (reason != REASON_PREF_CHANGED || pref_name == prefs::kNaturalScroll) {
// Force natural scroll default if we've sync'd and if the cmd line arg is
// set.
ForceNaturalScrollDefault();
const bool enabled = natural_scroll_.GetValue();
DVLOG(1) << "Natural scroll set to " << enabled;
if (user_is_active) {
touchpad_settings.SetNaturalScroll(enabled);
}
ReportBooleanPrefApplication(reason, "Touchpad.NaturalScroll.Changed",
"Touchpad.NaturalScroll.Started", enabled);
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kMouseReverseScroll) {
const bool enabled = mouse_reverse_scroll_.GetValue();
if (user_is_active) {
mouse_settings.SetReverseScroll(enabled);
}
}
if (reason != REASON_PREF_CHANGED || pref_name == prefs::kMouseSensitivity) {
const int sensitivity_int = mouse_sensitivity_.GetValue();
if (user_is_active) {
mouse_settings.SetSensitivity(sensitivity_int);
// With the flag off, also set scroll sensitivity (legacy fallback).
// TODO(https://crbug.com/836258): Remove check when flag is removed.
if (!AreScrollSettingsAllowed()) {
mouse_settings.SetScrollSensitivity(sensitivity_int);
}
}
ReportSensitivityPrefApplication(reason, "Mouse.PointerSensitivity.Changed",
"Mouse.PointerSensitivity.Started",
sensitivity_int);
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kMouseScrollSensitivity) {
// With the flag off, use to normal sensitivity (legacy fallback).
// TODO(https://crbug.com/836258): Remove check when flag is removed.
const int sensitivity_int = AreScrollSettingsAllowed()
? mouse_scroll_sensitivity_.GetValue()
: mouse_sensitivity_.GetValue();
if (user_is_active) {
mouse_settings.SetScrollSensitivity(sensitivity_int);
}
ReportSensitivityPrefApplication(reason, "Mouse.ScrollSensitivity.Changed",
"Mouse.ScrollSensitivity.Started",
sensitivity_int);
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kPointingStickSensitivity) {
const int sensitivity_int = pointing_stick_sensitivity_.GetValue();
if (user_is_active) {
pointing_stick_settings.SetSensitivity(sensitivity_int);
}
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kTouchpadSensitivity) {
const int sensitivity_int = touchpad_sensitivity_.GetValue();
if (user_is_active) {
touchpad_settings.SetSensitivity(sensitivity_int);
// With the flag off, also set scroll sensitivity (legacy fallback).
// TODO(https://crbug.com/836258): Remove check when flag is removed.
if (!AreScrollSettingsAllowed()) {
touchpad_settings.SetScrollSensitivity(sensitivity_int);
}
}
ReportSensitivityPrefApplication(
reason, "Touchpad.PointerSensitivity.Changed",
"Touchpad.PointerSensitivity.Started", sensitivity_int);
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kTouchpadScrollSensitivity) {
// With the flag off, use normal sensitivity (legacy fallback).
// TODO(https://crbug.com/836258): Remove check when flag is removed.
const int sensitivity_int = AreScrollSettingsAllowed()
? touchpad_scroll_sensitivity_.GetValue()
: touchpad_sensitivity_.GetValue();
if (user_is_active) {
touchpad_settings.SetScrollSensitivity(sensitivity_int);
}
ReportSensitivityPrefApplication(
reason, "Touchpad.ScrollSensitivity.Changed",
"Touchpad.ScrollSensitivity.Started", sensitivity_int);
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kPrimaryMouseButtonRight) {
const bool right = primary_mouse_button_right_.GetValue();
if (user_is_active) {
mouse_settings.SetPrimaryButtonRight(right);
}
ReportBooleanPrefApplication(reason, "Mouse.PrimaryButtonRight.Changed",
"Mouse.PrimaryButtonRight.Started", right);
// Save owner preference in local state to use on login screen.
if (user_is_owner) {
PrefService* prefs = g_browser_process->local_state();
if (prefs->GetBoolean(prefs::kOwnerPrimaryMouseButtonRight) != right) {
prefs->SetBoolean(prefs::kOwnerPrimaryMouseButtonRight, right);
}
}
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kPrimaryPointingStickButtonRight) {
const bool right = primary_pointing_stick_button_right_.GetValue();
if (user_is_active) {
pointing_stick_settings.SetPrimaryButtonRight(right);
}
// Save owner preference in local state to use on login screen.
if (user_is_owner) {
PrefService* prefs = g_browser_process->local_state();
if (prefs->GetBoolean(prefs::kOwnerPrimaryPointingStickButtonRight) !=
right) {
prefs->SetBoolean(prefs::kOwnerPrimaryPointingStickButtonRight, right);
}
}
}
if (reason != REASON_PREF_CHANGED || pref_name == prefs::kMouseAcceleration) {
const bool enabled = mouse_acceleration_.GetValue();
if (user_is_active) {
mouse_settings.SetAcceleration(enabled);
}
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kMouseScrollAcceleration) {
const bool enabled = mouse_scroll_acceleration_.GetValue();
if (user_is_active) {
mouse_settings.SetScrollAcceleration(enabled);
}
ReportBooleanPrefApplication(reason, "Mouse.ScrollAcceleration.Changed",
"Mouse.ScrollAcceleration.Started", enabled);
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kPointingStickAcceleration) {
const bool enabled = pointing_stick_acceleration_.GetValue();
if (user_is_active) {
pointing_stick_settings.SetAcceleration(enabled);
}
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kTouchpadAcceleration) {
const bool enabled = touchpad_acceleration_.GetValue();
if (user_is_active) {
touchpad_settings.SetAcceleration(enabled);
}
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kTouchpadScrollAcceleration) {
const bool enabled = touchpad_scroll_acceleration_.GetValue();
if (user_is_active) {
touchpad_settings.SetScrollAcceleration(enabled);
}
ReportBooleanPrefApplication(reason, "Touchpad.ScrollAcceleration.Changed",
"Touchpad.ScrollAcceleration.Started",
enabled);
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kTouchpadHapticFeedback) {
const bool enabled = touchpad_haptic_feedback_.GetValue();
if (user_is_active) {
touchpad_settings.SetHapticFeedback(enabled);
}
ReportBooleanPrefApplication(reason, "Touchpad.HapticFeedback.Changed",
"Touchpad.HapticFeedback.Started", enabled);
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kTouchpadHapticClickSensitivity) {
const int sensitivity_int = touchpad_haptic_click_sensitivity_.GetValue();
if (user_is_active) {
touchpad_settings.SetHapticClickSensitivity(sensitivity_int);
}
ReportSensitivityPrefApplication(
reason, "Touchpad.HapticClickSensitivity.Changed",
"Touchpad.HapticClickSensitivity.Started", sensitivity_int);
}
if (reason != REASON_PREF_CHANGED ||
pref_name == ::prefs::kDownloadDefaultDirectory) {
const bool default_download_to_drive = drive::util::IsUnderDriveMountPoint(
download_default_directory_.GetValue());
ReportBooleanPrefApplication(
reason, "FileBrowser.DownloadDestination.IsGoogleDrive.Changed",
"FileBrowser.DownloadDestination.IsGoogleDrive.Started",
default_download_to_drive);
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kXkbAutoRepeatEnabled) {
if (user_is_active) {
const bool enabled = xkb_auto_repeat_enabled_.GetValue();
input_method::InputMethodManager::Get()
->GetImeKeyboard()
->SetAutoRepeatEnabled(enabled);
known_user.SetBooleanPref(user_->GetAccountId(),
prefs::kXkbAutoRepeatEnabled, enabled);
ReportBooleanPrefApplication(
reason, "ChromeOS.Settings.Device.Keyboard.AutoRepeatEnabled.Changed",
"ChromeOS.Settings.Device.Keyboard.AutoRepeatEnabled.Initial",
xkb_auto_repeat_enabled_.GetValue());
}
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kXkbAutoRepeatDelay) {
if (user_is_active) {
UpdateAutoRepeatRate();
ReportTimePrefApplication(
reason, "ChromeOS.Settings.Device.Keyboard.AutoRepeatDelay.Changed",
"ChromeOS.Settings.Device.Keyboard.AutoRepeatDelay.Initial",
base::Milliseconds(xkb_auto_repeat_delay_pref_.GetValue()));
}
}
if (reason != REASON_PREF_CHANGED ||
pref_name == prefs::kXkbAutoRepeatInterval) {
if (user_is_active) {
UpdateAutoRepeatRate();
ReportTimePrefApplication(
reason,
"ChromeOS.Settings.Device.Keyboard.AutoRepeatInterval.Changed",
"ChromeOS.Settings.Device.Keyboard.AutoRepeatInterval.Initial",
base::Milliseconds(xkb_auto_repeat_interval_pref_.GetValue()));
}
}
if (reason == REASON_INITIALIZATION) {
SetInputMethodList();
}
if (reason != REASON_PREF_CHANGED ||
pref_name == ::prefs::kLanguageAllowedInputMethods) {
const std::vector<std::string> allowed_input_methods =
allowed_input_methods_.GetValue();
bool managed_by_policy =
ime_state_->SetAllowedInputMethods(allowed_input_methods);
bool success = ime_state_->ReplaceEnabledInputMethods(
ime_state_->GetEnabledInputMethodIds());
if (!success) {
const std::vector<std::string> fallback = {
ime_state_->GetAllowedFallBackKeyboardLayout()};
ime_state_->ReplaceEnabledInputMethods(fallback);
}
if (managed_by_policy) {
preload_engines_.SetValue(
base::JoinString(ime_state_->GetEnabledInputMethodIds(), ","));
}
}
if (reason != REASON_PREF_CHANGED ||
pref_name == ::prefs::kAllowedLanguages) {
locale_util::RemoveDisallowedLanguagesFromPreferred(prefs_);
}
if (reason != REASON_PREF_CHANGED ||
pref_name == language::prefs::kPreferredLanguages) {
// In case setting has been changed with sync it can contain disallowed
// values.
locale_util::RemoveDisallowedLanguagesFromPreferred(prefs_);
}
if (pref_name == ::prefs::kLanguagePreloadEngines &&
reason == REASON_PREF_CHANGED) {
SetLanguageConfigStringListAsCSV(language_prefs::kGeneralSectionName,
language_prefs::kPreloadEnginesConfigName,
preload_engines_.GetValue());
}
if ((reason == REASON_INITIALIZATION) ||
(pref_name == ::prefs::kLanguageEnabledImes &&
reason == REASON_PREF_CHANGED)) {
std::string value(enabled_imes_.GetValue());
std::vector<std::string> split_values;
if (!value.empty()) {
split_values = base::SplitString(value, ",", base::TRIM_WHITESPACE,
base::SPLIT_WANT_ALL);
}
ime_state_->SetEnabledExtensionImes(split_values);
}
if (pref_name == ::prefs::kLanguageImeMenuActivated &&
(reason == REASON_PREF_CHANGED || reason == REASON_ACTIVE_USER_CHANGED)) {
const bool activated = ime_menu_activated_.GetValue();
input_method::InputMethodManager::Get()->ImeMenuActivationChanged(
activated);
}
if (user_is_active) {
system::InputDeviceSettings::Get()->UpdateTouchpadSettings(
touchpad_settings);
system::InputDeviceSettings::Get()->UpdateMouseSettings(mouse_settings);
system::InputDeviceSettings::Get()->UpdatePointingStickSettings(
pointing_stick_settings);
}
// TODO(b/277061508): Move this logic inside
// GeolocationPrivacySwitchController.
if (reason == REASON_INITIALIZATION ||
(pref_name == ash::prefs::kUserGeolocationAccessLevel &&
reason == REASON_PREF_CHANGED)) {
const auto user_geolocation_access_level =
static_cast<GeolocationAccessLevel>(
prefs_->GetInteger(ash::prefs::kUserGeolocationAccessLevel));
// Notify `SimpleGeolocationProvider` of the user geolocation permission
// change.
SimpleGeolocationProvider::GetInstance()->SetGeolocationAccessLevel(
user_geolocation_access_level);
// Log-in screen follows the owner's geolocation setting.
if (user_is_owner) {
GeolocationAccessLevel access_level;
if (SimpleGeolocationProvider::GetInstance()
->IsGeolocationUsageAllowedForSystem()) {
access_level = GeolocationAccessLevel::kAllowed;
} else {
access_level = GeolocationAccessLevel::kDisallowed;
}
g_browser_process->local_state()->SetInteger(
ash::prefs::kDeviceGeolocationAllowed,
static_cast<int>(access_level));
}
}
if (pref_name == ::prefs::kUserTimezone &&
reason != REASON_ACTIVE_USER_CHANGED) {
system::UpdateSystemTimezone(ProfileHelper::Get()->GetProfileByUser(user_));
}
if (reason == REASON_INITIALIZATION ||
(pref_name == ::prefs::kResolveTimezoneByGeolocationMethod &&
reason != REASON_ACTIVE_USER_CHANGED)) {
if (prefs_->GetInteger(::prefs::kResolveTimezoneByGeolocationMethod) !=
static_cast<int>(
system::TimeZoneResolverManager::TimeZoneResolveMethod::DISABLED)) {
prefs_->SetBoolean(::prefs::kResolveTimezoneByGeolocationMigratedToMethod,
true);
}
if (user_is_owner) {
// Policy check is false here, because there is no owner for enterprise.
g_browser_process->local_state()->SetInteger(
::prefs::kResolveDeviceTimezoneByGeolocationMethod,
static_cast<int>(system::TimeZoneResolverManager::
GetEffectiveUserTimeZoneResolveMethod(
prefs_, false /* check_policy */)));
}
if (user_is_primary_) {
g_browser_process->platform_part()
->GetTimezoneResolverManager()
->UpdateTimezoneResolver();
if (system::TimeZoneResolverManager::
GetEffectiveUserTimeZoneResolveMethod(
prefs_, true /* check_policy */) ==
system::TimeZoneResolverManager::TimeZoneResolveMethod::
DISABLED &&
reason == REASON_PREF_CHANGED) {
// Allow immediate timezone update on Stop + Start.
g_browser_process->local_state()->ClearPref(
TimeZoneResolver::kLastTimeZoneRefreshTime);
}
}
}
if (pref_name == ::prefs::kParentAccessCodeConfig ||
reason != REASON_PREF_CHANGED) {
if (prefs_->IsManagedPreference(::prefs::kParentAccessCodeConfig) &&
user_->IsChild()) {
const base::Value::Dict& value =
prefs_->GetDict(::prefs::kParentAccessCodeConfig);
known_user.SetPath(user_->GetAccountId(),
::prefs::kKnownUserParentAccessCodeConfig,
base::Value(value.Clone()));
parent_access::ParentAccessService::Get().LoadConfigForUser(user_);
} else {
known_user.RemovePref(user_->GetAccountId(),
::prefs::kKnownUserParentAccessCodeConfig);
}
}
for (auto* copy_pref : kCopyToKnownUserPrefs) {
if (pref_name == copy_pref || reason != REASON_ACTIVE_USER_CHANGED) {
known_user.SetPath(user_->GetAccountId(), copy_pref,
prefs_->GetValue(copy_pref).Clone());
}
}
if (pref_name == prefs::kLocalStateDevicePeripheralDataAccessEnabled &&
reason == REASON_PREF_CHANGED) {
const bool value = g_browser_process->local_state()->GetBoolean(
prefs::kLocalStateDevicePeripheralDataAccessEnabled);
if (PeripheralNotificationManager::IsInitialized()) {
PeripheralNotificationManager::Get()->SetPcieTunnelingAllowedState(value);
}
PciguardClient::Get()->SendExternalPciDevicesPermissionState(value);
TypecdClient::Get()->SetPeripheralDataAccessPermissionState(value);
}
}
void Preferences::OnIsSyncingChanged() {
DVLOG(1) << "OnIsSyncingChanged";
ForceNaturalScrollDefault();
}
// TODO(anasalazar): Finish moving this to TouchDevicesController.
void Preferences::ForceNaturalScrollDefault() {
DVLOG(1) << "ForceNaturalScrollDefault";
// Natural scroll is a priority pref.
bool is_syncing = prefs_->AreOsPriorityPrefsSyncing();
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kNaturalScrollDefault) &&
is_syncing && !prefs_->GetUserPrefValue(prefs::kNaturalScroll)) {
DVLOG(1) << "Natural scroll forced to true";
natural_scroll_.SetValue(true);
}
}
void Preferences::SetLanguageConfigStringListAsCSV(const char* section,
const char* name,
const std::string& value) {
VLOG(1) << "Setting " << name << " to '" << value << "'";
std::vector<std::string> split_values;
if (!value.empty()) {
split_values = base::SplitString(value, ",", base::TRIM_WHITESPACE,
base::SPLIT_WANT_ALL);
}
// Transfers the xkb id to extension-xkb id.
if (input_method_manager_->GetMigratedInputMethodIDs(&split_values)) {
preload_engines_.SetValue(base::JoinString(split_values, ","));
}
if (section == std::string(language_prefs::kGeneralSectionName) &&
name == std::string(language_prefs::kPreloadEnginesConfigName)) {
ime_state_->ReplaceEnabledInputMethods(split_values);
return;
}
}
void Preferences::SetInputMethodList() {
// When |preload_engines_| are set, InputMethodManager::ChangeInputMethod()
// might be called to change the current input method to the first one in the
// |preload_engines_| list. This also updates previous/current input method
// prefs. That's why GetValue() calls are placed before the
// SetLanguageConfigStringListAsCSV() call below.
const std::string previous_input_method_id =
previous_input_method_.GetValue();
const std::string current_input_method_id = current_input_method_.GetValue();
SetLanguageConfigStringListAsCSV(language_prefs::kGeneralSectionName,
language_prefs::kPreloadEnginesConfigName,
preload_engines_.GetValue());
// ChangeInputMethod() has to be called AFTER the value of |preload_engines_|
// is sent to the InputMethodManager. Otherwise, the ChangeInputMethod request
// might be ignored as an invalid input method ID. The ChangeInputMethod()
// calls are also necessary to restore the previous/current input method prefs
// which could have been modified by the SetLanguageConfigStringListAsCSV call
// above to the original state.
if (!previous_input_method_id.empty()) {
ime_state_->ChangeInputMethod(previous_input_method_id,
false /* show_message */);
}
if (!current_input_method_id.empty()) {
ime_state_->ChangeInputMethod(current_input_method_id,
false /* show_message */);
}
}
void Preferences::UpdateAutoRepeatRate() {
input_method::AutoRepeatRate rate{
.initial_delay =
base::Milliseconds(xkb_auto_repeat_delay_pref_.GetValue()),
.repeat_interval =
base::Milliseconds(xkb_auto_repeat_interval_pref_.GetValue()),
};
DCHECK(rate.initial_delay.is_positive());
DCHECK(rate.repeat_interval.is_positive());
input_method::InputMethodManager::Get()->GetImeKeyboard()->SetAutoRepeatRate(
rate);
user_manager::KnownUser known_user(g_browser_process->local_state());
known_user.SetIntegerPref(user_->GetAccountId(), prefs::kXkbAutoRepeatDelay,
rate.initial_delay.InMilliseconds());
known_user.SetIntegerPref(user_->GetAccountId(),
prefs::kXkbAutoRepeatInterval,
rate.repeat_interval.InMilliseconds());
}
void Preferences::ActiveUserChanged(user_manager::User* active_user) {
if (active_user != user_) {
return;
}
ApplyPreferences(REASON_ACTIVE_USER_CHANGED, "");
}
void Preferences::UpdateStatusChanged(
const update_engine::StatusResult& status) {
DVLOG(1) << "UpdateStatusChanged";
for (int i = 0; i < status.features_size(); ++i) {
const update_engine::Feature& feature = status.features(i);
bool enabled = feature.enabled();
DVLOG(1) << "Feature name=" << feature.name() << " enabled=" << enabled;
if (feature.name() == update_engine::kFeatureConsumerAutoUpdate) {
// Writes into this preference are only flushed by listening to
// platform side signals. This means Chrome side writes into this
// preference will not be visible outside of Chrome. This preference
// should be updated by making DBus calls into the platform side, which
// will signal out the true value of this preference as the true value is
// managed by the update_engine daemon.
consumer_auto_update_toggle_pref_.SetValue(enabled);
}
}
}
void Preferences::OnIsConsumerAutoUpdateEnabled(std::optional<bool> enabled) {
DVLOG(1) << "OnIsConsumerAutoUpdateEnabled";
if (!enabled.has_value()) {
VLOG(1) << "Failed to retrieve consumer auto update feature value.";
return;
}
consumer_auto_update_toggle_pref_.SetValue(enabled.value());
}
} // namespace ash