From aa003a516ad8ee8e86066ab2ea343a30426b47ca Mon Sep 17 00:00:00 2001 From: "dzhioev@chromium.org" Date: Sat, 15 Feb 2014 06:24:23 +0000 Subject: [PATCH] chromeos::Preferences works correctly in multi-profile session. * When pref is changed it is applied only if user owning this pref is active. * Owner's prefernces is saved to local state even if owner is inactive. Additionally: * Removed deprecated pref kEnableTouchpadThreeFingerSwipe. BUG=325564,223480 TEST=browser_tests --gtest_filter=PreferencesTest.* TBR=noms Review URL: https://codereview.chromium.org/142913004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251550 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/browser/chromeos/login/login_browsertest.cc | 4 +- chrome/browser/chromeos/preferences.cc | 235 ++++++++++----------- chrome/browser/chromeos/preferences.h | 53 ++--- chrome/browser/chromeos/preferences_browsertest.cc | 202 ++++++++++++++++++ chrome/browser/chromeos/preferences_unittest.cc | 10 +- .../profiles/off_the_record_profile_impl.cc | 2 +- chrome/browser/profiles/profile_impl.cc | 7 +- chrome/chrome_tests.gypi | 1 + 8 files changed, 363 insertions(+), 151 deletions(-) create mode 100644 chrome/browser/chromeos/preferences_browsertest.cc diff --git a/chrome/browser/chromeos/login/login_browsertest.cc b/chrome/browser/chromeos/login/login_browsertest.cc index 6e5c04292453..34c157565cbd 100644 --- a/chrome/browser/chromeos/login/login_browsertest.cc +++ b/chrome/browser/chromeos/login/login_browsertest.cc @@ -10,6 +10,7 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/login/login_display_host_impl.h" #include "chrome/browser/chromeos/login/login_wizard.h" +#include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/browser.h" @@ -47,6 +48,8 @@ class LoginGuestTest : public InProcessBrowserTest { command_line->AppendSwitch(chromeos::switches::kGuestSession); command_line->AppendSwitch(::switches::kIncognito); command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); + command_line->AppendSwitchASCII(chromeos::switches::kLoginUser, + chromeos::UserManager::kGuestUserName); } }; @@ -147,7 +150,6 @@ IN_PROC_BROWSER_TEST_F(LoginUserTest, CursorShown) { // After a guest login, we should get the OTR default profile. IN_PROC_BROWSER_TEST_F(LoginGuestTest, GuestIsOTR) { Profile* profile = browser()->profile(); - EXPECT_EQ("Default", profile->GetPath().BaseName().value()); EXPECT_TRUE(profile->IsOffTheRecord()); // Ensure there's extension service for this profile. EXPECT_TRUE(extensions::ExtensionSystem::Get(profile)->extension_service()); diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index b65a8e8c20d7..67a84cdd16cd 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc @@ -23,7 +23,7 @@ #include "chrome/browser/chromeos/drive/file_system_util.h" #include "chrome/browser/chromeos/input_method/input_method_util.h" #include "chrome/browser/chromeos/login/login_utils.h" -#include "chrome/browser/chromeos/login/user_manager.h" +#include "chrome/browser/chromeos/login/user.h" #include "chrome/browser/chromeos/system/input_device_settings.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/feedback/tracing_manager.h" @@ -44,14 +44,11 @@ namespace chromeos { static const char kFallbackInputMethodLocale[] = "en-US"; -// TODO(achuith): Remove deprecated pref in M31. crbug.com/223480. -static const char kEnableTouchpadThreeFingerSwipe[] = - "settings.touchpad.enable_three_finger_swipe"; - Preferences::Preferences() : prefs_(NULL), input_method_manager_(input_method::InputMethodManager::Get()), - is_primary_user_prefs_(true) { + user_(NULL), + user_is_primary_(false) { // Do not observe shell, if there is no shell instance; e.g., in some unit // tests. if (ash::Shell::HasInstance()) @@ -61,7 +58,7 @@ Preferences::Preferences() Preferences::Preferences(input_method::InputMethodManager* input_method_manager) : prefs_(NULL), input_method_manager_(input_method_manager), - is_primary_user_prefs_(true) { + user_(NULL) { // Do not observe shell, if there is no shell instance; e.g., in some unit // tests. if (ash::Shell::HasInstance()) @@ -70,6 +67,7 @@ Preferences::Preferences(input_method::InputMethodManager* input_method_manager) Preferences::~Preferences() { prefs_->RemoveObserver(this); + UserManager::Get()->RemoveSessionStateObserver(this); // If shell instance is destoryed before this preferences instance, there is // no need to remove this shell observer. if (ash::Shell::HasInstance()) @@ -300,12 +298,6 @@ void Preferences::RegisterProfilePrefs( "", user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - // TODO(achuith): Remove deprecated pref in M31. crbug.com/223480. - registry->RegisterBooleanPref( - kEnableTouchpadThreeFingerSwipe, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( prefs::kTouchHudProjectionEnabled, false, @@ -325,38 +317,14 @@ void Preferences::InitUserPrefs(PrefServiceSyncable* prefs) { three_finger_click_enabled_.Init(prefs::kEnableTouchpadThreeFingerClick, prefs, callback); natural_scroll_.Init(prefs::kNaturalScroll, prefs, callback); - a11y_spoken_feedback_enabled_.Init(prefs::kSpokenFeedbackEnabled, - prefs, callback); - a11y_high_contrast_enabled_.Init(prefs::kHighContrastEnabled, - prefs, callback); - a11y_screen_magnifier_enabled_.Init(prefs::kScreenMagnifierEnabled, - prefs, callback); - a11y_screen_magnifier_type_.Init(prefs::kScreenMagnifierType, - prefs, callback); - a11y_screen_magnifier_scale_.Init(prefs::kScreenMagnifierScale, - prefs, callback); - a11y_virtual_keyboard_enabled_.Init(prefs::kVirtualKeyboardEnabled, - prefs, callback); mouse_sensitivity_.Init(prefs::kMouseSensitivity, prefs, callback); touchpad_sensitivity_.Init(prefs::kTouchpadSensitivity, prefs, callback); - use_24hour_clock_.Init(prefs::kUse24HourClock, prefs, callback); - disable_drive_.Init(prefs::kDisableDrive, prefs, callback); - disable_drive_over_cellular_.Init(prefs::kDisableDriveOverCellular, - prefs, callback); - disable_drive_hosted_files_.Init(prefs::kDisableDriveHostedFiles, + primary_mouse_button_right_.Init(prefs::kPrimaryMouseButtonRight, prefs, callback); download_default_directory_.Init(prefs::kDownloadDefaultDirectory, prefs, callback); - select_file_last_directory_.Init(prefs::kSelectFileLastDirectory, - prefs, callback); - save_file_default_directory_.Init(prefs::kSaveFileDefaultDirectory, - prefs, callback); touch_hud_projection_enabled_.Init(prefs::kTouchHudProjectionEnabled, prefs, callback); - primary_mouse_button_right_.Init(prefs::kPrimaryMouseButtonRight, - prefs, callback); - preferred_languages_.Init(prefs::kLanguagePreferredLanguages, - prefs, callback); preload_engines_.Init(prefs::kLanguagePreloadEngines, prefs, callback); enabled_extension_imes_.Init(prefs::kLanguageEnabledExtensionImes, prefs, callback); @@ -371,21 +339,22 @@ void Preferences::InitUserPrefs(PrefServiceSyncable* prefs) { prefs::kLanguageXkbAutoRepeatDelay, prefs, callback); xkb_auto_repeat_interval_pref_.Init( prefs::kLanguageXkbAutoRepeatInterval, prefs, callback); - - // TODO(achuith): Remove deprecated pref in M31. crbug.com/223480. - prefs->ClearPref(kEnableTouchpadThreeFingerSwipe); } -void Preferences::Init(PrefServiceSyncable* prefs, bool is_primary_user) { - is_primary_user_prefs_ = is_primary_user; +void Preferences::Init(PrefServiceSyncable* prefs, const User* user) { + DCHECK(user); + user_ = user; + user_is_primary_ = UserManager::Get()->GetPrimaryUser() == user_; InitUserPrefs(prefs); + UserManager::Get()->AddSessionStateObserver(this); + // This causes OnIsSyncingChanged to be called when the value of // PrefService::IsSyncing() changes. prefs->AddObserver(this); // Initialize preferences to currently saved state. - NotifyPrefChanged(NULL); + ApplyPreferences(REASON_INITIALIZATION, ""); // If a guest is logged in, initialize the prefs as if this is the first // login. @@ -394,7 +363,9 @@ void Preferences::Init(PrefServiceSyncable* prefs, bool is_primary_user) { } } -void Preferences::InitUserPrefsForTesting(PrefServiceSyncable* prefs) { +void Preferences::InitUserPrefsForTesting(PrefServiceSyncable* prefs, + const User* user) { + user_ = user; InitUserPrefs(prefs); } @@ -403,163 +374,184 @@ void Preferences::SetInputMethodListForTesting() { } void Preferences::OnPreferenceChanged(const std::string& pref_name) { - NotifyPrefChanged(&pref_name); + ApplyPreferences(REASON_PREF_CHANGED, pref_name); } -void Preferences::NotifyPrefChanged(const std::string* pref_name) { +void Preferences::ApplyPreferences(ApplyReason reason, + const std::string& pref_name) { + DCHECK(reason != REASON_PREF_CHANGED || !pref_name.empty()); + const bool user_is_owner = + UserManager::Get()->GetOwnerEmail() == user_->email(); + const bool user_is_active = user_->is_active(); + system::TouchpadSettings touchpad_settings; system::MouseSettings mouse_settings; - if (!pref_name || *pref_name == prefs::kPerformanceTracingEnabled) { + + if (user_is_primary_ && (reason == REASON_INITIALIZATION || + pref_name == prefs::kPerformanceTracingEnabled)) { const bool enabled = performance_tracing_enabled_.GetValue(); if (enabled) tracing_manager_ = TracingManager::Create(); else tracing_manager_.reset(); } - if ((!pref_name && is_primary_user_prefs_) || - (pref_name && *pref_name == prefs::kTapToClickEnabled)) { + if (reason != REASON_PREF_CHANGED || pref_name == prefs::kTapToClickEnabled) { const bool enabled = tap_to_click_enabled_.GetValue(); - touchpad_settings.SetTapToClick(enabled); - if (pref_name) + if (user_is_active) + touchpad_settings.SetTapToClick(enabled); + if (reason == REASON_PREF_CHANGED) UMA_HISTOGRAM_BOOLEAN("Touchpad.TapToClick.Changed", enabled); - else + else if (reason == REASON_INITIALIZATION) UMA_HISTOGRAM_BOOLEAN("Touchpad.TapToClick.Started", enabled); // Save owner preference in local state to use on login screen. - if (chromeos::UserManager::Get()->IsCurrentUserOwner()) { + if (user_is_owner) { PrefService* prefs = g_browser_process->local_state(); if (prefs->GetBoolean(prefs::kOwnerTapToClickEnabled) != enabled) prefs->SetBoolean(prefs::kOwnerTapToClickEnabled, enabled); } } - if ((!pref_name && is_primary_user_prefs_) || - (pref_name && *pref_name == prefs::kTapDraggingEnabled)) { + if (reason != REASON_PREF_CHANGED || + pref_name == prefs::kTapDraggingEnabled) { const bool enabled = tap_dragging_enabled_.GetValue(); - touchpad_settings.SetTapDragging(enabled); - if (pref_name) + if (user_is_active) + touchpad_settings.SetTapDragging(enabled); + if (reason == REASON_PREF_CHANGED) UMA_HISTOGRAM_BOOLEAN("Touchpad.TapDragging.Changed", enabled); - else + else if (reason == REASON_INITIALIZATION) UMA_HISTOGRAM_BOOLEAN("Touchpad.TapDragging.Started", enabled); } - if ((!pref_name && is_primary_user_prefs_) || - (pref_name && *pref_name == prefs::kEnableTouchpadThreeFingerClick)) { + if (reason != REASON_PREF_CHANGED || + pref_name == prefs::kEnableTouchpadThreeFingerClick) { const bool enabled = three_finger_click_enabled_.GetValue(); - touchpad_settings.SetThreeFingerClick(enabled); - if (pref_name) + if (user_is_active) + touchpad_settings.SetThreeFingerClick(enabled); + if (reason == REASON_PREF_CHANGED) UMA_HISTOGRAM_BOOLEAN("Touchpad.ThreeFingerClick.Changed", enabled); - else + else if (reason == REASON_INITIALIZATION) UMA_HISTOGRAM_BOOLEAN("Touchpad.ThreeFingerClick.Started", enabled); } - if ((!pref_name && is_primary_user_prefs_) || - (pref_name && *pref_name == prefs::kNaturalScroll)) { + 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; - ui::SetNaturalScroll(enabled); - if (pref_name) + if (user_is_active) + ui::SetNaturalScroll(enabled); + if (reason == REASON_PREF_CHANGED) UMA_HISTOGRAM_BOOLEAN("Touchpad.NaturalScroll.Changed", enabled); - else + else if (reason == REASON_INITIALIZATION) UMA_HISTOGRAM_BOOLEAN("Touchpad.NaturalScroll.Started", enabled); } - if ((!pref_name && is_primary_user_prefs_) || - (pref_name && *pref_name == prefs::kMouseSensitivity)) { + if (reason != REASON_PREF_CHANGED || pref_name == prefs::kMouseSensitivity) { const int sensitivity = mouse_sensitivity_.GetValue(); - mouse_settings.SetSensitivity(sensitivity); - if (pref_name) { + if (user_is_active) + mouse_settings.SetSensitivity(sensitivity); + if (reason == REASON_PREF_CHANGED) { UMA_HISTOGRAM_ENUMERATION("Mouse.PointerSensitivity.Changed", sensitivity, system::kMaxPointerSensitivity + 1); - } else { + } else if (reason == REASON_INITIALIZATION) { UMA_HISTOGRAM_ENUMERATION("Mouse.PointerSensitivity.Started", sensitivity, system::kMaxPointerSensitivity + 1); } } - if ((!pref_name && is_primary_user_prefs_) || - (pref_name && *pref_name == prefs::kTouchpadSensitivity)) { + if (reason != REASON_PREF_CHANGED || + pref_name == prefs::kTouchpadSensitivity) { const int sensitivity = touchpad_sensitivity_.GetValue(); - touchpad_settings.SetSensitivity(sensitivity); - if (pref_name) { + if (user_is_active) + touchpad_settings.SetSensitivity(sensitivity); + if (reason == REASON_PREF_CHANGED) { UMA_HISTOGRAM_ENUMERATION("Touchpad.PointerSensitivity.Changed", sensitivity, system::kMaxPointerSensitivity + 1); - } else { + } else if (reason == REASON_INITIALIZATION) { UMA_HISTOGRAM_ENUMERATION("Touchpad.PointerSensitivity.Started", sensitivity, system::kMaxPointerSensitivity + 1); } } - if ((!pref_name && is_primary_user_prefs_) || - (pref_name && *pref_name == prefs::kPrimaryMouseButtonRight)) { + if (reason != REASON_PREF_CHANGED || + pref_name == prefs::kPrimaryMouseButtonRight) { const bool right = primary_mouse_button_right_.GetValue(); - mouse_settings.SetPrimaryButtonRight(right); - if (pref_name) + if (user_is_active) + mouse_settings.SetPrimaryButtonRight(right); + if (reason == REASON_PREF_CHANGED) UMA_HISTOGRAM_BOOLEAN("Mouse.PrimaryButtonRight.Changed", right); - else + else if (reason == REASON_INITIALIZATION) UMA_HISTOGRAM_BOOLEAN("Mouse.PrimaryButtonRight.Started", right); - // Save owner preference in local state to use on login screen. - if (chromeos::UserManager::Get()->IsCurrentUserOwner()) { + if (user_is_owner) { PrefService* prefs = g_browser_process->local_state(); if (prefs->GetBoolean(prefs::kOwnerPrimaryMouseButtonRight) != right) prefs->SetBoolean(prefs::kOwnerPrimaryMouseButtonRight, right); } } - if (!pref_name || *pref_name == prefs::kDownloadDefaultDirectory) { + if (reason != REASON_PREF_CHANGED || + pref_name == prefs::kDownloadDefaultDirectory) { const bool default_download_to_drive = drive::util::IsUnderDriveMountPoint( download_default_directory_.GetValue()); - if (pref_name) + if (reason == REASON_PREF_CHANGED) UMA_HISTOGRAM_BOOLEAN( "FileBrowser.DownloadDestination.IsGoogleDrive.Changed", default_download_to_drive); - else + else if (reason == REASON_INITIALIZATION) UMA_HISTOGRAM_BOOLEAN( "FileBrowser.DownloadDestination.IsGoogleDrive.Started", default_download_to_drive); } - if ((!pref_name && is_primary_user_prefs_) || - (pref_name && *pref_name == prefs::kTouchHudProjectionEnabled)) { - const bool enabled = touch_hud_projection_enabled_.GetValue(); - ash::Shell::GetInstance()->SetTouchHudProjectionEnabled(enabled); - } - - if (!pref_name || *pref_name == prefs::kLanguagePreferredLanguages) { - // Unlike kLanguagePreloadEngines and some other input method - // preferencs, we don't need to send this to ibus-daemon. + if (reason != REASON_PREF_CHANGED || + pref_name == prefs::kTouchHudProjectionEnabled) { + if (user_is_active) { + const bool enabled = touch_hud_projection_enabled_.GetValue(); + ash::Shell::GetInstance()->SetTouchHudProjectionEnabled(enabled); + } } - if (!pref_name || *pref_name == prefs::kLanguageXkbAutoRepeatEnabled) { - const bool enabled = xkb_auto_repeat_enabled_.GetValue(); - input_method::InputMethodManager::Get()->GetXKeyboard() - ->SetAutoRepeatEnabled(enabled); + if (reason != REASON_PREF_CHANGED || + pref_name == prefs::kLanguageXkbAutoRepeatEnabled) { + if (user_is_active) { + const bool enabled = xkb_auto_repeat_enabled_.GetValue(); + input_method::InputMethodManager::Get()->GetXKeyboard() + ->SetAutoRepeatEnabled(enabled); + } } - if (!pref_name || ((*pref_name == prefs::kLanguageXkbAutoRepeatDelay) || - (*pref_name == prefs::kLanguageXkbAutoRepeatInterval))) { - UpdateAutoRepeatRate(); + if (reason != REASON_PREF_CHANGED || + pref_name == prefs::kLanguageXkbAutoRepeatDelay || + pref_name == prefs::kLanguageXkbAutoRepeatInterval) { + if (user_is_active) + UpdateAutoRepeatRate(); } - if (!pref_name) { + if (reason != REASON_PREF_CHANGED && user_is_active) { SetInputMethodList(); - } else if (*pref_name == prefs::kLanguagePreloadEngines) { + } else if (pref_name == prefs::kLanguagePreloadEngines && user_is_active) { SetLanguageConfigStringListAsCSV(language_prefs::kGeneralSectionName, language_prefs::kPreloadEnginesConfigName, preload_engines_.GetValue()); } - if (!pref_name || *pref_name == prefs::kLanguageEnabledExtensionImes) { - std::string value(enabled_extension_imes_.GetValue()); + if (reason != REASON_PREF_CHANGED || + pref_name == prefs::kLanguageEnabledExtensionImes) { + if (user_is_active) { + std::string value(enabled_extension_imes_.GetValue()); - std::vector split_values; - if (!value.empty()) - base::SplitString(value, ',', &split_values); + std::vector split_values; + if (!value.empty()) + base::SplitString(value, ',', &split_values); - input_method_manager_->SetEnabledExtensionImes(&split_values); + input_method_manager_->SetEnabledExtensionImes(&split_values); + } + } + + if (user_is_active) { + system::InputDeviceSettings::Get()->UpdateTouchpadSettings( + touchpad_settings); + system::InputDeviceSettings::Get()->UpdateMouseSettings(mouse_settings); } - system::InputDeviceSettings::Get()->UpdateTouchpadSettings(touchpad_settings); - system::InputDeviceSettings::Get()->UpdateMouseSettings(mouse_settings); } void Preferences::OnIsSyncingChanged() { @@ -621,10 +613,6 @@ void Preferences::SetInputMethodList() { } void Preferences::UpdateAutoRepeatRate() { - // Avoid setting repeat rate on desktop dev environment. - if (!base::SysInfo::IsRunningOnChromeOS()) - return; - input_method::AutoRepeatRate rate; rate.initial_delay_in_ms = xkb_auto_repeat_delay_pref_.GetValue(); rate.repeat_interval_in_ms = xkb_auto_repeat_interval_pref_.GetValue(); @@ -637,8 +625,15 @@ void Preferences::UpdateAutoRepeatRate() { void Preferences::OnTouchHudProjectionToggled(bool enabled) { if (touch_hud_projection_enabled_.GetValue() == enabled) return; - + if (!user_->is_active()) + return; touch_hud_projection_enabled_.SetValue(enabled); } +void Preferences::ActiveUserChanged(const User* active_user) { + if (active_user != user_) + return; + ApplyPreferences(REASON_ACTIVE_USER_CHANGED, ""); +} + } // namespace chromeos diff --git a/chrome/browser/chromeos/preferences.h b/chrome/browser/chromeos/preferences.h index c1efa932575b..a314c11d74a1 100644 --- a/chrome/browser/chromeos/preferences.h +++ b/chrome/browser/chromeos/preferences.h @@ -12,6 +12,7 @@ #include "base/compiler_specific.h" #include "base/prefs/pref_member.h" #include "chrome/browser/chromeos/language_preferences.h" +#include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/prefs/pref_service_syncable_observer.h" class PrefRegistrySimple; @@ -26,6 +27,8 @@ class PrefRegistrySyncable; namespace chromeos { +class User; + namespace input_method { class InputMethodManager; } @@ -35,7 +38,8 @@ class InputMethodManager; // the preferences. These include touchpad settings, etc. // When the preferences change, we change the settings to reflect the new value. class Preferences : public PrefServiceSyncableObserver, - public ash::ShellObserver { + public ash::ShellObserver, + public UserManager::UserSessionStateObserver { public: Preferences(); explicit Preferences( @@ -47,24 +51,32 @@ class Preferences : public PrefServiceSyncableObserver, static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); // This method will initialize Chrome OS settings to values in user prefs. - // |is_primary_user| is true if preferences are initialized for primary user - // in multi-profile session. - void Init(PrefServiceSyncable* prefs, bool is_primary_user); + // |user| is the user owning this preferences. + void Init(PrefServiceSyncable* prefs, const User* user); - void InitUserPrefsForTesting(PrefServiceSyncable* prefs); + void InitUserPrefsForTesting(PrefServiceSyncable* prefs, const User* user); void SetInputMethodListForTesting(); private: + enum ApplyReason { + REASON_INITIALIZATION, + REASON_ACTIVE_USER_CHANGED, + REASON_PREF_CHANGED + }; + // Initializes all member prefs. void InitUserPrefs(PrefServiceSyncable* prefs); // Callback method for preference changes. void OnPreferenceChanged(const std::string& pref_name); - // This will set the OS settings when the preference changes. - // If this method is called with NULL, it will set all OS settings to what's - // stored in the preferences. - void NotifyPrefChanged(const std::string* pref_name); + // This will set the OS settings when the preference changed or user owning + // these preferences became active. Also this method is called on + // initialization. The reason of call is stored in |reason| parameter. + // |pref_name| keeps name of changed preference in |reason| is + // |REASON_PREF_CHANGED|, otherwise it is empty. + void ApplyPreferences(ApplyReason reason, + const std::string& pref_name); // A variant of SetLanguageConfigStringList. You can pass comma-separated // values. Examples of |value|: "", "Control+space,Hiragana" @@ -90,6 +102,9 @@ class Preferences : public PrefServiceSyncableObserver, // Overriden from ash::ShellObserver. virtual void OnTouchHudProjectionToggled(bool enabled) OVERRIDE; + // Overriden form UserManager::UserSessionStateObserver. + virtual void ActiveUserChanged(const User* active_user) OVERRIDE; + PrefServiceSyncable* prefs_; input_method::InputMethodManager* input_method_manager_; @@ -101,27 +116,14 @@ class Preferences : public PrefServiceSyncableObserver, BooleanPrefMember three_finger_click_enabled_; BooleanPrefMember natural_scroll_; BooleanPrefMember vert_edge_scroll_enabled_; - BooleanPrefMember a11y_spoken_feedback_enabled_; - BooleanPrefMember a11y_high_contrast_enabled_; - BooleanPrefMember a11y_screen_magnifier_enabled_; - IntegerPrefMember a11y_screen_magnifier_type_; - DoublePrefMember a11y_screen_magnifier_scale_; - BooleanPrefMember a11y_virtual_keyboard_enabled_; IntegerPrefMember speed_factor_; IntegerPrefMember mouse_sensitivity_; IntegerPrefMember touchpad_sensitivity_; BooleanPrefMember primary_mouse_button_right_; - BooleanPrefMember use_24hour_clock_; - BooleanPrefMember disable_drive_; - BooleanPrefMember disable_drive_over_cellular_; - BooleanPrefMember disable_drive_hosted_files_; FilePathPrefMember download_default_directory_; - FilePathPrefMember select_file_last_directory_; - FilePathPrefMember save_file_default_directory_; BooleanPrefMember touch_hud_projection_enabled_; // Input method preferences. - StringPrefMember preferred_languages_; StringPrefMember preload_engines_; StringPrefMember current_input_method_; StringPrefMember previous_input_method_; @@ -131,8 +133,11 @@ class Preferences : public PrefServiceSyncableObserver, IntegerPrefMember xkb_auto_repeat_delay_pref_; IntegerPrefMember xkb_auto_repeat_interval_pref_; - // True if this preferences instance is for primary user. - bool is_primary_user_prefs_; + // User owning these preferences. + const User* user_; + + // Whether user is a primary user. + bool user_is_primary_; DISALLOW_COPY_AND_ASSIGN(Preferences); }; diff --git a/chrome/browser/chromeos/preferences_browsertest.cc b/chrome/browser/chromeos/preferences_browsertest.cc new file mode 100644 index 000000000000..ed6c7c07f0f1 --- /dev/null +++ b/chrome/browser/chromeos/preferences_browsertest.cc @@ -0,0 +1,202 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "ash/shell.h" +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "base/prefs/pref_service.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/input_method/input_method_manager_impl.h" +#include "chrome/browser/chromeos/login/login_manager_test.h" +#include "chrome/browser/chromeos/login/startup_utils.h" +#include "chrome/browser/chromeos/login/user_adding_screen.h" +#include "chrome/browser/chromeos/preferences.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" +#include "chrome/browser/chromeos/system/fake_input_device_settings.h" +#include "chrome/browser/feedback/tracing_manager.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" +#include "chromeos/chromeos_switches.h" +#include "chromeos/ime/fake_xkeyboard.h" +#include "content/public/test/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/event_utils.h" + +namespace chromeos { + +namespace { + +const char* kTestUsers[] = {"test-user1@gmail.com", "test-user2@gmail.com"}; + +} // namespace + +class PreferencesTest : public LoginManagerTest { + public: + PreferencesTest() + : LoginManagerTest(true), + input_settings_(NULL), + xkeyboard_(NULL) {} + + virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { + LoginManagerTest::SetUpCommandLine(command_line); + command_line->AppendSwitch(::switches::kMultiProfiles); + command_line->AppendSwitch(switches::kForceMultiProfileInTests); + command_line->AppendSwitch(switches::kStubCrosSettings); + } + + virtual void SetUpOnMainThread() OVERRIDE { + LoginManagerTest::SetUpOnMainThread(); + input_settings_ = new system::FakeInputDeviceSettings(); + system::InputDeviceSettings::SetSettingsForTesting(input_settings_); + xkeyboard_ = new input_method::FakeXKeyboard(); + static_cast( + input_method::InputMethodManager::Get()) + ->SetXKeyboardForTesting(xkeyboard_); + CrosSettings::Get()->SetString(kDeviceOwner, kTestUsers[0]); + } + + // Sets set of preferences in given |prefs|. Value of prefernece depends of + // |variant| value. For opposite |variant| values all preferences recieve + // different values. + void SetPrefs(PrefService* prefs, bool variant) { + prefs->SetBoolean(prefs::kTapToClickEnabled, variant); + prefs->SetBoolean(prefs::kPrimaryMouseButtonRight, !variant); + prefs->SetBoolean(prefs::kTapDraggingEnabled, variant); + prefs->SetBoolean(prefs::kEnableTouchpadThreeFingerClick, !variant); + prefs->SetBoolean(prefs::kNaturalScroll, variant); + prefs->SetInteger(prefs::kMouseSensitivity, !variant); + prefs->SetInteger(prefs::kTouchpadSensitivity, variant); + prefs->SetBoolean(prefs::kTouchHudProjectionEnabled, !variant); + prefs->SetBoolean(prefs::kLanguageXkbAutoRepeatEnabled, variant); + prefs->SetInteger(prefs::kLanguageXkbAutoRepeatDelay, variant ? 100 : 500); + prefs->SetInteger(prefs::kLanguageXkbAutoRepeatInterval, variant ? 1 : 4); + prefs->SetString(prefs::kLanguagePreloadEngines, + variant ? "xkb:us::eng,xkb:us:dvorak:eng" + : "xkb:us::eng,xkb:ru::rus"); + } + + void CheckSettingsCorrespondToPrefs(PrefService* prefs) { + EXPECT_EQ(prefs->GetBoolean(prefs::kTapToClickEnabled), + input_settings_->current_touchpad_settings().GetTapToClick()); + EXPECT_EQ(prefs->GetBoolean(prefs::kPrimaryMouseButtonRight), + input_settings_->current_mouse_settings() + .GetPrimaryButtonRight()); + EXPECT_EQ(prefs->GetBoolean(prefs::kTapDraggingEnabled), + input_settings_->current_touchpad_settings().GetTapDragging()); + EXPECT_EQ(prefs->GetBoolean(prefs::kEnableTouchpadThreeFingerClick), + input_settings_->current_touchpad_settings() + .GetThreeFingerClick()); + EXPECT_EQ(prefs->GetBoolean(prefs::kNaturalScroll), + ui::IsNaturalScrollEnabled()); + EXPECT_EQ(prefs->GetInteger(prefs::kMouseSensitivity), + input_settings_->current_mouse_settings().GetSensitivity()); + EXPECT_EQ(prefs->GetInteger(prefs::kTouchpadSensitivity), + input_settings_->current_touchpad_settings().GetSensitivity()); + EXPECT_EQ(prefs->GetBoolean(prefs::kTouchHudProjectionEnabled), + ash::Shell::GetInstance()->is_touch_hud_projection_enabled()); + EXPECT_EQ(prefs->GetBoolean(prefs::kLanguageXkbAutoRepeatEnabled), + xkeyboard_->auto_repeat_is_enabled_); + input_method::AutoRepeatRate rate = xkeyboard_->last_auto_repeat_rate_; + EXPECT_EQ(prefs->GetInteger(prefs::kLanguageXkbAutoRepeatDelay), + (int)rate.initial_delay_in_ms); + EXPECT_EQ(prefs->GetInteger(prefs::kLanguageXkbAutoRepeatInterval), + (int)rate.repeat_interval_in_ms); + EXPECT_EQ( + prefs->GetString(prefs::kLanguageCurrentInputMethod), + input_method::InputMethodManager::Get()->GetCurrentInputMethod().id()); + } + + void CheckLocalStateCorrespondsToPrefs(PrefService* prefs) { + PrefService* local_state = g_browser_process->local_state(); + EXPECT_EQ(local_state->GetBoolean(prefs::kOwnerTapToClickEnabled), + prefs->GetBoolean(prefs::kTapToClickEnabled)); + EXPECT_EQ(local_state->GetBoolean(prefs::kOwnerPrimaryMouseButtonRight), + prefs->GetBoolean(prefs::kPrimaryMouseButtonRight)); + } + + private: + system::FakeInputDeviceSettings* input_settings_; + input_method::FakeXKeyboard* xkeyboard_; + + DISALLOW_COPY_AND_ASSIGN(PreferencesTest); +}; + +IN_PROC_BROWSER_TEST_F(PreferencesTest, PRE_MultiProfiles) { + RegisterUser(kTestUsers[0]); + RegisterUser(kTestUsers[1]); + chromeos::StartupUtils::MarkOobeCompleted(); +} + +IN_PROC_BROWSER_TEST_F(PreferencesTest, MultiProfiles) { + UserManager* user_manager = UserManager::Get(); + + // Add first user and init its preferences. Check that corresponding + // settings has been changed. + LoginUser(kTestUsers[0]); + const User* user1 = user_manager->FindUser(kTestUsers[0]); + PrefService* prefs1 = user_manager->GetProfileByUser(user1)->GetPrefs(); + SetPrefs(prefs1, false); + content::RunAllPendingInMessageLoop(); + CheckSettingsCorrespondToPrefs(prefs1); + + // Add second user and init its prefs with different values. + UserAddingScreen::Get()->Start(); + content::RunAllPendingInMessageLoop(); + AddUser(kTestUsers[1]); + EXPECT_TRUE(user1->is_active()); + const User* user2 = user_manager->FindUser(kTestUsers[1]); + PrefService* prefs2 = user_manager->GetProfileByUser(user2)->GetPrefs(); + SetPrefs(prefs2, true); + + // First user is still active, so settings was not changed. + EXPECT_TRUE(user1->is_active()); + CheckSettingsCorrespondToPrefs(prefs1); + + // Switch user and check that settings was changed accordingly. + user_manager->SwitchActiveUser(kTestUsers[1]); + EXPECT_TRUE(user2->is_active()); + CheckSettingsCorrespondToPrefs(prefs2); + + // Check that changing prefs of the active user doesn't affect prefs of the + // inactive user. + scoped_ptr prefs_backup = + prefs1->GetPreferenceValues(); + SetPrefs(prefs2, false); + CheckSettingsCorrespondToPrefs(prefs2); + EXPECT_TRUE(prefs_backup->Equals(prefs1->GetPreferenceValues().get())); + SetPrefs(prefs2, true); + CheckSettingsCorrespondToPrefs(prefs2); + EXPECT_TRUE(prefs_backup->Equals(prefs1->GetPreferenceValues().get())); + + // Check that changing prefs of the inactive user doesn't affect prefs of the + // active user. + prefs_backup = prefs2->GetPreferenceValues(); + SetPrefs(prefs1, true); + CheckSettingsCorrespondToPrefs(prefs2); + EXPECT_TRUE(prefs_backup->Equals(prefs2->GetPreferenceValues().get())); + SetPrefs(prefs1, false); + CheckSettingsCorrespondToPrefs(prefs2); + EXPECT_TRUE(prefs_backup->Equals(prefs2->GetPreferenceValues().get())); + + // Check that changing non-owner prefs doesn't change corresponding local + // state prefs and vice versa. + EXPECT_EQ(user_manager->GetOwnerEmail(), kTestUsers[0]); + CheckLocalStateCorrespondsToPrefs(prefs1); + prefs2->SetBoolean(prefs::kTapToClickEnabled, + !prefs1->GetBoolean(prefs::kTapToClickEnabled)); + CheckLocalStateCorrespondsToPrefs(prefs1); + prefs1->SetBoolean(prefs::kTapToClickEnabled, + !prefs1->GetBoolean(prefs::kTapToClickEnabled)); + CheckLocalStateCorrespondsToPrefs(prefs1); + + // Switch user back. + user_manager->SwitchActiveUser(kTestUsers[0]); + CheckSettingsCorrespondToPrefs(prefs1); + CheckLocalStateCorrespondsToPrefs(prefs1); +} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/preferences_unittest.cc b/chrome/browser/chromeos/preferences_unittest.cc index 979e15494719..ab02c749351a 100644 --- a/chrome/browser/chromeos/preferences_unittest.cc +++ b/chrome/browser/chromeos/preferences_unittest.cc @@ -6,6 +6,8 @@ #include "base/prefs/pref_member.h" #include "chrome/browser/chromeos/input_method/mock_input_method_manager.h" +#include "chrome/browser/chromeos/login/fake_user_manager.h" +#include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_pref_service_syncable.h" @@ -45,6 +47,12 @@ class MyMockInputMethodManager : public input_method::MockInputMethodManager { } // anonymous namespace TEST(PreferencesTest, TestUpdatePrefOnBrowserScreenDetails) { + chromeos::FakeUserManager* user_manager = new chromeos::FakeUserManager(); + chromeos::ScopedUserManagerEnabler user_manager_enabler(user_manager); + const char test_user_email[] = "test_user@example.com"; + const User* test_user = user_manager->AddUser(test_user_email); + user_manager->LoginUser(test_user_email); + TestingPrefServiceSyncable prefs; Preferences::RegisterProfilePrefs(prefs.registry()); DownloadPrefs::RegisterProfilePrefs(prefs.registry()); @@ -64,7 +72,7 @@ TEST(PreferencesTest, TestUpdatePrefOnBrowserScreenDetails) { MyMockInputMethodManager mock_manager(&previous, ¤t); Preferences testee(&mock_manager); - testee.InitUserPrefsForTesting(&prefs); + testee.InitUserPrefsForTesting(&prefs, test_user); testee.SetInputMethodListForTesting(); // Confirm they're unchanged. diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc index 87aa06988c32..20c643285a16 100644 --- a/chrome/browser/profiles/off_the_record_profile_impl.cc +++ b/chrome/browser/profiles/off_the_record_profile_impl.cc @@ -501,7 +501,7 @@ class GuestSessionProfile : public OffTheRecordProfileImpl { virtual void InitChromeOSPreferences() OVERRIDE { chromeos_preferences_.reset(new chromeos::Preferences()); chromeos_preferences_->Init(static_cast(GetPrefs()), - true /* is_primary_profile */); + chromeos::UserManager::Get()->GetActiveUser()); } private: diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index a7ab71bdabba..52acc0c0809f 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc @@ -1156,10 +1156,9 @@ void ProfileImpl::OnLogin() { void ProfileImpl::InitChromeOSPreferences() { chromeos_preferences_.reset(new chromeos::Preferences()); - bool is_primary_user = chromeos::UserManager::Get()->GetPrimaryUser() == - chromeos::UserManager::Get()->GetUserByProfile(this); - chromeos_preferences_->Init(PrefServiceSyncable::FromProfile(this), - is_primary_user); + chromeos_preferences_->Init( + PrefServiceSyncable::FromProfile(this), + chromeos::UserManager::Get()->GetUserByProfile(this)); } #endif // defined(OS_CHROMEOS) diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 78d4ea32a30b..6c2ea9ac8b3e 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1106,6 +1106,7 @@ 'browser/chromeos/policy/user_cloud_external_data_manager_browsertest.cc', 'browser/chromeos/policy/variations_service_policy_browsertest.cc', 'browser/chromeos/power/peripheral_battery_observer_browsertest.cc', + 'browser/chromeos/preferences_browsertest.cc', 'browser/chromeos/profiles/profile_helper_browsertest.cc', 'browser/chromeos/system/tray_accessibility_browsertest.cc', 'browser/chromeos/ui/idle_logout_dialog_view_browsertest.cc', -- 2.11.4.GIT