Commit 3daab832 authored by Dominic Mazzoni's avatar Dominic Mazzoni Committed by Commit Bot

Sync Switch Access preferences to Signin profile

Enabling Switch Access can only be done from a user profile.
However, once it's enabled, it needs to be possible for a switch
access user to reboot or sign out and still control their device.

So, every time a switch access pref is changed in a signed-in
user profile, sync that same pref value to the signin profile.
That way the next time the user is on the signin screen, switch
access continues to work with their same settings.

If someone else wants to use the machine and doesn't want
switch access enabled, they can turn it off in the
quick settings.

Bug: 1108808
Change-Id: I136abcddc59f76d7b6ba9c55e2b4cb0607c4ab36
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2361662
Commit-Queue: Dominic Mazzoni <dmazzoni@chromium.org>
Reviewed-by: default avatarAnastasia Helfinstein <anastasi@google.com>
Cr-Commit-Position: refs/heads/master@{#799357}
parent 4f081fd8
......@@ -180,6 +180,22 @@ constexpr const char* const kCopiedOnSigninAccessibilityPrefs[]{
prefs::kDisplayRotationAcceleratorDialogHasBeenAccepted2,
};
// List of switch access accessibility prefs that are to be copied (if changed
// by the user) from the current user to the signin screen profile. That way
// if a switch access user signs out, their switch continues to function.
constexpr const char* const kSwitchAccessPrefsCopiedToSignin[]{
prefs::kAccessibilitySwitchAccessAutoScanEnabled,
prefs::kAccessibilitySwitchAccessAutoScanKeyboardSpeedMs,
prefs::kAccessibilitySwitchAccessAutoScanSpeedMs,
prefs::kAccessibilitySwitchAccessEnabled,
prefs::kAccessibilitySwitchAccessNextKeyCodes,
prefs::kAccessibilitySwitchAccessNextSetting,
prefs::kAccessibilitySwitchAccessPreviousKeyCodes,
prefs::kAccessibilitySwitchAccessPreviousSetting,
prefs::kAccessibilitySwitchAccessSelectKeyCodes,
prefs::kAccessibilitySwitchAccessSelectSetting,
};
// Helper function that is used to verify the validity of kFeatures and
// kFeatureDialogs.
bool VerifyFeaturesData() {
......@@ -1521,6 +1537,21 @@ void AccessibilityControllerImpl::ObservePrefs(PrefService* prefs) {
base::BindRepeating(&AccessibilityControllerImpl::
UpdateSwitchAccessAutoScanKeyboardSpeedFromPref,
base::Unretained(this)));
pref_change_registrar_->Add(
prefs::kAccessibilitySwitchAccessNextSetting,
base::BindRepeating(
&AccessibilityControllerImpl::SyncSwitchAccessPrefsToSignInProfile,
base::Unretained(this)));
pref_change_registrar_->Add(
prefs::kAccessibilitySwitchAccessPreviousSetting,
base::BindRepeating(
&AccessibilityControllerImpl::SyncSwitchAccessPrefsToSignInProfile,
base::Unretained(this)));
pref_change_registrar_->Add(
prefs::kAccessibilitySwitchAccessSelectSetting,
base::BindRepeating(
&AccessibilityControllerImpl::SyncSwitchAccessPrefsToSignInProfile,
base::Unretained(this)));
pref_change_registrar_->Add(
prefs::kAccessibilityTabletModeShelfNavigationButtonsEnabled,
base::BindRepeating(&AccessibilityControllerImpl::
......@@ -1751,6 +1782,8 @@ void AccessibilityControllerImpl::UpdateSwitchAccessKeyCodesFromPref(
SwitchAccessCommand command) {
DCHECK(active_user_prefs_);
SyncSwitchAccessPrefsToSignInProfile();
std::string pref_key = PrefKeyForSwitchAccessCommand(command);
const base::ListValue* key_codes_pref = active_user_prefs_->GetList(pref_key);
std::set<int> key_codes;
......@@ -1781,6 +1814,7 @@ void AccessibilityControllerImpl::UpdateSwitchAccessAutoScanEnabledFromPref() {
prefs::kAccessibilitySwitchAccessAutoScanEnabled);
base::UmaHistogramBoolean("Accessibility.CrosSwitchAccess.AutoScan", enabled);
SyncSwitchAccessPrefsToSignInProfile();
}
void AccessibilityControllerImpl::UpdateSwitchAccessAutoScanSpeedFromPref() {
......@@ -1791,6 +1825,7 @@ void AccessibilityControllerImpl::UpdateSwitchAccessAutoScanSpeedFromPref() {
base::UmaHistogramCustomCounts(
"Accessibility.CrosSwitchAccess.AutoScan.SpeedMs", speed_ms, 1 /* min */,
10000 /* max */, 100 /* buckets */);
SyncSwitchAccessPrefsToSignInProfile();
}
void AccessibilityControllerImpl::
......@@ -1802,6 +1837,7 @@ void AccessibilityControllerImpl::
base::UmaHistogramCustomCounts(
"Accessibility.CrosSwitchAccess.AutoScan.KeyboardSpeedMs", speed_ms,
1 /* min */, 10000 /* max */, 100 /* buckets */);
SyncSwitchAccessPrefsToSignInProfile();
}
void AccessibilityControllerImpl::SwitchAccessDisableDialogClosed(
......@@ -1867,6 +1903,28 @@ void AccessibilityControllerImpl::DeactivateSwitchAccess() {
switch_access_event_handler_.reset();
}
void AccessibilityControllerImpl::SyncSwitchAccessPrefsToSignInProfile() {
if (!active_user_prefs_ || IsSigninPrefService(active_user_prefs_))
return;
PrefService* signin_prefs =
Shell::Get()->session_controller()->GetSigninScreenPrefService();
DCHECK(signin_prefs);
for (const auto* pref_path : kSwitchAccessPrefsCopiedToSignin) {
const PrefService::Preference* pref =
active_user_prefs_->FindPreference(pref_path);
// Ignore if the pref has not been set by the user.
if (!pref || !pref->IsUserControlled())
continue;
// Copy the pref value to the signin profile.
const base::Value* value = pref->GetValue();
signin_prefs->Set(pref_path, *value);
}
}
void AccessibilityControllerImpl::UpdateShortcutsEnabledFromPref() {
DCHECK(active_user_prefs_);
const bool enabled =
......@@ -2011,6 +2069,7 @@ void AccessibilityControllerImpl::UpdateFeatureFromPref(FeatureType feature) {
} else {
ActivateSwitchAccess();
}
SyncSwitchAccessPrefsToSignInProfile();
break;
case FeatureType::kVirtualKeyboard:
keyboard::SetAccessibilityKeyboardEnabled(enabled);
......
......@@ -458,6 +458,7 @@ class ASH_EXPORT AccessibilityControllerImpl : public AccessibilityController,
void MaybeCreateSwitchAccessEventHandler();
void ActivateSwitchAccess();
void DeactivateSwitchAccess();
void SyncSwitchAccessPrefsToSignInProfile();
// Client interface in chrome browser.
AccessibilityControllerClient* client_ = nullptr;
......
......@@ -1143,4 +1143,71 @@ TEST_P(AccessibilityControllerSigninTest, EnableOnLoginScreenAndLogin) {
}
}
TEST_P(AccessibilityControllerSigninTest, SwitchAccessPrefsSyncToSignIn) {
AccessibilityControllerImpl* accessibility =
Shell::Get()->accessibility_controller();
SessionControllerImpl* session = Shell::Get()->session_controller();
EXPECT_EQ(session_manager::SessionState::LOGIN_PRIMARY,
session->GetSessionState());
EXPECT_FALSE(accessibility->switch_access_enabled());
using prefs::kAccessibilitySwitchAccessAutoScanEnabled;
using prefs::kAccessibilitySwitchAccessAutoScanKeyboardSpeedMs;
using prefs::kAccessibilitySwitchAccessAutoScanSpeedMs;
using prefs::kAccessibilitySwitchAccessEnabled;
using prefs::kAccessibilitySwitchAccessNextSetting;
using prefs::kAccessibilitySwitchAccessPreviousSetting;
using prefs::kAccessibilitySwitchAccessSelectSetting;
PrefService* signin_prefs = session->GetSigninScreenPrefService();
EXPECT_FALSE(signin_prefs->GetBoolean(kAccessibilitySwitchAccessEnabled));
EXPECT_FALSE(
signin_prefs->GetBoolean(kAccessibilitySwitchAccessAutoScanEnabled));
SimulateLogin();
PrefService* user_prefs = session->GetLastActiveUserPrefService();
EXPECT_NE(signin_prefs, user_prefs);
EXPECT_FALSE(user_prefs->GetBoolean(kAccessibilitySwitchAccessEnabled));
EXPECT_FALSE(
user_prefs->GetBoolean(kAccessibilitySwitchAccessAutoScanEnabled));
// Enabling switch access in a user profile should enable it for the
// signin profile.
accessibility->SetSwitchAccessEnabled(true);
EXPECT_TRUE(user_prefs->GetBoolean(kAccessibilitySwitchAccessEnabled));
EXPECT_TRUE(signin_prefs->GetBoolean(kAccessibilitySwitchAccessEnabled));
// Changing a switch access option in a user profile should sync that
// option to the signin profile.
user_prefs->Set(kAccessibilitySwitchAccessAutoScanEnabled, base::Value(true));
EXPECT_TRUE(
signin_prefs->GetBoolean(kAccessibilitySwitchAccessAutoScanEnabled));
user_prefs->Set(kAccessibilitySwitchAccessAutoScanKeyboardSpeedMs,
base::Value(123));
EXPECT_EQ(123, signin_prefs->GetInteger(
kAccessibilitySwitchAccessAutoScanKeyboardSpeedMs));
user_prefs->Set(kAccessibilitySwitchAccessAutoScanSpeedMs, base::Value(234));
EXPECT_EQ(
234, signin_prefs->GetInteger(kAccessibilitySwitchAccessAutoScanSpeedMs));
user_prefs->Set(kAccessibilitySwitchAccessNextSetting, base::Value(3));
EXPECT_EQ(3, signin_prefs->GetInteger(kAccessibilitySwitchAccessNextSetting));
user_prefs->Set(kAccessibilitySwitchAccessPreviousSetting, base::Value(4));
EXPECT_EQ(
4, signin_prefs->GetInteger(kAccessibilitySwitchAccessPreviousSetting));
user_prefs->Set(kAccessibilitySwitchAccessSelectSetting, base::Value(5));
EXPECT_EQ(5,
signin_prefs->GetInteger(kAccessibilitySwitchAccessSelectSetting));
// The reverse is not true; turning off switch access in the signin profile
// has no effect on the user profile.
signin_prefs->Set(kAccessibilitySwitchAccessEnabled, base::Value(false));
EXPECT_TRUE(user_prefs->GetBoolean(kAccessibilitySwitchAccessEnabled));
}
} // namespace ash
......@@ -45,6 +45,7 @@
#include "ash/public/cpp/window_tree_host_lookup.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/ui/webui/settings/chromeos/constants/routes_util.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ui_base_features.h"
......@@ -81,8 +82,11 @@ AccessibilityPrivateOpenSettingsSubpageFunction::Run() {
EXTENSION_FUNCTION_VALIDATE(params);
#if defined(OS_CHROMEOS)
// TODO(chrome-a11y-core): we can't open a settings page when you're on the
// signin profile, but maybe we should notify the user and explain why?
Profile* profile = chromeos::AccessibilityManager::Get()->profile();
if (chromeos::settings::IsOSSettingsSubPage(params->subpage)) {
if (!chromeos::ProfileHelper::IsSigninProfile(profile) &&
chromeos::settings::IsOSSettingsSubPage(params->subpage)) {
chrome::SettingsWindowManager::GetInstance()->ShowOSSettings(
profile, params->subpage);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment