blob: 36c4460ee8dbcb0aae8c292cd25f3bda61f59773 [file] [log] [blame]
[email protected]1dfebfc2013-06-04 03:14:321// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
6
avi8a07d53892015-12-24 22:13:537#include <stddef.h>
8#include <stdint.h>
dcheng24002d02016-04-08 02:42:409
10#include <memory>
dcheng7c802f02015-12-31 16:09:5511#include <utility>
avi8a07d53892015-12-24 22:13:5312
James Cook9f9ff79d32017-09-01 00:39:2913#include "ash/accessibility/accessibility_controller.h"
pkotwicz04d5c892015-01-15 00:05:3614#include "ash/autoclick/autoclick_controller.h"
riajiang4b626b972016-09-13 16:12:4915#include "ash/autoclick/mus/public/interfaces/autoclick.mojom.h"
James Cookc63b9fd2017-08-18 18:48:3216#include "ash/public/cpp/ash_pref_names.h"
dmazzoniff86e3472016-06-03 19:52:3217#include "ash/root_window_controller.h"
James Cook840177e2017-05-25 02:20:0118#include "ash/shelf/shelf.h"
James Cookb0bf8e82017-04-09 17:01:4419#include "ash/shelf/shelf_layout_manager.h"
pkotwicz04d5c892015-01-15 00:05:3620#include "ash/shell.h"
pkotwicz04d5c892015-01-15 00:05:3621#include "ash/sticky_keys/sticky_keys_controller.h"
James Cookfc97f0a2017-08-16 20:05:3522#include "ash/system/tray/system_tray_notifier.h"
[email protected]44beb032014-06-11 06:24:3723#include "base/callback.h"
24#include "base/callback_helpers.h"
plundbladcf1d08f2015-09-28 09:18:5825#include "base/command_line.h"
avi8a07d53892015-12-24 22:13:5326#include "base/macros.h"
fdorayba121422016-12-23 19:51:4827#include "base/memory/ptr_util.h"
[email protected]1dfebfc2013-06-04 03:14:3228#include "base/memory/singleton.h"
asvitkineb56637512016-09-01 19:41:4029#include "base/metrics/histogram_macros.h"
[email protected]ab38d192013-12-13 11:38:5830#include "base/path_service.h"
mgiuca30f75882017-03-28 02:07:1931#include "base/strings/string_piece.h"
[email protected]2e5e0b12014-05-07 13:30:2032#include "base/strings/string_split.h"
33#include "base/strings/string_util.h"
[email protected]0b5a0d2b2013-10-30 03:43:4034#include "base/time/time.h"
[email protected]0aae2fe2013-07-05 07:04:4235#include "base/values.h"
[email protected]1dfebfc2013-06-04 03:14:3236#include "chrome/browser/accessibility/accessibility_extension_api.h"
37#include "chrome/browser/browser_process.h"
[email protected]fdf40f3e2013-07-11 23:55:4638#include "chrome/browser/chrome_notification_types.h"
dmazzoni337c5af2016-09-13 23:08:5739#include "chrome/browser/chromeos/accessibility/accessibility_extension_loader.h"
dmazzonib93107c2016-03-22 21:51:1840#include "chrome/browser/chromeos/accessibility/accessibility_highlight_manager.h"
pkotwicz04d5c892015-01-15 00:05:3641#include "chrome/browser/chromeos/accessibility/magnification_manager.h"
dmazzoni735c79df2016-11-28 22:39:4242#include "chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h"
elichtenbergc4b4bf462017-02-28 20:48:1043#include "chrome/browser/chromeos/accessibility/switch_access_event_handler.h"
dmazzoni16d2dec2016-12-19 23:27:5744#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
James Cook696fb106a2017-08-17 21:50:4445#include "chrome/browser/chromeos/ash_config.h"
dmazzoni16d2dec2016-12-19 23:27:5746#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
[email protected]e6f20642013-06-11 17:05:4647#include "chrome/browser/chromeos/profiles/profile_helper.h"
minchd9d542482017-04-07 19:29:5648#include "chrome/browser/chromeos/system/input_device_settings.h"
dmazzonifb33d592014-10-30 19:26:5449#include "chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h"
plundbladcf1d08f2015-09-28 09:18:5850#include "chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h"
[email protected]1dfebfc2013-06-04 03:14:3251#include "chrome/browser/extensions/extension_service.h"
gogeralddde4ee02015-08-26 18:58:4952#include "chrome/browser/prefs/incognito_mode_prefs.h"
[email protected]1dfebfc2013-06-04 03:14:3253#include "chrome/browser/profiles/profile.h"
54#include "chrome/browser/profiles/profile_manager.h"
[email protected]ab38d192013-12-13 11:38:5855#include "chrome/common/chrome_paths.h"
[email protected]9848bf6c2014-05-09 12:34:0056#include "chrome/common/extensions/api/accessibility_private.h"
[email protected]dccba4f82014-05-29 00:52:5657#include "chrome/common/extensions/extension_constants.h"
[email protected]1dfebfc2013-06-04 03:14:3258#include "chrome/common/pref_names.h"
[email protected]b58d2f82014-08-09 05:36:1459#include "chrome/grit/browser_resources.h"
warx533c8f62016-04-12 01:19:4360#include "chromeos/audio/audio_a11y_controller.h"
[email protected]ce89d9392013-12-11 21:05:2061#include "chromeos/audio/chromeos_sounds.h"
Dominic Mazzonic85a5c92017-08-31 18:53:3062#include "chromeos/chromeos_switches.h"
dtseng3a17f212017-03-25 08:58:5263#include "chromeos/dbus/dbus_thread_manager.h"
64#include "chromeos/dbus/power_manager_client.h"
brettwb1fc1b82016-02-02 00:19:0865#include "components/prefs/pref_member.h"
66#include "components/prefs/pref_service.h"
tbarziccd5ad222017-03-24 04:46:3167#include "components/session_manager/core/session_manager.h"
[email protected]1dfebfc2013-06-04 03:14:3268#include "content/public/browser/browser_accessibility_state.h"
[email protected]8c79e3f2013-10-30 01:05:1469#include "content/public/browser/browser_thread.h"
[email protected]9cf54f362013-07-01 07:28:1270#include "content/public/browser/notification_details.h"
[email protected]1dfebfc2013-06-04 03:14:3271#include "content/public/browser/notification_service.h"
[email protected]9cf54f362013-07-01 07:28:1272#include "content/public/browser/notification_source.h"
[email protected]1dfebfc2013-06-04 03:14:3273#include "content/public/browser/web_ui.h"
plundbladcf1d08f2015-09-28 09:18:5874#include "content/public/common/content_switches.h"
bend32292b2016-10-07 00:21:5875#include "content/public/common/service_manager_connection.h"
juncaicf523332015-06-04 00:14:0476#include "extensions/browser/event_router.h"
reillyga3acbc12014-11-11 23:17:1277#include "extensions/browser/extension_registry.h"
[email protected]59b0e602014-01-30 00:41:2478#include "extensions/browser/extension_system.h"
[email protected]e4452d32013-11-15 23:07:4179#include "extensions/common/extension.h"
[email protected]fb820c02014-03-13 15:07:0880#include "extensions/common/extension_messages.h"
[email protected]1dfebfc2013-06-04 03:14:3281#include "extensions/common/extension_resource.h"
hanxi79f7a572015-03-09 20:46:5982#include "extensions/common/host_id.h"
riajiang4b626b972016-09-13 16:12:4983#include "mash/public/interfaces/launchable.mojom.h"
[email protected]12b0a842013-12-04 20:48:1384#include "media/audio/sounds/sounds_manager.h"
dtsengd50debe32016-12-29 06:23:3785#include "media/base/media_switches.h"
rockot734fb662016-10-15 16:41:3086#include "services/service_manager/public/cpp/connector.h"
jamescook2d60f032017-06-01 00:55:2187#include "ui/base/ime/chromeos/extension_ime_util.h"
shuchen179b1f42014-11-27 17:24:4088#include "ui/base/ime/chromeos/input_method_manager.h"
[email protected]1dfebfc2013-06-04 03:14:3289#include "ui/base/resource/resource_bundle.h"
[email protected]e1b299b2014-01-29 23:53:4190#include "ui/keyboard/keyboard_controller.h"
91#include "ui/keyboard/keyboard_util.h"
Scott Violet66193f72017-06-26 22:24:1892#include "ui/views/widget/widget.h"
jamescook9eb0f912017-02-03 19:13:3993#include "ui/views/widget/widget_observer.h"
[email protected]1dfebfc2013-06-04 03:14:3294
[email protected]8c79e3f2013-10-30 01:05:1495using content::BrowserThread;
[email protected]8c79e3f2013-10-30 01:05:1496using extensions::api::braille_display_private::BrailleController;
97using extensions::api::braille_display_private::DisplayState;
[email protected]2e5e0b12014-05-07 13:30:2098using extensions::api::braille_display_private::KeyEvent;
plundbladcf1d08f2015-09-28 09:18:5899using extensions::api::braille_display_private::StubBrailleController;
[email protected]1dfebfc2013-06-04 03:14:32100
101namespace chromeos {
102
103namespace {
104
sadrulcdc2bb42016-07-13 19:44:51105// When this flag is set, system sounds will not be played.
106const char kAshDisableSystemSounds[] = "ash-disable-system-sounds";
107
[email protected]1dfebfc2013-06-04 03:14:32108static chromeos::AccessibilityManager* g_accessibility_manager = NULL;
109
[email protected]8c79e3f2013-10-30 01:05:14110static BrailleController* g_braille_controller_for_test = NULL;
111
112BrailleController* GetBrailleController() {
plundbladcf1d08f2015-09-28 09:18:58113 if (g_braille_controller_for_test)
114 return g_braille_controller_for_test;
115 // Don't use the real braille controller for tests to avoid automatically
116 // starting ChromeVox which confuses some tests.
117 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
Dominic Mazzonic85a5c92017-08-31 18:53:30118 if (command_line->HasSwitch(::switches::kTestType))
plundbladcf1d08f2015-09-28 09:18:58119 return StubBrailleController::GetInstance();
120 return BrailleController::GetInstance();
[email protected]8c79e3f2013-10-30 01:05:14121}
122
[email protected]1dfebfc2013-06-04 03:14:32123} // namespace
124
dmazzoni94a4f882015-11-13 05:46:52125class ChromeVoxPanelWidgetObserver : public views::WidgetObserver {
126 public:
127 ChromeVoxPanelWidgetObserver(views::Widget* widget,
128 AccessibilityManager* manager)
129 : widget_(widget), manager_(manager) {
130 widget_->AddObserver(this);
131 }
132
133 void OnWidgetClosing(views::Widget* widget) override {
134 CHECK_EQ(widget_, widget);
135 widget->RemoveObserver(this);
136 manager_->OnChromeVoxPanelClosing();
137 }
138
139 void OnWidgetDestroying(views::Widget* widget) override {
140 CHECK_EQ(widget_, widget);
141 widget->RemoveObserver(this);
142 manager_->OnChromeVoxPanelDestroying();
143 }
144
145 private:
146 views::Widget* widget_;
147 AccessibilityManager* manager_;
148
149 DISALLOW_COPY_AND_ASSIGN(ChromeVoxPanelWidgetObserver);
150};
151
[email protected]1dfebfc2013-06-04 03:14:32152///////////////////////////////////////////////////////////////////////////////
153// AccessibilityStatusEventDetails
154
155AccessibilityStatusEventDetails::AccessibilityStatusEventDetails(
[email protected]d8edc9c2014-02-25 00:06:03156 AccessibilityNotificationType notification_type,
[email protected]1dfebfc2013-06-04 03:14:32157 bool enabled,
jamescooka7f8dab2016-06-21 01:44:03158 ash::AccessibilityNotificationVisibility notify)
159 : notification_type(notification_type),
160 enabled(enabled),
jamescooka7f8dab2016-06-21 01:44:03161 notify(notify) {}
[email protected]1dfebfc2013-06-04 03:14:32162
163///////////////////////////////////////////////////////////////////////////////
[email protected]0aae2fe2013-07-05 07:04:42164// AccessibilityManager::PrefHandler
165
166AccessibilityManager::PrefHandler::PrefHandler(const char* pref_path)
167 : pref_path_(pref_path) {}
168
169AccessibilityManager::PrefHandler::~PrefHandler() {}
170
171void AccessibilityManager::PrefHandler::HandleProfileChanged(
172 Profile* previous_profile, Profile* current_profile) {
173 // Returns if the current profile is null.
174 if (!current_profile)
175 return;
176
177 // If the user set a pref value on the login screen and is now starting a
178 // session with a new profile, copy the pref value to the profile.
179 if ((previous_profile &&
180 ProfileHelper::IsSigninProfile(previous_profile) &&
181 current_profile->IsNewProfile() &&
182 !ProfileHelper::IsSigninProfile(current_profile)) ||
183 // Special case for Guest mode:
184 // Guest mode launches a guest-mode browser process before session starts,
185 // so the previous profile is null.
186 (!previous_profile &&
187 current_profile->IsGuestSession())) {
188 // Returns if the pref has not been set by the user.
189 const PrefService::Preference* pref = ProfileHelper::GetSigninProfile()->
190 GetPrefs()->FindPreference(pref_path_);
191 if (!pref || !pref->IsUserControlled())
192 return;
193
194 // Copy the pref value from the signin screen.
195 const base::Value* value_on_login = pref->GetValue();
196 PrefService* user_prefs = current_profile->GetPrefs();
197 user_prefs->Set(pref_path_, *value_on_login);
198 }
199}
200
201///////////////////////////////////////////////////////////////////////////////
202//
[email protected]1dfebfc2013-06-04 03:14:32203// AccessibilityManager
204
205// static
206void AccessibilityManager::Initialize() {
207 CHECK(g_accessibility_manager == NULL);
208 g_accessibility_manager = new AccessibilityManager();
209}
210
211// static
212void AccessibilityManager::Shutdown() {
213 CHECK(g_accessibility_manager);
214 delete g_accessibility_manager;
215 g_accessibility_manager = NULL;
216}
217
218// static
219AccessibilityManager* AccessibilityManager::Get() {
220 return g_accessibility_manager;
221}
222
[email protected]d80f19302013-06-07 13:12:14223AccessibilityManager::AccessibilityManager()
224 : profile_(NULL),
James Cookc63b9fd2017-08-18 18:48:32225 large_cursor_pref_handler_(ash::prefs::kAccessibilityLargeCursorEnabled),
226 sticky_keys_pref_handler_(ash::prefs::kAccessibilityStickyKeysEnabled),
227 spoken_feedback_pref_handler_(
228 ash::prefs::kAccessibilitySpokenFeedbackEnabled),
229 high_contrast_pref_handler_(
230 ash::prefs::kAccessibilityHighContrastEnabled),
231 autoclick_pref_handler_(ash::prefs::kAccessibilityAutoclickEnabled),
232 autoclick_delay_pref_handler_(ash::prefs::kAccessibilityAutoclickDelayMs),
[email protected]ced247a2014-06-13 19:14:19233 virtual_keyboard_pref_handler_(
James Cookc63b9fd2017-08-18 18:48:32234 ash::prefs::kAccessibilityVirtualKeyboardEnabled),
235 mono_audio_pref_handler_(ash::prefs::kAccessibilityMonoAudioEnabled),
236 caret_highlight_pref_handler_(
237 ash::prefs::kAccessibilityCaretHighlightEnabled),
dmazzoni756089a22016-03-15 23:55:16238 cursor_highlight_pref_handler_(
James Cookc63b9fd2017-08-18 18:48:32239 ash::prefs::kAccessibilityCursorHighlightEnabled),
240 focus_highlight_pref_handler_(
241 ash::prefs::kAccessibilityFocusHighlightEnabled),
minchd9d542482017-04-07 19:29:56242 tap_dragging_pref_handler_(prefs::kTapDraggingEnabled),
James Cookc63b9fd2017-08-18 18:48:32243 select_to_speak_pref_handler_(
244 ash::prefs::kAccessibilitySelectToSpeakEnabled),
245 switch_access_pref_handler_(
246 ash::prefs::kAccessibilitySwitchAccessEnabled),
[email protected]93a534e2013-06-20 16:41:44247 sticky_keys_enabled_(false),
[email protected]d80f19302013-06-07 13:12:14248 spoken_feedback_enabled_(false),
[email protected]186ba06bc2013-11-26 18:02:19249 autoclick_enabled_(false),
sammiequon820646f2016-06-24 18:47:13250 autoclick_delay_ms_(ash::AutoclickController::GetDefaultAutoclickDelay()),
[email protected]e1b299b2014-01-29 23:53:41251 virtual_keyboard_enabled_(false),
warx533c8f62016-04-12 01:19:43252 mono_audio_enabled_(false),
dmazzoni756089a22016-03-15 23:55:16253 caret_highlight_enabled_(false),
254 cursor_highlight_enabled_(false),
255 focus_highlight_enabled_(false),
minchd9d542482017-04-07 19:29:56256 tap_dragging_enabled_(false),
dmazzoni756089a22016-03-15 23:55:16257 select_to_speak_enabled_(false),
258 switch_access_enabled_(false),
jamescooka7f8dab2016-06-21 01:44:03259 spoken_feedback_notification_(ash::A11Y_NOTIFICATION_NONE),
[email protected]a81b2c32014-03-28 06:35:01260 braille_display_connected_(false),
[email protected]2e5e0b12014-05-07 13:30:20261 scoped_braille_observer_(this),
anand.ratn04aae9ef2014-09-16 04:16:51262 braille_ime_current_(false),
dmazzoni94a4f882015-11-13 05:46:52263 chromevox_panel_(nullptr),
dtsengfb6d7cd2016-01-20 23:00:13264 extension_registry_observer_(this),
anand.ratn04aae9ef2014-09-16 04:16:51265 weak_ptr_factory_(this) {
[email protected]1dfebfc2013-06-04 03:14:32266 notification_registrar_.Add(this,
[email protected]093d9ba2013-07-23 19:26:21267 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
[email protected]e6f20642013-06-11 17:05:46268 content::NotificationService::AllSources());
269 notification_registrar_.Add(this,
Yuki Awanod59b6492017-07-28 00:52:11270 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
271 content::NotificationService::AllSources());
272 notification_registrar_.Add(this,
[email protected]1dfebfc2013-06-04 03:14:32273 chrome::NOTIFICATION_SESSION_STARTED,
274 content::NotificationService::AllSources());
275 notification_registrar_.Add(this,
[email protected]1dfebfc2013-06-04 03:14:32276 chrome::NOTIFICATION_PROFILE_DESTROYED,
277 content::NotificationService::AllSources());
[email protected]c20122572013-12-16 20:35:58278
[email protected]1488a035f2014-03-28 21:12:07279 input_method::InputMethodManager::Get()->AddObserver(this);
tbarziccd5ad222017-03-24 04:46:31280 session_manager::SessionManager::Get()->AddObserver(this);
[email protected]1488a035f2014-03-28 21:12:07281
[email protected]12b0a842013-12-04 20:48:13282 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
[email protected]ce89d9392013-12-11 21:05:20283 media::SoundsManager* manager = media::SoundsManager::Get();
284 manager->Initialize(SOUND_SHUTDOWN,
285 bundle.GetRawDataResource(IDR_SOUND_SHUTDOWN_WAV));
286 manager->Initialize(
287 SOUND_SPOKEN_FEEDBACK_ENABLED,
288 bundle.GetRawDataResource(IDR_SOUND_SPOKEN_FEEDBACK_ENABLED_WAV));
289 manager->Initialize(
290 SOUND_SPOKEN_FEEDBACK_DISABLED,
291 bundle.GetRawDataResource(IDR_SOUND_SPOKEN_FEEDBACK_DISABLED_WAV));
[email protected]07f3ea92014-08-14 05:23:38292 manager->Initialize(SOUND_PASSTHROUGH,
293 bundle.GetRawDataResource(IDR_SOUND_PASSTHROUGH_WAV));
294 manager->Initialize(SOUND_EXIT_SCREEN,
295 bundle.GetRawDataResource(IDR_SOUND_EXIT_SCREEN_WAV));
296 manager->Initialize(SOUND_ENTER_SCREEN,
297 bundle.GetRawDataResource(IDR_SOUND_ENTER_SCREEN_WAV));
dmazzoni16d2dec2016-12-19 23:27:57298 manager->Initialize(SOUND_SPOKEN_FEEDBACK_TOGGLE_COUNTDOWN_HIGH,
299 bundle.GetRawDataResource(
300 IDR_SOUND_SPOKEN_FEEDBACK_TOGGLE_COUNTDOWN_HIGH_WAV));
301 manager->Initialize(SOUND_SPOKEN_FEEDBACK_TOGGLE_COUNTDOWN_LOW,
302 bundle.GetRawDataResource(
303 IDR_SOUND_SPOKEN_FEEDBACK_TOGGLE_COUNTDOWN_LOW_WAV));
dmazzoni337c5af2016-09-13 23:08:57304
305 base::FilePath resources_path;
306 if (!PathService::Get(chrome::DIR_RESOURCES, &resources_path))
307 NOTREACHED();
308 chromevox_loader_ = base::WrapUnique(new AccessibilityExtensionLoader(
309 extension_misc::kChromeVoxExtensionId,
310 resources_path.Append(extension_misc::kChromeVoxExtensionPath),
311 base::Bind(&AccessibilityManager::PostUnloadChromeVox,
312 weak_ptr_factory_.GetWeakPtr())));
dmazzoni5288b2612016-09-16 23:05:39313 select_to_speak_loader_ = base::WrapUnique(new AccessibilityExtensionLoader(
314 extension_misc::kSelectToSpeakExtensionId,
315 resources_path.Append(extension_misc::kSelectToSpeakExtensionPath),
316 base::Closure()));
elichtenberg0746c1bd2017-02-22 07:59:15317 switch_access_loader_ = base::WrapUnique(new AccessibilityExtensionLoader(
318 extension_misc::kSwitchAccessExtensionId,
319 resources_path.Append(extension_misc::kSwitchAccessExtensionPath),
320 base::Closure()));
[email protected]1dfebfc2013-06-04 03:14:32321}
322
323AccessibilityManager::~AccessibilityManager() {
324 CHECK(this == g_accessibility_manager);
jamescooka7f8dab2016-06-21 01:44:03325 AccessibilityStatusEventDetails details(ACCESSIBILITY_MANAGER_SHUTDOWN, false,
326 ash::A11Y_NOTIFICATION_NONE);
[email protected]d8edc9c2014-02-25 00:06:03327 NotifyAccessibilityStatusChanged(details);
[email protected]1488a035f2014-03-28 21:12:07328 input_method::InputMethodManager::Get()->RemoveObserver(this);
tbarziccd5ad222017-03-24 04:46:31329 session_manager::SessionManager::Get()->RemoveObserver(this);
dmazzoni94a4f882015-11-13 05:46:52330
331 if (chromevox_panel_) {
332 chromevox_panel_->Close();
333 chromevox_panel_ = nullptr;
334 }
[email protected]1dfebfc2013-06-04 03:14:32335}
336
[email protected]c20122572013-12-16 20:35:58337bool AccessibilityManager::ShouldShowAccessibilityMenu() {
338 // If any of the loaded profiles has an accessibility feature turned on - or
339 // enforced to always show the menu - we return true to show the menu.
James Cookfc97f0a2017-08-16 20:05:35340 // NOTE: This includes the login screen profile, so if a feature is turned on
341 // at the login screen the menu will show even if the user has no features
342 // enabled inside the session. http://crbug.com/755631
[email protected]c20122572013-12-16 20:35:58343 std::vector<Profile*> profiles =
344 g_browser_process->profile_manager()->GetLoadedProfiles();
345 for (std::vector<Profile*>::iterator it = profiles.begin();
346 it != profiles.end();
347 ++it) {
James Cookc63b9fd2017-08-18 18:48:32348 PrefService* prefs = (*it)->GetPrefs();
349 if (prefs->GetBoolean(ash::prefs::kAccessibilityStickyKeysEnabled) ||
350 prefs->GetBoolean(ash::prefs::kAccessibilityLargeCursorEnabled) ||
351 prefs->GetBoolean(ash::prefs::kAccessibilitySpokenFeedbackEnabled) ||
352 prefs->GetBoolean(ash::prefs::kAccessibilityHighContrastEnabled) ||
353 prefs->GetBoolean(ash::prefs::kAccessibilityAutoclickEnabled) ||
354 prefs->GetBoolean(ash::prefs::kShouldAlwaysShowAccessibilityMenu) ||
355 prefs->GetBoolean(ash::prefs::kAccessibilityScreenMagnifierEnabled) ||
356 prefs->GetBoolean(ash::prefs::kAccessibilityVirtualKeyboardEnabled) ||
357 prefs->GetBoolean(ash::prefs::kAccessibilityMonoAudioEnabled) ||
358 prefs->GetBoolean(ash::prefs::kAccessibilityCaretHighlightEnabled) ||
359 prefs->GetBoolean(ash::prefs::kAccessibilityCursorHighlightEnabled) ||
360 prefs->GetBoolean(ash::prefs::kAccessibilityFocusHighlightEnabled) ||
361 prefs->GetBoolean(prefs::kTapDraggingEnabled))
[email protected]c20122572013-12-16 20:35:58362 return true;
363 }
364 return false;
365}
366
James Cookfc97f0a2017-08-16 20:05:35367void AccessibilityManager::UpdateAlwaysShowMenuFromPref() {
368 if (!profile_)
369 return;
370
James Cook696fb106a2017-08-17 21:50:44371 // TODO(crbug.com/594887): Fix for mash by moving pref into ash.
372 if (GetAshConfig() == ash::Config::MASH)
373 return;
374
James Cookfc97f0a2017-08-16 20:05:35375 // Update system tray menu visibility.
James Cookc46731e2017-08-16 23:39:22376 ash::Shell::Get()->system_tray_notifier()->NotifyAccessibilityStatusChanged(
James Cookfc97f0a2017-08-16 20:05:35377 ash::A11Y_NOTIFICATION_NONE);
378}
379
[email protected]8126b812013-06-06 03:49:17380void AccessibilityManager::EnableLargeCursor(bool enabled) {
[email protected]d80f19302013-06-07 13:12:14381 if (!profile_)
382 return;
383
384 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32385 pref_service->SetBoolean(ash::prefs::kAccessibilityLargeCursorEnabled,
386 enabled);
[email protected]d80f19302013-06-07 13:12:14387 pref_service->CommitPendingWrite();
388}
389
James Cook9f9ff79d32017-09-01 00:39:29390void AccessibilityManager::OnLargeCursorChanged() {
jamescooka7f8dab2016-06-21 01:44:03391 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_LARGE_CURSOR,
James Cook9f9ff79d32017-09-01 00:39:29392 IsLargeCursorEnabled(),
393 ash::A11Y_NOTIFICATION_NONE);
[email protected]d8edc9c2014-02-25 00:06:03394 NotifyAccessibilityStatusChanged(details);
[email protected]8126b812013-06-06 03:49:17395}
396
[email protected]5ecf6122013-10-31 12:24:09397bool AccessibilityManager::IsIncognitoAllowed() {
gogeralddde4ee02015-08-26 18:58:49398 return profile_ != NULL &&
399 profile_->GetProfileType() != Profile::GUEST_PROFILE &&
400 IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) !=
401 IncognitoModePrefs::DISABLED;
[email protected]5ecf6122013-10-31 12:24:09402}
403
minch0bfec0b2017-04-10 17:50:09404bool AccessibilityManager::IsLargeCursorEnabled() const {
James Cook9f9ff79d32017-09-01 00:39:29405 return profile_ && profile_->GetPrefs()->GetBoolean(
406 ash::prefs::kAccessibilityLargeCursorEnabled);
[email protected]8126b812013-06-06 03:49:17407}
408
[email protected]93a534e2013-06-20 16:41:44409void AccessibilityManager::EnableStickyKeys(bool enabled) {
410 if (!profile_)
411 return;
412 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32413 pref_service->SetBoolean(ash::prefs::kAccessibilityStickyKeysEnabled,
414 enabled);
[email protected]93a534e2013-06-20 16:41:44415 pref_service->CommitPendingWrite();
416}
417
minch0bfec0b2017-04-10 17:50:09418bool AccessibilityManager::IsStickyKeysEnabled() const {
[email protected]93a534e2013-06-20 16:41:44419 return sticky_keys_enabled_;
420}
421
422void AccessibilityManager::UpdateStickyKeysFromPref() {
423 if (!profile_)
424 return;
425
James Cookc63b9fd2017-08-18 18:48:32426 const bool enabled = profile_->GetPrefs()->GetBoolean(
427 ash::prefs::kAccessibilityStickyKeysEnabled);
[email protected]93a534e2013-06-20 16:41:44428
429 if (sticky_keys_enabled_ == enabled)
430 return;
431
432 sticky_keys_enabled_ = enabled;
minchd9d542482017-04-07 19:29:56433
434 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_STICKY_KEYS,
435 enabled, ash::A11Y_NOTIFICATION_NONE);
436 NotifyAccessibilityStatusChanged(details);
James Cook696fb106a2017-08-17 21:50:44437
438 // TODO(crbug.com/594887): Fix for mash by moving pref into ash.
439 if (GetAshConfig() == ash::Config::MASH)
440 return;
441
skycb4be5b2017-04-06 17:52:45442 ash::Shell::Get()->sticky_keys_controller()->Enable(enabled);
[email protected]93a534e2013-06-20 16:41:44443}
444
[email protected]1dfebfc2013-06-04 03:14:32445void AccessibilityManager::EnableSpokenFeedback(
446 bool enabled,
jamescooka7f8dab2016-06-21 01:44:03447 ash::AccessibilityNotificationVisibility notify) {
[email protected]1dfebfc2013-06-04 03:14:32448 if (!profile_)
449 return;
[email protected]5d2ea362013-12-13 08:10:18450
[email protected]d80f19302013-06-07 13:12:14451 spoken_feedback_notification_ = notify;
452
[email protected]1dfebfc2013-06-04 03:14:32453 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32454 pref_service->SetBoolean(ash::prefs::kAccessibilitySpokenFeedbackEnabled,
455 enabled);
[email protected]1dfebfc2013-06-04 03:14:32456 pref_service->CommitPendingWrite();
[email protected]d80f19302013-06-07 13:12:14457
jamescooka7f8dab2016-06-21 01:44:03458 spoken_feedback_notification_ = ash::A11Y_NOTIFICATION_NONE;
[email protected]d80f19302013-06-07 13:12:14459}
460
461void AccessibilityManager::UpdateSpokenFeedbackFromPref() {
462 if (!profile_)
463 return;
464
[email protected]ced247a2014-06-13 19:14:19465 const bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32466 ash::prefs::kAccessibilitySpokenFeedbackEnabled);
[email protected]d80f19302013-06-07 13:12:14467
dmazzoni63199b12016-10-19 15:44:36468 if (enabled) {
469 chromevox_loader_->SetProfile(
470 profile_, base::Bind(&AccessibilityManager::PostSwitchChromeVoxProfile,
471 weak_ptr_factory_.GetWeakPtr()));
472 }
dmazzoni2c013202016-09-07 19:59:37473
[email protected]d80f19302013-06-07 13:12:14474 if (spoken_feedback_enabled_ == enabled)
475 return;
476
477 spoken_feedback_enabled_ = enabled;
478
[email protected]d8edc9c2014-02-25 00:06:03479 AccessibilityStatusEventDetails details(
480 ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK,
481 enabled,
482 spoken_feedback_notification_);
483
484 NotifyAccessibilityStatusChanged(details);
[email protected]1dfebfc2013-06-04 03:14:32485
[email protected]0e9504d2013-11-05 02:33:29486 if (enabled) {
dtseng4702f8e2017-01-11 18:54:12487 chromevox_loader_->Load(profile_,
dmazzoni337c5af2016-09-13 23:08:57488 base::Bind(&AccessibilityManager::PostLoadChromeVox,
489 weak_ptr_factory_.GetWeakPtr()));
[email protected]0e9504d2013-11-05 02:33:29490 } else {
dmazzoni337c5af2016-09-13 23:08:57491 chromevox_loader_->Unload();
[email protected]0e9504d2013-11-05 02:33:29492 }
[email protected]2e5e0b12014-05-07 13:30:20493 UpdateBrailleImeState();
dmazzoni1970d4e62016-06-16 23:46:34494
495 // ChromeVox focus highlighting overrides the other focus highlighting.
496 UpdateFocusHighlightFromPref();
[email protected]b0a2ce32013-07-23 15:24:53497}
498
minch0bfec0b2017-04-10 17:50:09499bool AccessibilityManager::IsSpokenFeedbackEnabled() const {
[email protected]1dfebfc2013-06-04 03:14:32500 return spoken_feedback_enabled_;
501}
502
503void AccessibilityManager::ToggleSpokenFeedback(
jamescooka7f8dab2016-06-21 01:44:03504 ash::AccessibilityNotificationVisibility notify) {
[email protected]681d0532013-06-11 12:52:50505 EnableSpokenFeedback(!IsSpokenFeedbackEnabled(), notify);
[email protected]1dfebfc2013-06-04 03:14:32506}
507
[email protected]1dfebfc2013-06-04 03:14:32508void AccessibilityManager::EnableHighContrast(bool enabled) {
[email protected]d80f19302013-06-07 13:12:14509 if (!profile_)
510 return;
511
512 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32513 pref_service->SetBoolean(ash::prefs::kAccessibilityHighContrastEnabled,
514 enabled);
[email protected]d80f19302013-06-07 13:12:14515 pref_service->CommitPendingWrite();
516}
517
James Cook5fbdccb2017-09-01 21:17:55518bool AccessibilityManager::IsHighContrastEnabled() const {
519 return profile_ && profile_->GetPrefs()->GetBoolean(
520 ash::prefs::kAccessibilityHighContrastEnabled);
521}
[email protected]d80f19302013-06-07 13:12:14522
James Cook5fbdccb2017-09-01 21:17:55523void AccessibilityManager::OnHighContrastChanged() {
[email protected]d8edc9c2014-02-25 00:06:03524 AccessibilityStatusEventDetails details(
James Cook5fbdccb2017-09-01 21:17:55525 ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE, IsHighContrastEnabled(),
jamescooka7f8dab2016-06-21 01:44:03526 ash::A11Y_NOTIFICATION_NONE);
[email protected]d8edc9c2014-02-25 00:06:03527 NotifyAccessibilityStatusChanged(details);
[email protected]1dfebfc2013-06-04 03:14:32528}
529
[email protected]628b8902014-03-12 05:26:41530void AccessibilityManager::OnLocaleChanged() {
[email protected]d1d5f4f2013-06-14 07:17:09531 if (!profile_)
532 return;
533
534 if (!IsSpokenFeedbackEnabled())
535 return;
536
537 // If the system locale changes and spoken feedback is enabled,
538 // reload ChromeVox so that it switches its internal translations
539 // to the new language.
jamescooka7f8dab2016-06-21 01:44:03540 EnableSpokenFeedback(false, ash::A11Y_NOTIFICATION_NONE);
541 EnableSpokenFeedback(true, ash::A11Y_NOTIFICATION_NONE);
[email protected]d1d5f4f2013-06-14 07:17:09542}
543
yawanoca05a1af2017-01-25 02:38:17544void AccessibilityManager::OnViewFocusedInArc(
545 const gfx::Rect& bounds_in_screen) {
546 accessibility_highlight_manager_->OnViewFocusedInArc(bounds_in_screen);
547}
548
sadrulcdc2bb42016-07-13 19:44:51549bool AccessibilityManager::PlayEarcon(int sound_key, PlaySoundOption option) {
[email protected]07f3ea92014-08-14 05:23:38550 DCHECK(sound_key < chromeos::SOUND_COUNT);
sadrulcdc2bb42016-07-13 19:44:51551 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
552 if (cl->HasSwitch(kAshDisableSystemSounds))
553 return false;
554 if (option == PlaySoundOption::SPOKEN_FEEDBACK_ENABLED &&
David Tseng89850d12017-08-29 02:23:41555 !IsSpokenFeedbackEnabled()) {
sadrulcdc2bb42016-07-13 19:44:51556 return false;
557 }
558 return media::SoundsManager::Get()->Play(sound_key);
[email protected]07f3ea92014-08-14 05:23:38559}
560
dmazzonidf9a1e922017-04-13 05:10:44561void AccessibilityManager::OnTwoFingerTouchStart() {
dmazzonic613a562017-05-02 03:19:19562 if (!profile())
563 return;
564
dmazzonidf9a1e922017-04-13 05:10:44565 extensions::EventRouter* event_router =
566 extensions::EventRouter::Get(profile());
567 CHECK(event_router);
568
569 auto event_args = base::MakeUnique<base::ListValue>();
570 auto event = base::MakeUnique<extensions::Event>(
571 extensions::events::ACCESSIBILITY_PRIVATE_ON_TWO_FINGER_TOUCH_START,
572 extensions::api::accessibility_private::OnTwoFingerTouchStart::kEventName,
573 std::move(event_args));
574 event_router->BroadcastEvent(std::move(event));
575}
576
577void AccessibilityManager::OnTwoFingerTouchStop() {
dmazzonic613a562017-05-02 03:19:19578 if (!profile())
579 return;
580
dmazzonidf9a1e922017-04-13 05:10:44581 extensions::EventRouter* event_router =
582 extensions::EventRouter::Get(profile());
583 CHECK(event_router);
584
585 auto event_args = base::MakeUnique<base::ListValue>();
586 auto event = base::MakeUnique<extensions::Event>(
587 extensions::events::ACCESSIBILITY_PRIVATE_ON_TWO_FINGER_TOUCH_STOP,
588 extensions::api::accessibility_private::OnTwoFingerTouchStop::kEventName,
589 std::move(event_args));
590 event_router->BroadcastEvent(std::move(event));
591}
592
dmazzoni16d2dec2016-12-19 23:27:57593bool AccessibilityManager::ShouldToggleSpokenFeedbackViaTouch() {
dmazzoni200099c2017-01-31 23:21:40594#if 1
595 // Temporarily disabling this feature until UI feedback is fixed.
596 // http://crbug.com/662501
597 return false;
598#else
dmazzoni16d2dec2016-12-19 23:27:57599 policy::BrowserPolicyConnectorChromeOS* connector =
600 g_browser_process->platform_part()->browser_policy_connector_chromeos();
601 if (!connector)
602 return false;
603
604 if (!connector->IsEnterpriseManaged())
605 return false;
606
607 const policy::DeviceCloudPolicyManagerChromeOS* const
608 device_cloud_policy_manager = connector->GetDeviceCloudPolicyManager();
609 if (!device_cloud_policy_manager)
610 return false;
611
612 if (!device_cloud_policy_manager->IsRemoraRequisition())
613 return false;
614
615 KioskAppManager* manager = KioskAppManager::Get();
616 KioskAppManager::App app;
617 CHECK(manager->GetApp(manager->GetAutoLaunchApp(), &app));
618 return app.was_auto_launched_with_zero_delay;
dmazzoni200099c2017-01-31 23:21:40619#endif
dmazzoni16d2dec2016-12-19 23:27:57620}
621
622bool AccessibilityManager::PlaySpokenFeedbackToggleCountdown(int tick_count) {
623 return media::SoundsManager::Get()->Play(
624 tick_count % 2 ? SOUND_SPOKEN_FEEDBACK_TOGGLE_COUNTDOWN_HIGH
625 : SOUND_SPOKEN_FEEDBACK_TOGGLE_COUNTDOWN_LOW);
626}
627
dmazzoni82ef29a2016-05-10 23:37:51628void AccessibilityManager::HandleAccessibilityGesture(ui::AXGesture gesture) {
629 extensions::EventRouter* event_router =
630 extensions::EventRouter::Get(profile());
631 CHECK(event_router);
632
633 std::unique_ptr<base::ListValue> event_args(new base::ListValue());
634 event_args->AppendString(ui::ToString(gesture));
635 std::unique_ptr<extensions::Event> event(new extensions::Event(
636 extensions::events::ACCESSIBILITY_PRIVATE_ON_ACCESSIBILITY_GESTURE,
637 extensions::api::accessibility_private::OnAccessibilityGesture::
638 kEventName,
639 std::move(event_args)));
640 event_router->DispatchEventWithLazyListener(
641 extension_misc::kChromeVoxExtensionId, std::move(event));
642}
643
dmazzoniff86e3472016-06-03 19:52:32644void AccessibilityManager::SetTouchAccessibilityAnchorPoint(
645 const gfx::Point& anchor_point) {
dmazzoni50f65802017-06-28 18:19:39646 for (auto* rwc : ash::RootWindowController::root_window_controllers())
647 rwc->SetTouchAccessibilityAnchorPoint(anchor_point);
dmazzoniff86e3472016-06-03 19:52:32648}
649
[email protected]1c881562013-10-12 07:52:58650void AccessibilityManager::EnableAutoclick(bool enabled) {
651 if (!profile_)
652 return;
653
654 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32655 pref_service->SetBoolean(ash::prefs::kAccessibilityAutoclickEnabled, enabled);
[email protected]1c881562013-10-12 07:52:58656 pref_service->CommitPendingWrite();
657}
658
minch0bfec0b2017-04-10 17:50:09659bool AccessibilityManager::IsAutoclickEnabled() const {
[email protected]1c881562013-10-12 07:52:58660 return autoclick_enabled_;
661}
662
663void AccessibilityManager::UpdateAutoclickFromPref() {
ginkagebda078c2014-12-15 14:24:53664 if (!profile_)
665 return;
666
James Cookc63b9fd2017-08-18 18:48:32667 bool enabled = profile_->GetPrefs()->GetBoolean(
668 ash::prefs::kAccessibilityAutoclickEnabled);
[email protected]1c881562013-10-12 07:52:58669
670 if (autoclick_enabled_ == enabled)
671 return;
672 autoclick_enabled_ = enabled;
673
James Cook696fb106a2017-08-17 21:50:44674 if (GetAshConfig() == ash::Config::MASH) {
rockot400ea35b2016-10-15 19:15:32675 service_manager::Connector* connector =
bend32292b2016-10-07 00:21:58676 content::ServiceManagerConnection::GetForProcess()->GetConnector();
riajiang4b626b972016-09-13 16:12:49677 mash::mojom::LaunchablePtr launchable;
benbd3c2482017-01-07 05:48:21678 connector->BindInterface("accessibility_autoclick", &launchable);
riajiang4b626b972016-09-13 16:12:49679 launchable->Launch(mash::mojom::kWindow, mash::mojom::LaunchMode::DEFAULT);
680 return;
681 }
682
James Cookc46731e2017-08-16 23:39:22683 ash::Shell::Get()->system_tray_notifier()->NotifyAccessibilityStatusChanged(
James Cookfc97f0a2017-08-16 20:05:35684 ash::A11Y_NOTIFICATION_NONE);
skycb4be5b2017-04-06 17:52:45685 ash::Shell::Get()->autoclick_controller()->SetEnabled(enabled);
[email protected]1c881562013-10-12 07:52:58686}
687
[email protected]84d652d2013-10-23 13:57:57688void AccessibilityManager::SetAutoclickDelay(int delay_ms) {
689 if (!profile_)
690 return;
691
692 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32693 pref_service->SetInteger(ash::prefs::kAccessibilityAutoclickDelayMs,
694 delay_ms);
[email protected]84d652d2013-10-23 13:57:57695 pref_service->CommitPendingWrite();
696}
697
698int AccessibilityManager::GetAutoclickDelay() const {
riajiang4b626b972016-09-13 16:12:49699 return static_cast<int>(autoclick_delay_ms_.InMilliseconds());
[email protected]84d652d2013-10-23 13:57:57700}
701
702void AccessibilityManager::UpdateAutoclickDelayFromPref() {
ginkagebda078c2014-12-15 14:24:53703 if (!profile_)
704 return;
705
sammiequon820646f2016-06-24 18:47:13706 base::TimeDelta autoclick_delay_ms = base::TimeDelta::FromMilliseconds(
707 int64_t{profile_->GetPrefs()->GetInteger(
James Cookc63b9fd2017-08-18 18:48:32708 ash::prefs::kAccessibilityAutoclickDelayMs)});
[email protected]84d652d2013-10-23 13:57:57709
710 if (autoclick_delay_ms == autoclick_delay_ms_)
711 return;
712 autoclick_delay_ms_ = autoclick_delay_ms;
713
James Cook696fb106a2017-08-17 21:50:44714 if (GetAshConfig() == ash::Config::MASH) {
rockot400ea35b2016-10-15 19:15:32715 service_manager::Connector* connector =
bend32292b2016-10-07 00:21:58716 content::ServiceManagerConnection::GetForProcess()->GetConnector();
riajiang4b626b972016-09-13 16:12:49717 ash::autoclick::mojom::AutoclickControllerPtr autoclick_controller;
benbd3c2482017-01-07 05:48:21718 connector->BindInterface("accessibility_autoclick", &autoclick_controller);
riajiang4b626b972016-09-13 16:12:49719 autoclick_controller->SetAutoclickDelay(
720 autoclick_delay_ms_.InMilliseconds());
721 return;
722 }
723
skycb4be5b2017-04-06 17:52:45724 ash::Shell::Get()->autoclick_controller()->SetAutoclickDelay(
[email protected]84d652d2013-10-23 13:57:57725 autoclick_delay_ms_);
[email protected]84d652d2013-10-23 13:57:57726}
727
[email protected]e1b299b2014-01-29 23:53:41728void AccessibilityManager::EnableVirtualKeyboard(bool enabled) {
729 if (!profile_)
730 return;
731
732 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32733 pref_service->SetBoolean(ash::prefs::kAccessibilityVirtualKeyboardEnabled,
[email protected]ced247a2014-06-13 19:14:19734 enabled);
[email protected]e1b299b2014-01-29 23:53:41735 pref_service->CommitPendingWrite();
736}
737
minch0bfec0b2017-04-10 17:50:09738bool AccessibilityManager::IsVirtualKeyboardEnabled() const {
[email protected]e1b299b2014-01-29 23:53:41739 return virtual_keyboard_enabled_;
740}
741
742void AccessibilityManager::UpdateVirtualKeyboardFromPref() {
743 if (!profile_)
744 return;
745
[email protected]ced247a2014-06-13 19:14:19746 const bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32747 ash::prefs::kAccessibilityVirtualKeyboardEnabled);
[email protected]e1b299b2014-01-29 23:53:41748
749 if (virtual_keyboard_enabled_ == enabled)
750 return;
751 virtual_keyboard_enabled_ = enabled;
752
[email protected]e1b299b2014-01-29 23:53:41753 keyboard::SetAccessibilityKeyboardEnabled(enabled);
James Cook696fb106a2017-08-17 21:50:44754 if (GetAshConfig() != ash::Config::MASH) {
msw15156bf2016-09-13 21:49:17755 // Note that there are two versions of the on-screen keyboard. A full layout
756 // is provided for accessibility, which includes sticky modifier keys to
Mitsuru Oshima63d3f2a2017-08-23 00:12:11757 // enable typing of hotkeys. A compact version is used in tablet mode
msw15156bf2016-09-13 21:49:17758 // to provide a layout with larger keys to facilitate touch typing. In the
759 // event that the a11y keyboard is being disabled, an on-screen keyboard
760 // might still be enabled and a forced reset is required to pick up the
761 // layout change.
762 if (keyboard::IsKeyboardEnabled())
skycb4be5b2017-04-06 17:52:45763 ash::Shell::Get()->CreateKeyboard();
msw15156bf2016-09-13 21:49:17764 else
Keigo Okac7617a42017-06-14 11:33:24765 ash::Shell::Get()->DestroyKeyboard();
msw15156bf2016-09-13 21:49:17766 } else {
767 // TODO(mash): Support on-screen keyboard. See http://crbug.com/646565
768 NOTIMPLEMENTED();
769 }
rsadama1104b82014-11-03 20:50:52770
jamescooka7f8dab2016-06-21 01:44:03771 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_VIRTUAL_KEYBOARD,
772 enabled, ash::A11Y_NOTIFICATION_NONE);
rsadama1104b82014-11-03 20:50:52773 NotifyAccessibilityStatusChanged(details);
[email protected]e1b299b2014-01-29 23:53:41774}
775
warx533c8f62016-04-12 01:19:43776void AccessibilityManager::EnableMonoAudio(bool enabled) {
777 if (!profile_)
778 return;
779
780 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32781 pref_service->SetBoolean(ash::prefs::kAccessibilityMonoAudioEnabled, enabled);
warx533c8f62016-04-12 01:19:43782 pref_service->CommitPendingWrite();
783}
784
minch0bfec0b2017-04-10 17:50:09785bool AccessibilityManager::IsMonoAudioEnabled() const {
warx533c8f62016-04-12 01:19:43786 return mono_audio_enabled_;
787}
788
789void AccessibilityManager::UpdateMonoAudioFromPref() {
790 if (!profile_)
791 return;
792
793 const bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32794 ash::prefs::kAccessibilityMonoAudioEnabled);
warx533c8f62016-04-12 01:19:43795
796 if (mono_audio_enabled_ == enabled)
797 return;
798 mono_audio_enabled_ = enabled;
799
jamescooka7f8dab2016-06-21 01:44:03800 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_MONO_AUDIO,
801 enabled, ash::A11Y_NOTIFICATION_NONE);
warx533c8f62016-04-12 01:19:43802 NotifyAccessibilityStatusChanged(details);
803
James Cook696fb106a2017-08-17 21:50:44804 // TODO(crbug.com/594887): Fix for mash by moving pref into ash.
805 if (GetAshConfig() == ash::Config::MASH)
806 return;
807
skycb4be5b2017-04-06 17:52:45808 ash::Shell::Get()->audio_a11y_controller()->SetOutputMono(enabled);
warx533c8f62016-04-12 01:19:43809}
810
dmazzoni756089a22016-03-15 23:55:16811void AccessibilityManager::SetCaretHighlightEnabled(bool enabled) {
812 if (!profile_)
813 return;
814
815 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32816 pref_service->SetBoolean(ash::prefs::kAccessibilityCaretHighlightEnabled,
817 enabled);
dmazzoni756089a22016-03-15 23:55:16818 pref_service->CommitPendingWrite();
819}
820
821bool AccessibilityManager::IsCaretHighlightEnabled() const {
822 return caret_highlight_enabled_;
823}
824
825void AccessibilityManager::UpdateCaretHighlightFromPref() {
826 if (!profile_)
827 return;
828
829 const bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32830 ash::prefs::kAccessibilityCaretHighlightEnabled);
dmazzoni756089a22016-03-15 23:55:16831
832 if (caret_highlight_enabled_ == enabled)
833 return;
834 caret_highlight_enabled_ = enabled;
835
mincha0b24ab2017-03-31 22:16:01836 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_CARET_HIGHLIGHT,
837 enabled, ash::A11Y_NOTIFICATION_NONE);
838 NotifyAccessibilityStatusChanged(details);
dmazzonib93107c2016-03-22 21:51:18839 UpdateAccessibilityHighlightingFromPrefs();
dmazzoni756089a22016-03-15 23:55:16840}
841
842void AccessibilityManager::SetCursorHighlightEnabled(bool enabled) {
843 if (!profile_)
844 return;
845
846 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32847 pref_service->SetBoolean(ash::prefs::kAccessibilityCursorHighlightEnabled,
dmazzoni756089a22016-03-15 23:55:16848 enabled);
849 pref_service->CommitPendingWrite();
850}
851
852bool AccessibilityManager::IsCursorHighlightEnabled() const {
853 return cursor_highlight_enabled_;
854}
855
856void AccessibilityManager::UpdateCursorHighlightFromPref() {
857 if (!profile_)
858 return;
859
860 const bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32861 ash::prefs::kAccessibilityCursorHighlightEnabled);
dmazzoni756089a22016-03-15 23:55:16862
863 if (cursor_highlight_enabled_ == enabled)
864 return;
865 cursor_highlight_enabled_ = enabled;
866
mincha0b24ab2017-03-31 22:16:01867 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_CURSOR_HIGHLIGHT,
868 enabled, ash::A11Y_NOTIFICATION_NONE);
869 NotifyAccessibilityStatusChanged(details);
dmazzonib93107c2016-03-22 21:51:18870 UpdateAccessibilityHighlightingFromPrefs();
dmazzoni756089a22016-03-15 23:55:16871}
872
873void AccessibilityManager::SetFocusHighlightEnabled(bool enabled) {
874 if (!profile_)
875 return;
876
877 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32878 pref_service->SetBoolean(ash::prefs::kAccessibilityFocusHighlightEnabled,
879 enabled);
dmazzoni756089a22016-03-15 23:55:16880 pref_service->CommitPendingWrite();
881}
882
883bool AccessibilityManager::IsFocusHighlightEnabled() const {
884 return focus_highlight_enabled_;
885}
886
887void AccessibilityManager::UpdateFocusHighlightFromPref() {
888 if (!profile_)
889 return;
890
dmazzoni42e4b002016-06-08 20:58:42891 bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32892 ash::prefs::kAccessibilityFocusHighlightEnabled);
dmazzoni756089a22016-03-15 23:55:16893
dmazzoni42e4b002016-06-08 20:58:42894 // Focus highlighting can't be on when spoken feedback is on, because
895 // ChromeVox does its own focus highlighting.
896 if (profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32897 ash::prefs::kAccessibilitySpokenFeedbackEnabled))
dmazzoni42e4b002016-06-08 20:58:42898 enabled = false;
899
dmazzoni756089a22016-03-15 23:55:16900 if (focus_highlight_enabled_ == enabled)
901 return;
902 focus_highlight_enabled_ = enabled;
903
mincha0b24ab2017-03-31 22:16:01904 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_FOCUS_HIGHLIGHT,
905 enabled, ash::A11Y_NOTIFICATION_NONE);
906 NotifyAccessibilityStatusChanged(details);
dmazzonib93107c2016-03-22 21:51:18907 UpdateAccessibilityHighlightingFromPrefs();
dmazzoni756089a22016-03-15 23:55:16908}
909
minchd9d542482017-04-07 19:29:56910void AccessibilityManager::EnableTapDragging(bool enabled) {
911 if (!profile_)
912 return;
913
914 PrefService* pref_service = profile_->GetPrefs();
915 pref_service->SetBoolean(prefs::kTapDraggingEnabled, enabled);
916 pref_service->CommitPendingWrite();
917}
918
minch0bfec0b2017-04-10 17:50:09919bool AccessibilityManager::IsTapDraggingEnabled() const {
minchd9d542482017-04-07 19:29:56920 return tap_dragging_enabled_;
921}
922
923void AccessibilityManager::UpdateTapDraggingFromPref() {
924 if (!profile_)
925 return;
926
927 const bool enabled =
928 profile_->GetPrefs()->GetBoolean(prefs::kTapDraggingEnabled);
929
930 if (tap_dragging_enabled_ == enabled)
931 return;
932 tap_dragging_enabled_ = enabled;
933
934 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_TAP_DRAGGING,
935 enabled, ash::A11Y_NOTIFICATION_NONE);
936 NotifyAccessibilityStatusChanged(details);
937
938 system::TouchpadSettings touchpad_settings;
939 touchpad_settings.SetTapDragging(enabled);
940}
941
dmazzoni756089a22016-03-15 23:55:16942void AccessibilityManager::SetSelectToSpeakEnabled(bool enabled) {
943 if (!profile_)
944 return;
945
946 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32947 pref_service->SetBoolean(ash::prefs::kAccessibilitySelectToSpeakEnabled,
948 enabled);
dmazzoni756089a22016-03-15 23:55:16949 pref_service->CommitPendingWrite();
950}
951
952bool AccessibilityManager::IsSelectToSpeakEnabled() const {
953 return select_to_speak_enabled_;
954}
955
956void AccessibilityManager::UpdateSelectToSpeakFromPref() {
957 if (!profile_)
958 return;
959
960 const bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32961 ash::prefs::kAccessibilitySelectToSpeakEnabled);
dmazzoni756089a22016-03-15 23:55:16962
963 if (select_to_speak_enabled_ == enabled)
964 return;
965 select_to_speak_enabled_ = enabled;
966
dmazzoni5288b2612016-09-16 23:05:39967 if (enabled) {
dtseng4702f8e2017-01-11 18:54:12968 select_to_speak_loader_->Load(profile_, base::Closure() /* done_cb */);
dmazzoni735c79df2016-11-28 22:39:42969 select_to_speak_event_handler_.reset(
970 new chromeos::SelectToSpeakEventHandler());
dmazzoni5288b2612016-09-16 23:05:39971 } else {
972 select_to_speak_loader_->Unload();
dmazzoni735c79df2016-11-28 22:39:42973 select_to_speak_event_handler_.reset(nullptr);
dmazzoni5288b2612016-09-16 23:05:39974 }
dmazzoni756089a22016-03-15 23:55:16975}
976
977void AccessibilityManager::SetSwitchAccessEnabled(bool enabled) {
978 if (!profile_)
979 return;
980
981 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32982 pref_service->SetBoolean(ash::prefs::kAccessibilitySwitchAccessEnabled,
983 enabled);
dmazzoni756089a22016-03-15 23:55:16984 pref_service->CommitPendingWrite();
985}
986
987bool AccessibilityManager::IsSwitchAccessEnabled() const {
988 return switch_access_enabled_;
989}
990
991void AccessibilityManager::UpdateSwitchAccessFromPref() {
992 if (!profile_)
993 return;
994
995 const bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32996 ash::prefs::kAccessibilitySwitchAccessEnabled);
dmazzoni756089a22016-03-15 23:55:16997
Dominic Mazzonic85a5c92017-08-31 18:53:30998 // The Switch Access setting is behind a flag. Don't enable the feature
999 // even if the preference is enabled, if the flag isn't also set.
1000 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
1001 if (!command_line->HasSwitch(
1002 chromeos::switches::kEnableExperimentalAccessibilityFeatures)) {
1003 if (enabled) {
1004 LOG(WARNING) << "Switch access enabled but experimental accessibility "
1005 << "features flag is not set.";
1006 }
1007 return;
1008 }
1009
dmazzoni756089a22016-03-15 23:55:161010 if (switch_access_enabled_ == enabled)
1011 return;
1012 switch_access_enabled_ = enabled;
1013
elichtenberg0746c1bd2017-02-22 07:59:151014 if (enabled) {
1015 switch_access_loader_->Load(profile_, base::Closure() /* done_cb */);
elichtenbergc4b4bf462017-02-28 20:48:101016 switch_access_event_handler_.reset(
1017 new chromeos::SwitchAccessEventHandler());
elichtenberg0746c1bd2017-02-22 07:59:151018 } else {
1019 switch_access_loader_->Unload();
elichtenbergc4b4bf462017-02-28 20:48:101020 switch_access_event_handler_.reset(nullptr);
elichtenberg0746c1bd2017-02-22 07:59:151021 }
dmazzoni756089a22016-03-15 23:55:161022}
1023
dmazzonib93107c2016-03-22 21:51:181024void AccessibilityManager::UpdateAccessibilityHighlightingFromPrefs() {
1025 if (!focus_highlight_enabled_ && !caret_highlight_enabled_ &&
1026 !cursor_highlight_enabled_) {
1027 if (accessibility_highlight_manager_)
1028 accessibility_highlight_manager_.reset();
1029 return;
1030 }
1031
dmazzoni7fb1f572016-06-18 00:06:171032 if (!accessibility_highlight_manager_) {
dmazzonib93107c2016-03-22 21:51:181033 accessibility_highlight_manager_.reset(new AccessibilityHighlightManager());
dmazzoni7fb1f572016-06-18 00:06:171034 accessibility_highlight_manager_->RegisterObservers();
1035 }
dmazzonib93107c2016-03-22 21:51:181036
1037 accessibility_highlight_manager_->HighlightFocus(focus_highlight_enabled_);
1038 accessibility_highlight_manager_->HighlightCaret(caret_highlight_enabled_);
1039 accessibility_highlight_manager_->HighlightCursor(cursor_highlight_enabled_);
1040}
1041
[email protected]a81b2c32014-03-28 06:35:011042bool AccessibilityManager::IsBrailleDisplayConnected() const {
1043 return braille_display_connected_;
1044}
1045
[email protected]8c79e3f2013-10-30 01:05:141046void AccessibilityManager::CheckBrailleState() {
[email protected]a81b2c32014-03-28 06:35:011047 BrailleController* braille_controller = GetBrailleController();
1048 if (!scoped_braille_observer_.IsObserving(braille_controller))
1049 scoped_braille_observer_.Add(braille_controller);
[email protected]8c79e3f2013-10-30 01:05:141050 BrowserThread::PostTaskAndReplyWithResult(
[email protected]a81b2c32014-03-28 06:35:011051 BrowserThread::IO,
1052 FROM_HERE,
1053 base::Bind(&BrailleController::GetDisplayState,
1054 base::Unretained(braille_controller)),
[email protected]8c79e3f2013-10-30 01:05:141055 base::Bind(&AccessibilityManager::ReceiveBrailleDisplayState,
1056 weak_ptr_factory_.GetWeakPtr()));
1057}
1058
1059void AccessibilityManager::ReceiveBrailleDisplayState(
dcheng24002d02016-04-08 02:42:401060 std::unique_ptr<extensions::api::braille_display_private::DisplayState>
1061 state) {
[email protected]2e5e0b12014-05-07 13:30:201062 OnBrailleDisplayStateChanged(*state);
1063}
1064
1065void AccessibilityManager::UpdateBrailleImeState() {
1066 if (!profile_)
1067 return;
1068 PrefService* pref_service = profile_->GetPrefs();
mgiuca30f75882017-03-28 02:07:191069 std::string preload_engines_str =
1070 pref_service->GetString(prefs::kLanguagePreloadEngines);
1071 std::vector<base::StringPiece> preload_engines = base::SplitStringPiece(
1072 preload_engines_str, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
1073 std::vector<base::StringPiece>::iterator it =
1074 std::find(preload_engines.begin(), preload_engines.end(),
jamescook2d60f032017-06-01 00:55:211075 extension_ime_util::kBrailleImeEngineId);
[email protected]2e5e0b12014-05-07 13:30:201076 bool is_enabled = (it != preload_engines.end());
1077 bool should_be_enabled =
1078 (spoken_feedback_enabled_ && braille_display_connected_);
1079 if (is_enabled == should_be_enabled)
1080 return;
1081 if (should_be_enabled)
jamescook2d60f032017-06-01 00:55:211082 preload_engines.push_back(extension_ime_util::kBrailleImeEngineId);
[email protected]2e5e0b12014-05-07 13:30:201083 else
1084 preload_engines.erase(it);
1085 pref_service->SetString(prefs::kLanguagePreloadEngines,
brettwd94a22142015-07-15 05:19:261086 base::JoinString(preload_engines, ","));
[email protected]2e5e0b12014-05-07 13:30:201087 braille_ime_current_ = false;
[email protected]8c79e3f2013-10-30 01:05:141088}
1089
[email protected]1488a035f2014-03-28 21:12:071090// Overridden from InputMethodManager::Observer.
1091void AccessibilityManager::InputMethodChanged(
1092 input_method::InputMethodManager* manager,
alematef06730292015-05-12 21:36:071093 Profile* /* profile */,
[email protected]1488a035f2014-03-28 21:12:071094 bool show_message) {
[email protected]1488a035f2014-03-28 21:12:071095 // Sticky keys is implemented only in ash.
dpolukhin04e5b8092014-09-11 02:55:051096 // TODO(dpolukhin): support Athena, crbug.com/408733.
James Cook696fb106a2017-08-17 21:50:441097 if (GetAshConfig() != ash::Config::MASH) {
skycb4be5b2017-04-06 17:52:451098 ash::Shell::Get()->sticky_keys_controller()->SetModifiersEnabled(
riajiang4b626b972016-09-13 16:12:491099 manager->IsISOLevel5ShiftUsedByCurrentInputMethod(),
1100 manager->IsAltGrUsedByCurrentInputMethod());
1101 }
[email protected]2e5e0b12014-05-07 13:30:201102 const chromeos::input_method::InputMethodDescriptor descriptor =
[email protected]f0881cf2014-08-15 23:31:421103 manager->GetActiveIMEState()->GetCurrentInputMethod();
[email protected]2e5e0b12014-05-07 13:30:201104 braille_ime_current_ =
jamescook2d60f032017-06-01 00:55:211105 (descriptor.id() == extension_ime_util::kBrailleImeEngineId);
[email protected]1488a035f2014-03-28 21:12:071106}
[email protected]8c79e3f2013-10-30 01:05:141107
tbarziccd5ad222017-03-24 04:46:311108void AccessibilityManager::OnSessionStateChanged() {
1109 if (!chromevox_panel_)
1110 return;
1111 if (chromevox_panel_->for_blocked_user_session() ==
1112 session_manager::SessionManager::Get()->IsUserSessionBlocked()) {
1113 return;
1114 }
1115
1116 // If user session got blocked or unblocked, reload ChromeVox panel, as
1117 // functionality available to the panel differs based on whether the user
1118 // session is active (and unlocked) or not.
1119 ReloadChromeVoxPanel();
1120}
1121
[email protected]1dfebfc2013-06-04 03:14:321122void AccessibilityManager::SetProfile(Profile* profile) {
Yuki Awanod59b6492017-07-28 00:52:111123 // Do nothing if this is called for the current profile. This can happen. For
1124 // example, ChromeSessionManager fires both
1125 // NOTIFICATION_LOGIN_USER_PROFILE_PREPARED and NOTIFICATION_SESSION_STARTED,
1126 // and we are observing both events.
1127 if (profile_ == profile)
1128 return;
1129
[email protected]1dfebfc2013-06-04 03:14:321130 pref_change_registrar_.reset();
[email protected]d1d5f4f2013-06-14 07:17:091131 local_state_pref_change_registrar_.reset();
[email protected]1dfebfc2013-06-04 03:14:321132
1133 if (profile) {
[email protected]0aae2fe2013-07-05 07:04:421134 // TODO(yoshiki): Move following code to PrefHandler.
[email protected]1dfebfc2013-06-04 03:14:321135 pref_change_registrar_.reset(new PrefChangeRegistrar);
1136 pref_change_registrar_->Init(profile->GetPrefs());
1137 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321138 ash::prefs::kShouldAlwaysShowAccessibilityMenu,
James Cookfc97f0a2017-08-16 20:05:351139 base::Bind(&AccessibilityManager::UpdateAlwaysShowMenuFromPref,
1140 base::Unretained(this)));
1141 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321142 ash::prefs::kAccessibilityLargeCursorEnabled,
James Cook9f9ff79d32017-09-01 00:39:291143 base::Bind(&AccessibilityManager::OnLargeCursorChanged,
[email protected]8126b812013-06-06 03:49:171144 base::Unretained(this)));
1145 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321146 ash::prefs::kAccessibilityLargeCursorDipSize,
James Cook9f9ff79d32017-09-01 00:39:291147 base::Bind(&AccessibilityManager::OnLargeCursorChanged,
yawanodc5533b32017-02-23 11:04:381148 base::Unretained(this)));
1149 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321150 ash::prefs::kAccessibilityStickyKeysEnabled,
[email protected]93a534e2013-06-20 16:41:441151 base::Bind(&AccessibilityManager::UpdateStickyKeysFromPref,
1152 base::Unretained(this)));
1153 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321154 ash::prefs::kAccessibilitySpokenFeedbackEnabled,
[email protected]d80f19302013-06-07 13:12:141155 base::Bind(&AccessibilityManager::UpdateSpokenFeedbackFromPref,
[email protected]1dfebfc2013-06-04 03:14:321156 base::Unretained(this)));
1157 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321158 ash::prefs::kAccessibilityHighContrastEnabled,
James Cook5fbdccb2017-09-01 21:17:551159 base::Bind(&AccessibilityManager::OnHighContrastChanged,
[email protected]1dfebfc2013-06-04 03:14:321160 base::Unretained(this)));
[email protected]1c881562013-10-12 07:52:581161 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321162 ash::prefs::kAccessibilityAutoclickEnabled,
[email protected]1c881562013-10-12 07:52:581163 base::Bind(&AccessibilityManager::UpdateAutoclickFromPref,
1164 base::Unretained(this)));
[email protected]84d652d2013-10-23 13:57:571165 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321166 ash::prefs::kAccessibilityAutoclickDelayMs,
[email protected]84d652d2013-10-23 13:57:571167 base::Bind(&AccessibilityManager::UpdateAutoclickDelayFromPref,
1168 base::Unretained(this)));
[email protected]e1b299b2014-01-29 23:53:411169 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321170 ash::prefs::kAccessibilityVirtualKeyboardEnabled,
[email protected]e1b299b2014-01-29 23:53:411171 base::Bind(&AccessibilityManager::UpdateVirtualKeyboardFromPref,
1172 base::Unretained(this)));
dmazzoni756089a22016-03-15 23:55:161173 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321174 ash::prefs::kAccessibilityMonoAudioEnabled,
warx533c8f62016-04-12 01:19:431175 base::Bind(&AccessibilityManager::UpdateMonoAudioFromPref,
1176 base::Unretained(this)));
1177 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321178 ash::prefs::kAccessibilityCaretHighlightEnabled,
dmazzoni756089a22016-03-15 23:55:161179 base::Bind(&AccessibilityManager::UpdateCaretHighlightFromPref,
1180 base::Unretained(this)));
1181 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321182 ash::prefs::kAccessibilityCursorHighlightEnabled,
dmazzoni756089a22016-03-15 23:55:161183 base::Bind(&AccessibilityManager::UpdateCursorHighlightFromPref,
1184 base::Unretained(this)));
1185 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321186 ash::prefs::kAccessibilityFocusHighlightEnabled,
dmazzoni756089a22016-03-15 23:55:161187 base::Bind(&AccessibilityManager::UpdateFocusHighlightFromPref,
1188 base::Unretained(this)));
1189 pref_change_registrar_->Add(
minchd9d542482017-04-07 19:29:561190 prefs::kTapDraggingEnabled,
1191 base::Bind(&AccessibilityManager::UpdateTapDraggingFromPref,
1192 base::Unretained(this)));
1193 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321194 ash::prefs::kAccessibilitySelectToSpeakEnabled,
dmazzoni756089a22016-03-15 23:55:161195 base::Bind(&AccessibilityManager::UpdateSelectToSpeakFromPref,
1196 base::Unretained(this)));
1197 pref_change_registrar_->Add(
James Cookc63b9fd2017-08-18 18:48:321198 ash::prefs::kAccessibilitySwitchAccessEnabled,
dmazzoni756089a22016-03-15 23:55:161199 base::Bind(&AccessibilityManager::UpdateSwitchAccessFromPref,
1200 base::Unretained(this)));
[email protected]1dfebfc2013-06-04 03:14:321201
[email protected]d1d5f4f2013-06-14 07:17:091202 local_state_pref_change_registrar_.reset(new PrefChangeRegistrar);
1203 local_state_pref_change_registrar_->Init(g_browser_process->local_state());
1204 local_state_pref_change_registrar_->Add(
1205 prefs::kApplicationLocale,
[email protected]628b8902014-03-12 05:26:411206 base::Bind(&AccessibilityManager::OnLocaleChanged,
[email protected]d1d5f4f2013-06-14 07:17:091207 base::Unretained(this)));
1208
[email protected]1dfebfc2013-06-04 03:14:321209 content::BrowserAccessibilityState::GetInstance()->AddHistogramCallback(
1210 base::Bind(
1211 &AccessibilityManager::UpdateChromeOSAccessibilityHistograms,
1212 base::Unretained(this)));
dmazzoni337c5af2016-09-13 23:08:571213
dmazzoni337c5af2016-09-13 23:08:571214 extensions::ExtensionRegistry* registry =
1215 extensions::ExtensionRegistry::Get(profile);
1216 if (!extension_registry_observer_.IsObserving(registry))
1217 extension_registry_observer_.Add(registry);
[email protected]1dfebfc2013-06-04 03:14:321218 }
1219
[email protected]0aae2fe2013-07-05 07:04:421220 large_cursor_pref_handler_.HandleProfileChanged(profile_, profile);
1221 spoken_feedback_pref_handler_.HandleProfileChanged(profile_, profile);
1222 high_contrast_pref_handler_.HandleProfileChanged(profile_, profile);
minchd9d542482017-04-07 19:29:561223 sticky_keys_pref_handler_.HandleProfileChanged(profile_, profile);
[email protected]1c881562013-10-12 07:52:581224 autoclick_pref_handler_.HandleProfileChanged(profile_, profile);
[email protected]84d652d2013-10-23 13:57:571225 autoclick_delay_pref_handler_.HandleProfileChanged(profile_, profile);
[email protected]42b471f2014-01-31 20:31:291226 virtual_keyboard_pref_handler_.HandleProfileChanged(profile_, profile);
warx533c8f62016-04-12 01:19:431227 mono_audio_pref_handler_.HandleProfileChanged(profile_, profile);
dmazzoni756089a22016-03-15 23:55:161228 caret_highlight_pref_handler_.HandleProfileChanged(profile_, profile);
1229 cursor_highlight_pref_handler_.HandleProfileChanged(profile_, profile);
1230 focus_highlight_pref_handler_.HandleProfileChanged(profile_, profile);
minchd9d542482017-04-07 19:29:561231 tap_dragging_pref_handler_.HandleProfileChanged(profile_, profile);
dmazzoni756089a22016-03-15 23:55:161232 select_to_speak_pref_handler_.HandleProfileChanged(profile_, profile);
1233 switch_access_pref_handler_.HandleProfileChanged(profile_, profile);
[email protected]0aae2fe2013-07-05 07:04:421234
[email protected]a81b2c32014-03-28 06:35:011235 bool had_profile = (profile_ != NULL);
1236 profile_ = profile;
1237
1238 if (!had_profile && profile)
[email protected]8c79e3f2013-10-30 01:05:141239 CheckBrailleState();
[email protected]2e5e0b12014-05-07 13:30:201240 else
1241 UpdateBrailleImeState();
James Cookfc97f0a2017-08-16 20:05:351242 UpdateAlwaysShowMenuFromPref();
[email protected]93a534e2013-06-20 16:41:441243 UpdateStickyKeysFromPref();
[email protected]d80f19302013-06-07 13:12:141244 UpdateSpokenFeedbackFromPref();
[email protected]1c881562013-10-12 07:52:581245 UpdateAutoclickFromPref();
[email protected]84d652d2013-10-23 13:57:571246 UpdateAutoclickDelayFromPref();
[email protected]e1b299b2014-01-29 23:53:411247 UpdateVirtualKeyboardFromPref();
warx533c8f62016-04-12 01:19:431248 UpdateMonoAudioFromPref();
dmazzoni756089a22016-03-15 23:55:161249 UpdateCaretHighlightFromPref();
1250 UpdateCursorHighlightFromPref();
1251 UpdateFocusHighlightFromPref();
minchd9d542482017-04-07 19:29:561252 UpdateTapDraggingFromPref();
dmazzoni756089a22016-03-15 23:55:161253 UpdateSelectToSpeakFromPref();
1254 UpdateSwitchAccessFromPref();
dmazzoni39d6d4b2016-03-29 22:18:001255
1256 // Update the panel height in the shelf layout manager when the profile
1257 // changes, since the shelf layout manager doesn't exist in the login profile.
1258 if (chromevox_panel_)
1259 chromevox_panel_->UpdatePanelHeight();
[email protected]1dfebfc2013-06-04 03:14:321260}
1261
xiyuan5d8d3ba2017-03-01 21:34:401262void AccessibilityManager::ActiveUserChanged(
1263 const user_manager::User* active_user) {
xiyuan8c6a4112017-06-19 21:03:491264 if (active_user && active_user->is_profile_created())
1265 SetProfile(ProfileManager::GetActiveUserProfile());
[email protected]c20122572013-12-16 20:35:581266}
1267
varkhac71444e52017-05-25 22:51:341268void AccessibilityManager::OnFullscreenStateChanged(bool is_fullscreen,
1269 aura::Window* root_window) {
dmazzonid47388d2016-03-31 16:03:511270 if (chromevox_panel_)
1271 chromevox_panel_->UpdateWidgetBounds();
1272}
1273
[email protected]1dfebfc2013-06-04 03:14:321274void AccessibilityManager::SetProfileForTest(Profile* profile) {
1275 SetProfile(profile);
1276}
1277
[email protected]8c79e3f2013-10-30 01:05:141278void AccessibilityManager::SetBrailleControllerForTest(
1279 BrailleController* controller) {
1280 g_braille_controller_for_test = controller;
1281}
1282
[email protected]ce89d9392013-12-11 21:05:201283base::TimeDelta AccessibilityManager::PlayShutdownSound() {
sadrulcdc2bb42016-07-13 19:44:511284 if (!PlayEarcon(SOUND_SHUTDOWN, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED))
[email protected]4f011f12014-01-15 08:22:451285 return base::TimeDelta();
1286 return media::SoundsManager::Get()->GetDuration(SOUND_SHUTDOWN);
[email protected]ce89d9392013-12-11 21:05:201287}
1288
dcheng24002d02016-04-08 02:42:401289std::unique_ptr<AccessibilityStatusSubscription>
1290AccessibilityManager::RegisterCallback(const AccessibilityStatusCallback& cb) {
[email protected]d8edc9c2014-02-25 00:06:031291 return callback_list_.Add(cb);
1292}
1293
1294void AccessibilityManager::NotifyAccessibilityStatusChanged(
1295 AccessibilityStatusEventDetails& details) {
1296 callback_list_.Notify(details);
James Cookfc97f0a2017-08-16 20:05:351297
James Cook696fb106a2017-08-17 21:50:441298 // TODO(crbug.com/594887): Fix for mash by moving pref into ash.
1299 if (GetAshConfig() == ash::Config::MASH)
1300 return;
1301
James Cookec144952017-09-01 00:05:161302 // Update system tray menu visibility. Prefs tracked inside ash handle their
1303 // own updates to avoid race conditions (pref updates are asynchronous between
1304 // chrome and ash).
1305 if (details.notification_type != ACCESSIBILITY_MANAGER_SHUTDOWN &&
1306 details.notification_type != ACCESSIBILITY_TOGGLE_LARGE_CURSOR) {
James Cookc46731e2017-08-16 23:39:221307 ash::Shell::Get()->system_tray_notifier()->NotifyAccessibilityStatusChanged(
James Cookfc97f0a2017-08-16 20:05:351308 details.notify);
1309 }
[email protected]d8edc9c2014-02-25 00:06:031310}
1311
[email protected]1dfebfc2013-06-04 03:14:321312void AccessibilityManager::UpdateChromeOSAccessibilityHistograms() {
1313 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosSpokenFeedback",
1314 IsSpokenFeedbackEnabled());
1315 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosHighContrast",
1316 IsHighContrastEnabled());
1317 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosVirtualKeyboard",
[email protected]e1b299b2014-01-29 23:53:411318 IsVirtualKeyboardEnabled());
[email protected]7fb7ea42014-02-12 21:19:311319 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosStickyKeys", IsStickyKeysEnabled());
[email protected]1dfebfc2013-06-04 03:14:321320 if (MagnificationManager::Get()) {
James Cookdb81c7672017-08-30 15:18:241321 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosScreenMagnifier",
1322 MagnificationManager::Get()->IsMagnifierEnabled());
[email protected]1dfebfc2013-06-04 03:14:321323 }
[email protected]ca3a0a82013-06-18 06:52:121324 if (profile_) {
1325 const PrefService* const prefs = profile_->GetPrefs();
yawano0c3441c72017-04-11 01:09:161326
1327 bool large_cursor_enabled =
James Cookc63b9fd2017-08-18 18:48:321328 prefs->GetBoolean(ash::prefs::kAccessibilityLargeCursorEnabled);
yawano0c3441c72017-04-11 01:09:161329 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosLargeCursor",
1330 large_cursor_enabled);
yawano92daff52017-04-21 06:34:281331 if (large_cursor_enabled) {
yawano0c3441c72017-04-11 01:09:161332 UMA_HISTOGRAM_COUNTS_100(
1333 "Accessibility.CrosLargeCursorSize",
James Cookc63b9fd2017-08-18 18:48:321334 prefs->GetInteger(ash::prefs::kAccessibilityLargeCursorDipSize));
yawano0c3441c72017-04-11 01:09:161335 }
1336
[email protected]ca3a0a82013-06-18 06:52:121337 UMA_HISTOGRAM_BOOLEAN(
1338 "Accessibility.CrosAlwaysShowA11yMenu",
James Cookc63b9fd2017-08-18 18:48:321339 prefs->GetBoolean(ash::prefs::kShouldAlwaysShowAccessibilityMenu));
[email protected]0b5a0d2b2013-10-30 03:43:401340
[email protected]ced247a2014-06-13 19:14:191341 bool autoclick_enabled =
James Cookc63b9fd2017-08-18 18:48:321342 prefs->GetBoolean(ash::prefs::kAccessibilityAutoclickEnabled);
[email protected]0b5a0d2b2013-10-30 03:43:401343 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosAutoclick", autoclick_enabled);
1344 if (autoclick_enabled) {
1345 // We only want to log the autoclick delay if the user has actually
1346 // enabled autoclick.
1347 UMA_HISTOGRAM_CUSTOM_TIMES(
1348 "Accessibility.CrosAutoclickDelay",
1349 base::TimeDelta::FromMilliseconds(
James Cookc63b9fd2017-08-18 18:48:321350 prefs->GetInteger(ash::prefs::kAccessibilityAutoclickDelayMs)),
[email protected]0b5a0d2b2013-10-30 03:43:401351 base::TimeDelta::FromMilliseconds(1),
James Cookc63b9fd2017-08-18 18:48:321352 base::TimeDelta::FromMilliseconds(3000), 50);
[email protected]0b5a0d2b2013-10-30 03:43:401353 }
[email protected]ca3a0a82013-06-18 06:52:121354 }
dmazzoni756089a22016-03-15 23:55:161355 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosCaretHighlight",
1356 IsCaretHighlightEnabled());
1357 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosCursorHighlight",
1358 IsCursorHighlightEnabled());
1359 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosFocusHighlight",
1360 IsFocusHighlightEnabled());
1361 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosSelectToSpeak",
1362 IsSelectToSpeakEnabled());
1363 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosSwitchAccess",
1364 IsSwitchAccessEnabled());
[email protected]1dfebfc2013-06-04 03:14:321365}
1366
1367void AccessibilityManager::Observe(
1368 int type,
1369 const content::NotificationSource& source,
1370 const content::NotificationDetails& details) {
1371 switch (type) {
[email protected]093d9ba2013-07-23 19:26:211372 case chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE: {
[email protected]9cf54f362013-07-01 07:28:121373 // Update |profile_| when entering the login screen.
[email protected]c20122572013-12-16 20:35:581374 Profile* profile = ProfileManager::GetActiveUserProfile();
[email protected]d888cdc2013-06-24 17:06:201375 if (ProfileHelper::IsSigninProfile(profile))
1376 SetProfile(profile);
[email protected]1dfebfc2013-06-04 03:14:321377 break;
[email protected]d888cdc2013-06-24 17:06:201378 }
Yuki Awanod59b6492017-07-28 00:52:111379 case chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED:
1380 // Update |profile_| when login user profile is prepared.
1381 // NOTIFICATION_SESSION_STARTED is not fired from UserSessionManager, but
1382 // profile may be changed by UserSessionManager in OOBE flow.
1383 SetProfile(ProfileManager::GetActiveUserProfile());
1384 break;
[email protected]e6f20642013-06-11 17:05:461385 case chrome::NOTIFICATION_SESSION_STARTED:
1386 // Update |profile_| when entering a session.
[email protected]c20122572013-12-16 20:35:581387 SetProfile(ProfileManager::GetActiveUserProfile());
[email protected]0e9504d2013-11-05 02:33:291388
[email protected]c20122572013-12-16 20:35:581389 // Add a session state observer to be able to monitor session changes.
xiyuan5d8d3ba2017-03-01 21:34:401390 if (!session_state_observer_.get())
[email protected]c20122572013-12-16 20:35:581391 session_state_observer_.reset(
xiyuan5d8d3ba2017-03-01 21:34:401392 new user_manager::ScopedUserSessionStateObserver(this));
[email protected]1dfebfc2013-06-04 03:14:321393 break;
[email protected]1dfebfc2013-06-04 03:14:321394 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
[email protected]e6f20642013-06-11 17:05:461395 // Update |profile_| when exiting a session or shutting down.
1396 Profile* profile = content::Source<Profile>(source).ptr();
1397 if (profile_ == profile)
1398 SetProfile(NULL);
[email protected]1dfebfc2013-06-04 03:14:321399 break;
1400 }
[email protected]1dfebfc2013-06-04 03:14:321401 }
1402}
1403
[email protected]2e5e0b12014-05-07 13:30:201404void AccessibilityManager::OnBrailleDisplayStateChanged(
[email protected]8c79e3f2013-10-30 01:05:141405 const DisplayState& display_state) {
[email protected]a81b2c32014-03-28 06:35:011406 braille_display_connected_ = display_state.available;
[email protected]2e5e0b12014-05-07 13:30:201407 if (braille_display_connected_) {
jamescooka7f8dab2016-06-21 01:44:031408 EnableSpokenFeedback(true, ash::A11Y_NOTIFICATION_SHOW);
[email protected]2e5e0b12014-05-07 13:30:201409 }
1410 UpdateBrailleImeState();
[email protected]a81b2c32014-03-28 06:35:011411
1412 AccessibilityStatusEventDetails details(
1413 ACCESSIBILITY_BRAILLE_DISPLAY_CONNECTION_STATE_CHANGED,
jamescooka7f8dab2016-06-21 01:44:031414 braille_display_connected_, ash::A11Y_NOTIFICATION_SHOW);
[email protected]a81b2c32014-03-28 06:35:011415 NotifyAccessibilityStatusChanged(details);
[email protected]8c79e3f2013-10-30 01:05:141416}
[email protected]0e9504d2013-11-05 02:33:291417
[email protected]2e5e0b12014-05-07 13:30:201418void AccessibilityManager::OnBrailleKeyEvent(const KeyEvent& event) {
1419 // Ensure the braille IME is active on braille keyboard (dots) input.
1420 if ((event.command ==
1421 extensions::api::braille_display_private::KEY_COMMAND_DOTS) &&
1422 !braille_ime_current_) {
[email protected]f0881cf2014-08-15 23:31:421423 input_method::InputMethodManager::Get()
1424 ->GetActiveIMEState()
jamescook2d60f032017-06-01 00:55:211425 ->ChangeInputMethod(extension_ime_util::kBrailleImeEngineId,
[email protected]f0881cf2014-08-15 23:31:421426 false /* show_message */);
[email protected]2e5e0b12014-05-07 13:30:201427 }
1428}
1429
dtsengfb6d7cd2016-01-20 23:00:131430void AccessibilityManager::OnExtensionUnloaded(
1431 content::BrowserContext* browser_context,
1432 const extensions::Extension* extension,
limasdf0deef2042017-05-03 19:17:171433 extensions::UnloadedExtensionReason reason) {
dtsengfb6d7cd2016-01-20 23:00:131434 if (extension->id() == keyboard_listener_extension_id_) {
1435 keyboard_listener_extension_id_ = std::string();
1436 keyboard_listener_capture_ = false;
dtsengfb6d7cd2016-01-20 23:00:131437 }
1438}
1439
1440void AccessibilityManager::OnShutdown(extensions::ExtensionRegistry* registry) {
1441 extension_registry_observer_.Remove(registry);
1442}
1443
dmazzoni337c5af2016-09-13 23:08:571444void AccessibilityManager::PostLoadChromeVox() {
[email protected]ee8bbd972014-02-03 06:52:471445 // Do any setup work needed immediately after ChromeVox actually loads.
sadrulcdc2bb42016-07-13 19:44:511446 PlayEarcon(SOUND_SPOKEN_FEEDBACK_ENABLED, PlaySoundOption::ALWAYS);
[email protected]0e9504d2013-11-05 02:33:291447
dtseng4702f8e2017-01-11 18:54:121448 extensions::EventRouter* event_router =
1449 extensions::EventRouter::Get(profile_);
1450 CHECK(event_router);
dtseng703a2042015-01-22 17:46:511451
dtseng4702f8e2017-01-11 18:54:121452 std::unique_ptr<base::ListValue> event_args(new base::ListValue());
1453 std::unique_ptr<extensions::Event> event(new extensions::Event(
1454 extensions::events::ACCESSIBILITY_PRIVATE_ON_INTRODUCE_CHROME_VOX,
1455 extensions::api::accessibility_private::OnIntroduceChromeVox::kEventName,
1456 std::move(event_args)));
1457 event_router->DispatchEventWithLazyListener(
1458 extension_misc::kChromeVoxExtensionId, std::move(event));
dmazzoni94a4f882015-11-13 05:46:521459
1460 if (!chromevox_panel_) {
tbarziccd5ad222017-03-24 04:46:311461 chromevox_panel_ = new ChromeVoxPanel(
1462 profile_,
1463 session_manager::SessionManager::Get()->IsUserSessionBlocked());
dmazzoni94a4f882015-11-13 05:46:521464 chromevox_panel_widget_observer_.reset(
1465 new ChromeVoxPanelWidgetObserver(chromevox_panel_->GetWidget(), this));
1466 }
dtsengd50debe32016-12-29 06:23:371467
1468 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
Dominic Mazzonic85a5c92017-08-31 18:53:301469 ::switches::kEnableAudioFocus)) {
dtsengd50debe32016-12-29 06:23:371470 base::CommandLine::ForCurrentProcess()->AppendSwitch(
Dominic Mazzonic85a5c92017-08-31 18:53:301471 ::switches::kEnableAudioFocus);
dtsengd50debe32016-12-29 06:23:371472 }
[email protected]0e9504d2013-11-05 02:33:291473}
1474
dmazzoni337c5af2016-09-13 23:08:571475void AccessibilityManager::PostUnloadChromeVox() {
[email protected]9d6c91362013-12-07 21:56:271476 // Do any teardown work needed immediately after ChromeVox actually unloads.
sadrulcdc2bb42016-07-13 19:44:511477 PlayEarcon(SOUND_SPOKEN_FEEDBACK_DISABLED, PlaySoundOption::ALWAYS);
dmazzonifb33d592014-10-30 19:26:541478 // Clear the accessibility focus ring.
1479 AccessibilityFocusRingController::GetInstance()->SetFocusRing(
dmazzoni42e4b002016-06-08 20:58:421480 std::vector<gfx::Rect>(),
1481 AccessibilityFocusRingController::PERSIST_FOCUS_RING);
dmazzoni337c5af2016-09-13 23:08:571482
1483 if (chromevox_panel_) {
1484 chromevox_panel_->Close();
1485 chromevox_panel_ = nullptr;
1486 }
dtseng3a17f212017-03-25 08:58:521487
1488 // In case the user darkened the screen, undarken it now.
1489 chromeos::DBusThreadManager::Get()
1490 ->GetPowerManagerClient()
1491 ->SetBacklightsForcedOff(false);
[email protected]9d6c91362013-12-07 21:56:271492}
1493
dmazzoni63199b12016-10-19 15:44:361494void AccessibilityManager::PostSwitchChromeVoxProfile() {
tbarziccd5ad222017-03-24 04:46:311495 ReloadChromeVoxPanel();
1496}
1497
1498void AccessibilityManager::ReloadChromeVoxPanel() {
dmazzoni63199b12016-10-19 15:44:361499 if (chromevox_panel_) {
1500 chromevox_panel_->Close();
1501 chromevox_panel_ = nullptr;
1502 }
tbarziccd5ad222017-03-24 04:46:311503 chromevox_panel_ = new ChromeVoxPanel(
1504 profile_, session_manager::SessionManager::Get()->IsUserSessionBlocked());
dmazzoni63199b12016-10-19 15:44:361505 chromevox_panel_widget_observer_.reset(
1506 new ChromeVoxPanelWidgetObserver(chromevox_panel_->GetWidget(), this));
1507}
1508
dmazzoni94a4f882015-11-13 05:46:521509void AccessibilityManager::OnChromeVoxPanelClosing() {
jamescook788b4fc2017-05-18 16:16:061510 chromevox_panel_->ResetPanelHeight();
1511 chromevox_panel_widget_observer_.reset();
dmazzoni94a4f882015-11-13 05:46:521512 chromevox_panel_ = nullptr;
dmazzoni94a4f882015-11-13 05:46:521513}
1514
1515void AccessibilityManager::OnChromeVoxPanelDestroying() {
1516 chromevox_panel_widget_observer_.reset(nullptr);
1517 chromevox_panel_ = nullptr;
1518}
1519
dtsengfb6d7cd2016-01-20 23:00:131520void AccessibilityManager::SetKeyboardListenerExtensionId(
1521 const std::string& id,
1522 content::BrowserContext* context) {
1523 keyboard_listener_extension_id_ = id;
1524
1525 extensions::ExtensionRegistry* registry =
1526 extensions::ExtensionRegistry::Get(context);
1527 if (!extension_registry_observer_.IsObserving(registry) && !id.empty())
1528 extension_registry_observer_.Add(registry);
1529}
1530
elichtenberga108c8a2017-06-02 21:13:191531void AccessibilityManager::SetSwitchAccessKeys(const std::set<int>& key_codes) {
1532 if (switch_access_enabled_)
1533 switch_access_event_handler_->SetKeysToCapture(key_codes);
1534}
1535
[email protected]1dfebfc2013-06-04 03:14:321536} // namespace chromeos