blob: 21c702ec4e639fc03627588b3ae8980ac6c4f9e1 [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"
James Cook108e6122017-09-20 19:04:2914#include "ash/accessibility/accessibility_focus_ring_controller.h"
pkotwicz04d5c892015-01-15 00:05:3615#include "ash/autoclick/autoclick_controller.h"
riajiang4b626b972016-09-13 16:12:4916#include "ash/autoclick/mus/public/interfaces/autoclick.mojom.h"
James Cookc63b9fd2017-08-18 18:48:3217#include "ash/public/cpp/ash_pref_names.h"
dmazzoniff86e3472016-06-03 19:52:3218#include "ash/root_window_controller.h"
James Cook840177e2017-05-25 02:20:0119#include "ash/shelf/shelf.h"
James Cookb0bf8e82017-04-09 17:01:4420#include "ash/shelf/shelf_layout_manager.h"
pkotwicz04d5c892015-01-15 00:05:3621#include "ash/shell.h"
pkotwicz04d5c892015-01-15 00:05:3622#include "ash/sticky_keys/sticky_keys_controller.h"
Daniel Erat477c56d2017-12-13 21:42:5423#include "ash/system/power/backlights_forced_off_setter.h"
24#include "ash/system/power/scoped_backlights_forced_off.h"
James Cookfc97f0a2017-08-16 20:05:3525#include "ash/system/tray/system_tray_notifier.h"
[email protected]44beb032014-06-11 06:24:3726#include "base/callback.h"
27#include "base/callback_helpers.h"
plundbladcf1d08f2015-09-28 09:18:5828#include "base/command_line.h"
avi8a07d53892015-12-24 22:13:5329#include "base/macros.h"
fdorayba121422016-12-23 19:51:4830#include "base/memory/ptr_util.h"
[email protected]1dfebfc2013-06-04 03:14:3231#include "base/memory/singleton.h"
asvitkineb56637512016-09-01 19:41:4032#include "base/metrics/histogram_macros.h"
[email protected]ab38d192013-12-13 11:38:5833#include "base/path_service.h"
mgiuca30f75882017-03-28 02:07:1934#include "base/strings/string_piece.h"
[email protected]2e5e0b12014-05-07 13:30:2035#include "base/strings/string_split.h"
36#include "base/strings/string_util.h"
[email protected]0b5a0d2b2013-10-30 03:43:4037#include "base/time/time.h"
[email protected]0aae2fe2013-07-05 07:04:4238#include "base/values.h"
[email protected]1dfebfc2013-06-04 03:14:3239#include "chrome/browser/accessibility/accessibility_extension_api.h"
40#include "chrome/browser/browser_process.h"
[email protected]fdf40f3e2013-07-11 23:55:4641#include "chrome/browser/chrome_notification_types.h"
dmazzoni337c5af2016-09-13 23:08:5742#include "chrome/browser/chromeos/accessibility/accessibility_extension_loader.h"
dmazzonib93107c2016-03-22 21:51:1843#include "chrome/browser/chromeos/accessibility/accessibility_highlight_manager.h"
pkotwicz04d5c892015-01-15 00:05:3644#include "chrome/browser/chromeos/accessibility/magnification_manager.h"
elichtenbergc4b4bf462017-02-28 20:48:1045#include "chrome/browser/chromeos/accessibility/switch_access_event_handler.h"
dmazzoni16d2dec2016-12-19 23:27:5746#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
James Cook696fb106a2017-08-17 21:50:4447#include "chrome/browser/chromeos/ash_config.h"
dmazzoni16d2dec2016-12-19 23:27:5748#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
[email protected]e6f20642013-06-11 17:05:4649#include "chrome/browser/chromeos/profiles/profile_helper.h"
minchd9d542482017-04-07 19:29:5650#include "chrome/browser/chromeos/system/input_device_settings.h"
plundbladcf1d08f2015-09-28 09:18:5851#include "chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h"
[email protected]1dfebfc2013-06-04 03:14:3252#include "chrome/browser/extensions/extension_service.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"
[email protected]ce89d9392013-12-11 21:05:2060#include "chromeos/audio/chromeos_sounds.h"
Dominic Mazzonic85a5c92017-08-31 18:53:3061#include "chromeos/chromeos_switches.h"
dtseng3a17f212017-03-25 08:58:5262#include "chromeos/dbus/dbus_thread_manager.h"
63#include "chromeos/dbus/power_manager_client.h"
brettwb1fc1b82016-02-02 00:19:0864#include "components/prefs/pref_member.h"
65#include "components/prefs/pref_service.h"
tbarziccd5ad222017-03-24 04:46:3166#include "components/session_manager/core/session_manager.h"
[email protected]1dfebfc2013-06-04 03:14:3267#include "content/public/browser/browser_accessibility_state.h"
[email protected]8c79e3f2013-10-30 01:05:1468#include "content/public/browser/browser_thread.h"
[email protected]9cf54f362013-07-01 07:28:1269#include "content/public/browser/notification_details.h"
[email protected]1dfebfc2013-06-04 03:14:3270#include "content/public/browser/notification_service.h"
[email protected]9cf54f362013-07-01 07:28:1271#include "content/public/browser/notification_source.h"
[email protected]1dfebfc2013-06-04 03:14:3272#include "content/public/browser/web_ui.h"
plundbladcf1d08f2015-09-28 09:18:5873#include "content/public/common/content_switches.h"
bend32292b2016-10-07 00:21:5874#include "content/public/common/service_manager_connection.h"
juncaicf523332015-06-04 00:14:0475#include "extensions/browser/event_router.h"
reillyga3acbc12014-11-11 23:17:1276#include "extensions/browser/extension_registry.h"
[email protected]59b0e602014-01-30 00:41:2477#include "extensions/browser/extension_system.h"
[email protected]e4452d32013-11-15 23:07:4178#include "extensions/common/extension.h"
[email protected]fb820c02014-03-13 15:07:0879#include "extensions/common/extension_messages.h"
[email protected]1dfebfc2013-06-04 03:14:3280#include "extensions/common/extension_resource.h"
hanxi79f7a572015-03-09 20:46:5981#include "extensions/common/host_id.h"
riajiang4b626b972016-09-13 16:12:4982#include "mash/public/interfaces/launchable.mojom.h"
[email protected]12b0a842013-12-04 20:48:1383#include "media/audio/sounds/sounds_manager.h"
dtsengd50debe32016-12-29 06:23:3784#include "media/base/media_switches.h"
rockot734fb662016-10-15 16:41:3085#include "services/service_manager/public/cpp/connector.h"
jamescook2d60f032017-06-01 00:55:2186#include "ui/base/ime/chromeos/extension_ime_util.h"
shuchen179b1f42014-11-27 17:24:4087#include "ui/base/ime/chromeos/input_method_manager.h"
[email protected]1dfebfc2013-06-04 03:14:3288#include "ui/base/resource/resource_bundle.h"
[email protected]e1b299b2014-01-29 23:53:4189#include "ui/keyboard/keyboard_controller.h"
90#include "ui/keyboard/keyboard_util.h"
Scott Violet66193f72017-06-26 22:24:1891#include "ui/views/widget/widget.h"
jamescook9eb0f912017-02-03 19:13:3992#include "ui/views/widget/widget_observer.h"
[email protected]1dfebfc2013-06-04 03:14:3293
[email protected]8c79e3f2013-10-30 01:05:1494using content::BrowserThread;
[email protected]8c79e3f2013-10-30 01:05:1495using extensions::api::braille_display_private::BrailleController;
96using extensions::api::braille_display_private::DisplayState;
[email protected]2e5e0b12014-05-07 13:30:2097using extensions::api::braille_display_private::KeyEvent;
plundbladcf1d08f2015-09-28 09:18:5898using extensions::api::braille_display_private::StubBrailleController;
[email protected]1dfebfc2013-06-04 03:14:3299
100namespace chromeos {
101
102namespace {
103
sadrulcdc2bb42016-07-13 19:44:51104// When this flag is set, system sounds will not be played.
Qiang Xu89af823e2017-12-05 04:04:47105constexpr char kAshDisableSystemSounds[] = "ash-disable-system-sounds";
sadrulcdc2bb42016-07-13 19:44:51106
Qiang Xu89af823e2017-12-05 04:04:47107static chromeos::AccessibilityManager* g_accessibility_manager = nullptr;
[email protected]1dfebfc2013-06-04 03:14:32108
Qiang Xu89af823e2017-12-05 04:04:47109static BrailleController* g_braille_controller_for_test = nullptr;
[email protected]8c79e3f2013-10-30 01:05:14110
111BrailleController* GetBrailleController() {
plundbladcf1d08f2015-09-28 09:18:58112 if (g_braille_controller_for_test)
113 return g_braille_controller_for_test;
114 // Don't use the real braille controller for tests to avoid automatically
115 // starting ChromeVox which confuses some tests.
116 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
Dominic Mazzonic85a5c92017-08-31 18:53:30117 if (command_line->HasSwitch(::switches::kTestType))
plundbladcf1d08f2015-09-28 09:18:58118 return StubBrailleController::GetInstance();
119 return BrailleController::GetInstance();
[email protected]8c79e3f2013-10-30 01:05:14120}
121
[email protected]1dfebfc2013-06-04 03:14:32122} // namespace
123
dmazzoni94a4f882015-11-13 05:46:52124class ChromeVoxPanelWidgetObserver : public views::WidgetObserver {
125 public:
126 ChromeVoxPanelWidgetObserver(views::Widget* widget,
127 AccessibilityManager* manager)
128 : widget_(widget), manager_(manager) {
129 widget_->AddObserver(this);
130 }
131
132 void OnWidgetClosing(views::Widget* widget) override {
133 CHECK_EQ(widget_, widget);
134 widget->RemoveObserver(this);
135 manager_->OnChromeVoxPanelClosing();
136 }
137
138 void OnWidgetDestroying(views::Widget* widget) override {
139 CHECK_EQ(widget_, widget);
140 widget->RemoveObserver(this);
141 manager_->OnChromeVoxPanelDestroying();
142 }
143
144 private:
145 views::Widget* widget_;
146 AccessibilityManager* manager_;
147
148 DISALLOW_COPY_AND_ASSIGN(ChromeVoxPanelWidgetObserver);
149};
150
David Tsengf84b652f2017-12-16 01:09:30151class ScopedKeyboardStateSetter {
152 public:
153 ScopedKeyboardStateSetter() : is_enabled_(keyboard::IsKeyboardEnabled()) {
154 keyboard::SetRequestedKeyboardState(keyboard::KEYBOARD_STATE_ENABLED);
155 }
156
157 ~ScopedKeyboardStateSetter() {
158 if (!is_enabled_)
159 keyboard::SetRequestedKeyboardState(keyboard::KEYBOARD_STATE_DISABLED);
160 }
161
162 private:
163 bool is_enabled_;
164
165 DISALLOW_COPY_AND_ASSIGN(ScopedKeyboardStateSetter);
166};
167
[email protected]1dfebfc2013-06-04 03:14:32168///////////////////////////////////////////////////////////////////////////////
169// AccessibilityStatusEventDetails
170
171AccessibilityStatusEventDetails::AccessibilityStatusEventDetails(
[email protected]d8edc9c2014-02-25 00:06:03172 AccessibilityNotificationType notification_type,
[email protected]1dfebfc2013-06-04 03:14:32173 bool enabled,
jamescooka7f8dab2016-06-21 01:44:03174 ash::AccessibilityNotificationVisibility notify)
James Cook12ccadd2017-10-09 03:53:34175 : notification_type(notification_type), enabled(enabled), notify(notify) {}
[email protected]1dfebfc2013-06-04 03:14:32176
177///////////////////////////////////////////////////////////////////////////////
[email protected]0aae2fe2013-07-05 07:04:42178// AccessibilityManager::PrefHandler
179
180AccessibilityManager::PrefHandler::PrefHandler(const char* pref_path)
181 : pref_path_(pref_path) {}
182
183AccessibilityManager::PrefHandler::~PrefHandler() {}
184
185void AccessibilityManager::PrefHandler::HandleProfileChanged(
James Cook12ccadd2017-10-09 03:53:34186 Profile* previous_profile,
187 Profile* current_profile) {
[email protected]0aae2fe2013-07-05 07:04:42188 // Returns if the current profile is null.
189 if (!current_profile)
190 return;
191
192 // If the user set a pref value on the login screen and is now starting a
193 // session with a new profile, copy the pref value to the profile.
James Cook12ccadd2017-10-09 03:53:34194 if ((previous_profile && ProfileHelper::IsSigninProfile(previous_profile) &&
[email protected]0aae2fe2013-07-05 07:04:42195 current_profile->IsNewProfile() &&
196 !ProfileHelper::IsSigninProfile(current_profile)) ||
197 // Special case for Guest mode:
198 // Guest mode launches a guest-mode browser process before session starts,
199 // so the previous profile is null.
James Cook12ccadd2017-10-09 03:53:34200 (!previous_profile && current_profile->IsGuestSession())) {
[email protected]0aae2fe2013-07-05 07:04:42201 // Returns if the pref has not been set by the user.
James Cook12ccadd2017-10-09 03:53:34202 const PrefService::Preference* pref =
203 ProfileHelper::GetSigninProfile()->GetPrefs()->FindPreference(
204 pref_path_);
[email protected]0aae2fe2013-07-05 07:04:42205 if (!pref || !pref->IsUserControlled())
206 return;
207
208 // Copy the pref value from the signin screen.
209 const base::Value* value_on_login = pref->GetValue();
210 PrefService* user_prefs = current_profile->GetPrefs();
211 user_prefs->Set(pref_path_, *value_on_login);
212 }
213}
214
215///////////////////////////////////////////////////////////////////////////////
216//
[email protected]1dfebfc2013-06-04 03:14:32217// AccessibilityManager
218
219// static
220void AccessibilityManager::Initialize() {
221 CHECK(g_accessibility_manager == NULL);
222 g_accessibility_manager = new AccessibilityManager();
223}
224
225// static
226void AccessibilityManager::Shutdown() {
227 CHECK(g_accessibility_manager);
228 delete g_accessibility_manager;
229 g_accessibility_manager = NULL;
230}
231
232// static
233AccessibilityManager* AccessibilityManager::Get() {
234 return g_accessibility_manager;
235}
236
[email protected]d80f19302013-06-07 13:12:14237AccessibilityManager::AccessibilityManager()
238 : profile_(NULL),
James Cookc63b9fd2017-08-18 18:48:32239 large_cursor_pref_handler_(ash::prefs::kAccessibilityLargeCursorEnabled),
240 sticky_keys_pref_handler_(ash::prefs::kAccessibilityStickyKeysEnabled),
241 spoken_feedback_pref_handler_(
242 ash::prefs::kAccessibilitySpokenFeedbackEnabled),
243 high_contrast_pref_handler_(
244 ash::prefs::kAccessibilityHighContrastEnabled),
245 autoclick_pref_handler_(ash::prefs::kAccessibilityAutoclickEnabled),
246 autoclick_delay_pref_handler_(ash::prefs::kAccessibilityAutoclickDelayMs),
[email protected]ced247a2014-06-13 19:14:19247 virtual_keyboard_pref_handler_(
James Cookc63b9fd2017-08-18 18:48:32248 ash::prefs::kAccessibilityVirtualKeyboardEnabled),
249 mono_audio_pref_handler_(ash::prefs::kAccessibilityMonoAudioEnabled),
250 caret_highlight_pref_handler_(
251 ash::prefs::kAccessibilityCaretHighlightEnabled),
dmazzoni756089a22016-03-15 23:55:16252 cursor_highlight_pref_handler_(
James Cookc63b9fd2017-08-18 18:48:32253 ash::prefs::kAccessibilityCursorHighlightEnabled),
254 focus_highlight_pref_handler_(
255 ash::prefs::kAccessibilityFocusHighlightEnabled),
minchd9d542482017-04-07 19:29:56256 tap_dragging_pref_handler_(prefs::kTapDraggingEnabled),
James Cookc63b9fd2017-08-18 18:48:32257 select_to_speak_pref_handler_(
258 ash::prefs::kAccessibilitySelectToSpeakEnabled),
259 switch_access_pref_handler_(
260 ash::prefs::kAccessibilitySwitchAccessEnabled),
[email protected]93a534e2013-06-20 16:41:44261 sticky_keys_enabled_(false),
Qiang(Joe) Xua0f644592017-12-01 02:16:50262 spoken_feedback_enabled_(false),
[email protected]186ba06bc2013-11-26 18:02:19263 autoclick_enabled_(false),
sammiequon820646f2016-06-24 18:47:13264 autoclick_delay_ms_(ash::AutoclickController::GetDefaultAutoclickDelay()),
[email protected]e1b299b2014-01-29 23:53:41265 virtual_keyboard_enabled_(false),
dmazzoni756089a22016-03-15 23:55:16266 caret_highlight_enabled_(false),
267 cursor_highlight_enabled_(false),
268 focus_highlight_enabled_(false),
minchd9d542482017-04-07 19:29:56269 tap_dragging_enabled_(false),
dmazzoni756089a22016-03-15 23:55:16270 select_to_speak_enabled_(false),
271 switch_access_enabled_(false),
jamescooka7f8dab2016-06-21 01:44:03272 spoken_feedback_notification_(ash::A11Y_NOTIFICATION_NONE),
[email protected]a81b2c32014-03-28 06:35:01273 braille_display_connected_(false),
[email protected]2e5e0b12014-05-07 13:30:20274 scoped_braille_observer_(this),
anand.ratn04aae9ef2014-09-16 04:16:51275 braille_ime_current_(false),
dmazzoni94a4f882015-11-13 05:46:52276 chromevox_panel_(nullptr),
dtsengfb6d7cd2016-01-20 23:00:13277 extension_registry_observer_(this),
anand.ratn04aae9ef2014-09-16 04:16:51278 weak_ptr_factory_(this) {
[email protected]1dfebfc2013-06-04 03:14:32279 notification_registrar_.Add(this,
[email protected]093d9ba2013-07-23 19:26:21280 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
[email protected]e6f20642013-06-11 17:05:46281 content::NotificationService::AllSources());
282 notification_registrar_.Add(this,
Yuki Awanod59b6492017-07-28 00:52:11283 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
284 content::NotificationService::AllSources());
James Cook12ccadd2017-10-09 03:53:34285 notification_registrar_.Add(this, chrome::NOTIFICATION_SESSION_STARTED,
[email protected]1dfebfc2013-06-04 03:14:32286 content::NotificationService::AllSources());
James Cook12ccadd2017-10-09 03:53:34287 notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
[email protected]1dfebfc2013-06-04 03:14:32288 content::NotificationService::AllSources());
[email protected]c20122572013-12-16 20:35:58289
[email protected]1488a035f2014-03-28 21:12:07290 input_method::InputMethodManager::Get()->AddObserver(this);
tbarziccd5ad222017-03-24 04:46:31291 session_manager::SessionManager::Get()->AddObserver(this);
[email protected]1488a035f2014-03-28 21:12:07292
[email protected]12b0a842013-12-04 20:48:13293 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
[email protected]ce89d9392013-12-11 21:05:20294 media::SoundsManager* manager = media::SoundsManager::Get();
295 manager->Initialize(SOUND_SHUTDOWN,
296 bundle.GetRawDataResource(IDR_SOUND_SHUTDOWN_WAV));
297 manager->Initialize(
298 SOUND_SPOKEN_FEEDBACK_ENABLED,
299 bundle.GetRawDataResource(IDR_SOUND_SPOKEN_FEEDBACK_ENABLED_WAV));
300 manager->Initialize(
301 SOUND_SPOKEN_FEEDBACK_DISABLED,
302 bundle.GetRawDataResource(IDR_SOUND_SPOKEN_FEEDBACK_DISABLED_WAV));
[email protected]07f3ea92014-08-14 05:23:38303 manager->Initialize(SOUND_PASSTHROUGH,
304 bundle.GetRawDataResource(IDR_SOUND_PASSTHROUGH_WAV));
305 manager->Initialize(SOUND_EXIT_SCREEN,
306 bundle.GetRawDataResource(IDR_SOUND_EXIT_SCREEN_WAV));
307 manager->Initialize(SOUND_ENTER_SCREEN,
308 bundle.GetRawDataResource(IDR_SOUND_ENTER_SCREEN_WAV));
dmazzoni16d2dec2016-12-19 23:27:57309 manager->Initialize(SOUND_SPOKEN_FEEDBACK_TOGGLE_COUNTDOWN_HIGH,
310 bundle.GetRawDataResource(
311 IDR_SOUND_SPOKEN_FEEDBACK_TOGGLE_COUNTDOWN_HIGH_WAV));
312 manager->Initialize(SOUND_SPOKEN_FEEDBACK_TOGGLE_COUNTDOWN_LOW,
313 bundle.GetRawDataResource(
314 IDR_SOUND_SPOKEN_FEEDBACK_TOGGLE_COUNTDOWN_LOW_WAV));
David Tseng580f050e2017-09-05 21:18:41315 manager->Initialize(SOUND_TOUCH_TYPE,
316 bundle.GetRawDataResource(IDR_SOUND_TOUCH_TYPE_WAV));
dmazzoni337c5af2016-09-13 23:08:57317
318 base::FilePath resources_path;
319 if (!PathService::Get(chrome::DIR_RESOURCES, &resources_path))
320 NOTREACHED();
321 chromevox_loader_ = base::WrapUnique(new AccessibilityExtensionLoader(
322 extension_misc::kChromeVoxExtensionId,
323 resources_path.Append(extension_misc::kChromeVoxExtensionPath),
324 base::Bind(&AccessibilityManager::PostUnloadChromeVox,
325 weak_ptr_factory_.GetWeakPtr())));
dmazzoni5288b2612016-09-16 23:05:39326 select_to_speak_loader_ = base::WrapUnique(new AccessibilityExtensionLoader(
327 extension_misc::kSelectToSpeakExtensionId,
328 resources_path.Append(extension_misc::kSelectToSpeakExtensionPath),
329 base::Closure()));
elichtenberg0746c1bd2017-02-22 07:59:15330 switch_access_loader_ = base::WrapUnique(new AccessibilityExtensionLoader(
331 extension_misc::kSwitchAccessExtensionId,
332 resources_path.Append(extension_misc::kSwitchAccessExtensionPath),
333 base::Closure()));
[email protected]1dfebfc2013-06-04 03:14:32334}
335
336AccessibilityManager::~AccessibilityManager() {
337 CHECK(this == g_accessibility_manager);
jamescooka7f8dab2016-06-21 01:44:03338 AccessibilityStatusEventDetails details(ACCESSIBILITY_MANAGER_SHUTDOWN, false,
339 ash::A11Y_NOTIFICATION_NONE);
[email protected]d8edc9c2014-02-25 00:06:03340 NotifyAccessibilityStatusChanged(details);
[email protected]1488a035f2014-03-28 21:12:07341 input_method::InputMethodManager::Get()->RemoveObserver(this);
tbarziccd5ad222017-03-24 04:46:31342 session_manager::SessionManager::Get()->RemoveObserver(this);
dmazzoni94a4f882015-11-13 05:46:52343
344 if (chromevox_panel_) {
345 chromevox_panel_->Close();
346 chromevox_panel_ = nullptr;
347 }
[email protected]1dfebfc2013-06-04 03:14:32348}
349
[email protected]c20122572013-12-16 20:35:58350bool AccessibilityManager::ShouldShowAccessibilityMenu() {
351 // If any of the loaded profiles has an accessibility feature turned on - or
352 // enforced to always show the menu - we return true to show the menu.
James Cookfc97f0a2017-08-16 20:05:35353 // NOTE: This includes the login screen profile, so if a feature is turned on
354 // at the login screen the menu will show even if the user has no features
355 // enabled inside the session. http://crbug.com/755631
[email protected]c20122572013-12-16 20:35:58356 std::vector<Profile*> profiles =
357 g_browser_process->profile_manager()->GetLoadedProfiles();
358 for (std::vector<Profile*>::iterator it = profiles.begin();
James Cook12ccadd2017-10-09 03:53:34359 it != profiles.end(); ++it) {
James Cookc63b9fd2017-08-18 18:48:32360 PrefService* prefs = (*it)->GetPrefs();
361 if (prefs->GetBoolean(ash::prefs::kAccessibilityStickyKeysEnabled) ||
362 prefs->GetBoolean(ash::prefs::kAccessibilityLargeCursorEnabled) ||
363 prefs->GetBoolean(ash::prefs::kAccessibilitySpokenFeedbackEnabled) ||
364 prefs->GetBoolean(ash::prefs::kAccessibilityHighContrastEnabled) ||
365 prefs->GetBoolean(ash::prefs::kAccessibilityAutoclickEnabled) ||
366 prefs->GetBoolean(ash::prefs::kShouldAlwaysShowAccessibilityMenu) ||
367 prefs->GetBoolean(ash::prefs::kAccessibilityScreenMagnifierEnabled) ||
368 prefs->GetBoolean(ash::prefs::kAccessibilityVirtualKeyboardEnabled) ||
369 prefs->GetBoolean(ash::prefs::kAccessibilityMonoAudioEnabled) ||
370 prefs->GetBoolean(ash::prefs::kAccessibilityCaretHighlightEnabled) ||
371 prefs->GetBoolean(ash::prefs::kAccessibilityCursorHighlightEnabled) ||
372 prefs->GetBoolean(ash::prefs::kAccessibilityFocusHighlightEnabled) ||
373 prefs->GetBoolean(prefs::kTapDraggingEnabled))
[email protected]c20122572013-12-16 20:35:58374 return true;
375 }
376 return false;
377}
378
James Cookfc97f0a2017-08-16 20:05:35379void AccessibilityManager::UpdateAlwaysShowMenuFromPref() {
380 if (!profile_)
381 return;
382
James Cook696fb106a2017-08-17 21:50:44383 // TODO(crbug.com/594887): Fix for mash by moving pref into ash.
384 if (GetAshConfig() == ash::Config::MASH)
385 return;
386
James Cookfc97f0a2017-08-16 20:05:35387 // Update system tray menu visibility.
James Cookc46731e2017-08-16 23:39:22388 ash::Shell::Get()->system_tray_notifier()->NotifyAccessibilityStatusChanged(
James Cookfc97f0a2017-08-16 20:05:35389 ash::A11Y_NOTIFICATION_NONE);
390}
391
[email protected]8126b812013-06-06 03:49:17392void AccessibilityManager::EnableLargeCursor(bool enabled) {
[email protected]d80f19302013-06-07 13:12:14393 if (!profile_)
394 return;
395
396 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32397 pref_service->SetBoolean(ash::prefs::kAccessibilityLargeCursorEnabled,
398 enabled);
[email protected]d80f19302013-06-07 13:12:14399 pref_service->CommitPendingWrite();
400}
401
James Cook9f9ff79d32017-09-01 00:39:29402void AccessibilityManager::OnLargeCursorChanged() {
jamescooka7f8dab2016-06-21 01:44:03403 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_LARGE_CURSOR,
James Cook9f9ff79d32017-09-01 00:39:29404 IsLargeCursorEnabled(),
405 ash::A11Y_NOTIFICATION_NONE);
[email protected]d8edc9c2014-02-25 00:06:03406 NotifyAccessibilityStatusChanged(details);
[email protected]8126b812013-06-06 03:49:17407}
408
minch0bfec0b2017-04-10 17:50:09409bool AccessibilityManager::IsLargeCursorEnabled() const {
James Cook9f9ff79d32017-09-01 00:39:29410 return profile_ && profile_->GetPrefs()->GetBoolean(
411 ash::prefs::kAccessibilityLargeCursorEnabled);
[email protected]8126b812013-06-06 03:49:17412}
413
[email protected]93a534e2013-06-20 16:41:44414void AccessibilityManager::EnableStickyKeys(bool enabled) {
415 if (!profile_)
416 return;
417 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32418 pref_service->SetBoolean(ash::prefs::kAccessibilityStickyKeysEnabled,
419 enabled);
[email protected]93a534e2013-06-20 16:41:44420 pref_service->CommitPendingWrite();
421}
422
minch0bfec0b2017-04-10 17:50:09423bool AccessibilityManager::IsStickyKeysEnabled() const {
[email protected]93a534e2013-06-20 16:41:44424 return sticky_keys_enabled_;
425}
426
427void AccessibilityManager::UpdateStickyKeysFromPref() {
428 if (!profile_)
429 return;
430
James Cookc63b9fd2017-08-18 18:48:32431 const bool enabled = profile_->GetPrefs()->GetBoolean(
432 ash::prefs::kAccessibilityStickyKeysEnabled);
[email protected]93a534e2013-06-20 16:41:44433
434 if (sticky_keys_enabled_ == enabled)
435 return;
436
437 sticky_keys_enabled_ = enabled;
minchd9d542482017-04-07 19:29:56438
439 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_STICKY_KEYS,
440 enabled, ash::A11Y_NOTIFICATION_NONE);
441 NotifyAccessibilityStatusChanged(details);
James Cook696fb106a2017-08-17 21:50:44442
443 // TODO(crbug.com/594887): Fix for mash by moving pref into ash.
444 if (GetAshConfig() == ash::Config::MASH)
445 return;
446
skycb4be5b2017-04-06 17:52:45447 ash::Shell::Get()->sticky_keys_controller()->Enable(enabled);
[email protected]93a534e2013-06-20 16:41:44448}
449
[email protected]1dfebfc2013-06-04 03:14:32450void AccessibilityManager::EnableSpokenFeedback(
451 bool enabled,
jamescooka7f8dab2016-06-21 01:44:03452 ash::AccessibilityNotificationVisibility notify) {
[email protected]1dfebfc2013-06-04 03:14:32453 if (!profile_)
454 return;
[email protected]5d2ea362013-12-13 08:10:18455
[email protected]d80f19302013-06-07 13:12:14456 spoken_feedback_notification_ = notify;
457
[email protected]1dfebfc2013-06-04 03:14:32458 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32459 pref_service->SetBoolean(ash::prefs::kAccessibilitySpokenFeedbackEnabled,
460 enabled);
[email protected]1dfebfc2013-06-04 03:14:32461 pref_service->CommitPendingWrite();
[email protected]d80f19302013-06-07 13:12:14462
jamescooka7f8dab2016-06-21 01:44:03463 spoken_feedback_notification_ = ash::A11Y_NOTIFICATION_NONE;
[email protected]d80f19302013-06-07 13:12:14464}
465
Qiang(Joe) Xua0f644592017-12-01 02:16:50466void AccessibilityManager::UpdateSpokenFeedbackFromPref() {
[email protected]d80f19302013-06-07 13:12:14467 if (!profile_)
468 return;
469
[email protected]ced247a2014-06-13 19:14:19470 const bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32471 ash::prefs::kAccessibilitySpokenFeedbackEnabled);
[email protected]d80f19302013-06-07 13:12:14472
dmazzoni63199b12016-10-19 15:44:36473 if (enabled) {
474 chromevox_loader_->SetProfile(
475 profile_, base::Bind(&AccessibilityManager::PostSwitchChromeVoxProfile,
476 weak_ptr_factory_.GetWeakPtr()));
477 }
dmazzoni2c013202016-09-07 19:59:37478
Qiang(Joe) Xua0f644592017-12-01 02:16:50479 if (spoken_feedback_enabled_ == enabled)
480 return;
481
482 spoken_feedback_enabled_ = enabled;
483
James Cook12ccadd2017-10-09 03:53:34484 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK,
485 enabled,
486 spoken_feedback_notification_);
[email protected]d8edc9c2014-02-25 00:06:03487
488 NotifyAccessibilityStatusChanged(details);
[email protected]1dfebfc2013-06-04 03:14:32489
[email protected]0e9504d2013-11-05 02:33:29490 if (enabled) {
dtseng4702f8e2017-01-11 18:54:12491 chromevox_loader_->Load(profile_,
dmazzoni337c5af2016-09-13 23:08:57492 base::Bind(&AccessibilityManager::PostLoadChromeVox,
493 weak_ptr_factory_.GetWeakPtr()));
[email protected]0e9504d2013-11-05 02:33:29494 } else {
dmazzoni337c5af2016-09-13 23:08:57495 chromevox_loader_->Unload();
[email protected]0e9504d2013-11-05 02:33:29496 }
[email protected]2e5e0b12014-05-07 13:30:20497 UpdateBrailleImeState();
dmazzoni1970d4e62016-06-16 23:46:34498
499 // ChromeVox focus highlighting overrides the other focus highlighting.
500 UpdateFocusHighlightFromPref();
[email protected]b0a2ce32013-07-23 15:24:53501}
502
minch0bfec0b2017-04-10 17:50:09503bool AccessibilityManager::IsSpokenFeedbackEnabled() const {
Qiang(Joe) Xua0f644592017-12-01 02:16:50504 return spoken_feedback_enabled_;
505}
506
507void AccessibilityManager::ToggleSpokenFeedback(
508 ash::AccessibilityNotificationVisibility notify) {
509 EnableSpokenFeedback(!IsSpokenFeedbackEnabled(), notify);
[email protected]1dfebfc2013-06-04 03:14:32510}
511
[email protected]1dfebfc2013-06-04 03:14:32512void AccessibilityManager::EnableHighContrast(bool enabled) {
[email protected]d80f19302013-06-07 13:12:14513 if (!profile_)
514 return;
515
516 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32517 pref_service->SetBoolean(ash::prefs::kAccessibilityHighContrastEnabled,
518 enabled);
[email protected]d80f19302013-06-07 13:12:14519 pref_service->CommitPendingWrite();
520}
521
James Cook5fbdccb2017-09-01 21:17:55522bool AccessibilityManager::IsHighContrastEnabled() const {
523 return profile_ && profile_->GetPrefs()->GetBoolean(
524 ash::prefs::kAccessibilityHighContrastEnabled);
525}
[email protected]d80f19302013-06-07 13:12:14526
James Cook5fbdccb2017-09-01 21:17:55527void AccessibilityManager::OnHighContrastChanged() {
[email protected]d8edc9c2014-02-25 00:06:03528 AccessibilityStatusEventDetails details(
James Cook5fbdccb2017-09-01 21:17:55529 ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE, IsHighContrastEnabled(),
jamescooka7f8dab2016-06-21 01:44:03530 ash::A11Y_NOTIFICATION_NONE);
[email protected]d8edc9c2014-02-25 00:06:03531 NotifyAccessibilityStatusChanged(details);
[email protected]1dfebfc2013-06-04 03:14:32532}
533
[email protected]628b8902014-03-12 05:26:41534void AccessibilityManager::OnLocaleChanged() {
[email protected]d1d5f4f2013-06-14 07:17:09535 if (!profile_)
536 return;
537
538 if (!IsSpokenFeedbackEnabled())
539 return;
540
541 // If the system locale changes and spoken feedback is enabled,
542 // reload ChromeVox so that it switches its internal translations
543 // to the new language.
jamescooka7f8dab2016-06-21 01:44:03544 EnableSpokenFeedback(false, ash::A11Y_NOTIFICATION_NONE);
545 EnableSpokenFeedback(true, ash::A11Y_NOTIFICATION_NONE);
[email protected]d1d5f4f2013-06-14 07:17:09546}
547
yawanoca05a1af2017-01-25 02:38:17548void AccessibilityManager::OnViewFocusedInArc(
549 const gfx::Rect& bounds_in_screen) {
550 accessibility_highlight_manager_->OnViewFocusedInArc(bounds_in_screen);
551}
552
sadrulcdc2bb42016-07-13 19:44:51553bool AccessibilityManager::PlayEarcon(int sound_key, PlaySoundOption option) {
[email protected]07f3ea92014-08-14 05:23:38554 DCHECK(sound_key < chromeos::SOUND_COUNT);
sadrulcdc2bb42016-07-13 19:44:51555 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
556 if (cl->HasSwitch(kAshDisableSystemSounds))
557 return false;
Qiang Xu89af823e2017-12-05 04:04:47558 if (option == PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED &&
David Tseng89850d12017-08-29 02:23:41559 !IsSpokenFeedbackEnabled()) {
sadrulcdc2bb42016-07-13 19:44:51560 return false;
561 }
562 return media::SoundsManager::Get()->Play(sound_key);
[email protected]07f3ea92014-08-14 05:23:38563}
564
dmazzonidf9a1e922017-04-13 05:10:44565void AccessibilityManager::OnTwoFingerTouchStart() {
dmazzonic613a562017-05-02 03:19:19566 if (!profile())
567 return;
568
dmazzonidf9a1e922017-04-13 05:10:44569 extensions::EventRouter* event_router =
570 extensions::EventRouter::Get(profile());
571 CHECK(event_router);
572
573 auto event_args = base::MakeUnique<base::ListValue>();
574 auto event = base::MakeUnique<extensions::Event>(
575 extensions::events::ACCESSIBILITY_PRIVATE_ON_TWO_FINGER_TOUCH_START,
576 extensions::api::accessibility_private::OnTwoFingerTouchStart::kEventName,
577 std::move(event_args));
578 event_router->BroadcastEvent(std::move(event));
579}
580
581void AccessibilityManager::OnTwoFingerTouchStop() {
dmazzonic613a562017-05-02 03:19:19582 if (!profile())
583 return;
584
dmazzonidf9a1e922017-04-13 05:10:44585 extensions::EventRouter* event_router =
586 extensions::EventRouter::Get(profile());
587 CHECK(event_router);
588
589 auto event_args = base::MakeUnique<base::ListValue>();
590 auto event = base::MakeUnique<extensions::Event>(
591 extensions::events::ACCESSIBILITY_PRIVATE_ON_TWO_FINGER_TOUCH_STOP,
592 extensions::api::accessibility_private::OnTwoFingerTouchStop::kEventName,
593 std::move(event_args));
594 event_router->BroadcastEvent(std::move(event));
595}
596
dmazzoni16d2dec2016-12-19 23:27:57597bool AccessibilityManager::ShouldToggleSpokenFeedbackViaTouch() {
dmazzoni200099c2017-01-31 23:21:40598#if 1
599 // Temporarily disabling this feature until UI feedback is fixed.
600 // http://crbug.com/662501
601 return false;
602#else
dmazzoni16d2dec2016-12-19 23:27:57603 policy::BrowserPolicyConnectorChromeOS* connector =
604 g_browser_process->platform_part()->browser_policy_connector_chromeos();
605 if (!connector)
606 return false;
607
608 if (!connector->IsEnterpriseManaged())
609 return false;
610
611 const policy::DeviceCloudPolicyManagerChromeOS* const
612 device_cloud_policy_manager = connector->GetDeviceCloudPolicyManager();
613 if (!device_cloud_policy_manager)
614 return false;
615
616 if (!device_cloud_policy_manager->IsRemoraRequisition())
617 return false;
618
619 KioskAppManager* manager = KioskAppManager::Get();
620 KioskAppManager::App app;
621 CHECK(manager->GetApp(manager->GetAutoLaunchApp(), &app));
622 return app.was_auto_launched_with_zero_delay;
dmazzoni200099c2017-01-31 23:21:40623#endif
dmazzoni16d2dec2016-12-19 23:27:57624}
625
626bool AccessibilityManager::PlaySpokenFeedbackToggleCountdown(int tick_count) {
627 return media::SoundsManager::Get()->Play(
628 tick_count % 2 ? SOUND_SPOKEN_FEEDBACK_TOGGLE_COUNTDOWN_HIGH
629 : SOUND_SPOKEN_FEEDBACK_TOGGLE_COUNTDOWN_LOW);
630}
631
Qiang Xu9e12fa762017-12-19 03:27:49632void AccessibilityManager::HandleAccessibilityGesture(
633 const std::string& gesture) {
dmazzoni82ef29a2016-05-10 23:37:51634 extensions::EventRouter* event_router =
635 extensions::EventRouter::Get(profile());
636 CHECK(event_router);
637
638 std::unique_ptr<base::ListValue> event_args(new base::ListValue());
Qiang Xu9e12fa762017-12-19 03:27:49639 event_args->AppendString(gesture);
dmazzoni82ef29a2016-05-10 23:37:51640 std::unique_ptr<extensions::Event> event(new extensions::Event(
641 extensions::events::ACCESSIBILITY_PRIVATE_ON_ACCESSIBILITY_GESTURE,
642 extensions::api::accessibility_private::OnAccessibilityGesture::
643 kEventName,
644 std::move(event_args)));
645 event_router->DispatchEventWithLazyListener(
646 extension_misc::kChromeVoxExtensionId, std::move(event));
647}
648
dmazzoniff86e3472016-06-03 19:52:32649void AccessibilityManager::SetTouchAccessibilityAnchorPoint(
650 const gfx::Point& anchor_point) {
dmazzoni50f65802017-06-28 18:19:39651 for (auto* rwc : ash::RootWindowController::root_window_controllers())
652 rwc->SetTouchAccessibilityAnchorPoint(anchor_point);
dmazzoniff86e3472016-06-03 19:52:32653}
654
[email protected]1c881562013-10-12 07:52:58655void AccessibilityManager::EnableAutoclick(bool enabled) {
656 if (!profile_)
657 return;
658
659 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32660 pref_service->SetBoolean(ash::prefs::kAccessibilityAutoclickEnabled, enabled);
[email protected]1c881562013-10-12 07:52:58661 pref_service->CommitPendingWrite();
662}
663
minch0bfec0b2017-04-10 17:50:09664bool AccessibilityManager::IsAutoclickEnabled() const {
[email protected]1c881562013-10-12 07:52:58665 return autoclick_enabled_;
666}
667
668void AccessibilityManager::UpdateAutoclickFromPref() {
ginkagebda078c2014-12-15 14:24:53669 if (!profile_)
670 return;
671
James Cookc63b9fd2017-08-18 18:48:32672 bool enabled = profile_->GetPrefs()->GetBoolean(
673 ash::prefs::kAccessibilityAutoclickEnabled);
[email protected]1c881562013-10-12 07:52:58674
675 if (autoclick_enabled_ == enabled)
676 return;
677 autoclick_enabled_ = enabled;
678
James Cook696fb106a2017-08-17 21:50:44679 if (GetAshConfig() == ash::Config::MASH) {
rockot400ea35b2016-10-15 19:15:32680 service_manager::Connector* connector =
bend32292b2016-10-07 00:21:58681 content::ServiceManagerConnection::GetForProcess()->GetConnector();
riajiang4b626b972016-09-13 16:12:49682 mash::mojom::LaunchablePtr launchable;
benbd3c2482017-01-07 05:48:21683 connector->BindInterface("accessibility_autoclick", &launchable);
riajiang4b626b972016-09-13 16:12:49684 launchable->Launch(mash::mojom::kWindow, mash::mojom::LaunchMode::DEFAULT);
685 return;
686 }
687
James Cookc46731e2017-08-16 23:39:22688 ash::Shell::Get()->system_tray_notifier()->NotifyAccessibilityStatusChanged(
James Cookfc97f0a2017-08-16 20:05:35689 ash::A11Y_NOTIFICATION_NONE);
skycb4be5b2017-04-06 17:52:45690 ash::Shell::Get()->autoclick_controller()->SetEnabled(enabled);
[email protected]1c881562013-10-12 07:52:58691}
692
[email protected]84d652d2013-10-23 13:57:57693void AccessibilityManager::SetAutoclickDelay(int delay_ms) {
694 if (!profile_)
695 return;
696
697 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32698 pref_service->SetInteger(ash::prefs::kAccessibilityAutoclickDelayMs,
699 delay_ms);
[email protected]84d652d2013-10-23 13:57:57700 pref_service->CommitPendingWrite();
701}
702
703int AccessibilityManager::GetAutoclickDelay() const {
riajiang4b626b972016-09-13 16:12:49704 return static_cast<int>(autoclick_delay_ms_.InMilliseconds());
[email protected]84d652d2013-10-23 13:57:57705}
706
707void AccessibilityManager::UpdateAutoclickDelayFromPref() {
ginkagebda078c2014-12-15 14:24:53708 if (!profile_)
709 return;
710
sammiequon820646f2016-06-24 18:47:13711 base::TimeDelta autoclick_delay_ms = base::TimeDelta::FromMilliseconds(
712 int64_t{profile_->GetPrefs()->GetInteger(
James Cookc63b9fd2017-08-18 18:48:32713 ash::prefs::kAccessibilityAutoclickDelayMs)});
[email protected]84d652d2013-10-23 13:57:57714
715 if (autoclick_delay_ms == autoclick_delay_ms_)
716 return;
717 autoclick_delay_ms_ = autoclick_delay_ms;
718
James Cook696fb106a2017-08-17 21:50:44719 if (GetAshConfig() == ash::Config::MASH) {
rockot400ea35b2016-10-15 19:15:32720 service_manager::Connector* connector =
bend32292b2016-10-07 00:21:58721 content::ServiceManagerConnection::GetForProcess()->GetConnector();
riajiang4b626b972016-09-13 16:12:49722 ash::autoclick::mojom::AutoclickControllerPtr autoclick_controller;
benbd3c2482017-01-07 05:48:21723 connector->BindInterface("accessibility_autoclick", &autoclick_controller);
riajiang4b626b972016-09-13 16:12:49724 autoclick_controller->SetAutoclickDelay(
725 autoclick_delay_ms_.InMilliseconds());
726 return;
727 }
728
skycb4be5b2017-04-06 17:52:45729 ash::Shell::Get()->autoclick_controller()->SetAutoclickDelay(
[email protected]84d652d2013-10-23 13:57:57730 autoclick_delay_ms_);
[email protected]84d652d2013-10-23 13:57:57731}
732
[email protected]e1b299b2014-01-29 23:53:41733void AccessibilityManager::EnableVirtualKeyboard(bool enabled) {
734 if (!profile_)
735 return;
736
737 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32738 pref_service->SetBoolean(ash::prefs::kAccessibilityVirtualKeyboardEnabled,
[email protected]ced247a2014-06-13 19:14:19739 enabled);
[email protected]e1b299b2014-01-29 23:53:41740 pref_service->CommitPendingWrite();
741}
742
minch0bfec0b2017-04-10 17:50:09743bool AccessibilityManager::IsVirtualKeyboardEnabled() const {
[email protected]e1b299b2014-01-29 23:53:41744 return virtual_keyboard_enabled_;
745}
746
747void AccessibilityManager::UpdateVirtualKeyboardFromPref() {
748 if (!profile_)
749 return;
750
[email protected]ced247a2014-06-13 19:14:19751 const bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32752 ash::prefs::kAccessibilityVirtualKeyboardEnabled);
[email protected]e1b299b2014-01-29 23:53:41753
754 if (virtual_keyboard_enabled_ == enabled)
755 return;
756 virtual_keyboard_enabled_ = enabled;
757
[email protected]e1b299b2014-01-29 23:53:41758 keyboard::SetAccessibilityKeyboardEnabled(enabled);
James Cook696fb106a2017-08-17 21:50:44759 if (GetAshConfig() != ash::Config::MASH) {
msw15156bf2016-09-13 21:49:17760 // Note that there are two versions of the on-screen keyboard. A full layout
761 // is provided for accessibility, which includes sticky modifier keys to
Mitsuru Oshima63d3f2a2017-08-23 00:12:11762 // enable typing of hotkeys. A compact version is used in tablet mode
msw15156bf2016-09-13 21:49:17763 // to provide a layout with larger keys to facilitate touch typing. In the
764 // event that the a11y keyboard is being disabled, an on-screen keyboard
765 // might still be enabled and a forced reset is required to pick up the
766 // layout change.
767 if (keyboard::IsKeyboardEnabled())
skycb4be5b2017-04-06 17:52:45768 ash::Shell::Get()->CreateKeyboard();
msw15156bf2016-09-13 21:49:17769 else
Keigo Okac7617a42017-06-14 11:33:24770 ash::Shell::Get()->DestroyKeyboard();
msw15156bf2016-09-13 21:49:17771 } else {
772 // TODO(mash): Support on-screen keyboard. See http://crbug.com/646565
773 NOTIMPLEMENTED();
774 }
rsadama1104b82014-11-03 20:50:52775
jamescooka7f8dab2016-06-21 01:44:03776 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_VIRTUAL_KEYBOARD,
777 enabled, ash::A11Y_NOTIFICATION_NONE);
rsadama1104b82014-11-03 20:50:52778 NotifyAccessibilityStatusChanged(details);
[email protected]e1b299b2014-01-29 23:53:41779}
780
warx533c8f62016-04-12 01:19:43781void AccessibilityManager::EnableMonoAudio(bool enabled) {
782 if (!profile_)
783 return;
784
785 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32786 pref_service->SetBoolean(ash::prefs::kAccessibilityMonoAudioEnabled, enabled);
warx533c8f62016-04-12 01:19:43787 pref_service->CommitPendingWrite();
788}
789
minch0bfec0b2017-04-10 17:50:09790bool AccessibilityManager::IsMonoAudioEnabled() const {
Qiang Xu1ee98022017-11-21 19:52:55791 return profile_ && profile_->GetPrefs()->GetBoolean(
792 ash::prefs::kAccessibilityMonoAudioEnabled);
warx533c8f62016-04-12 01:19:43793}
794
Qiang Xu1ee98022017-11-21 19:52:55795void AccessibilityManager::OnMonoAudioChanged() {
jamescooka7f8dab2016-06-21 01:44:03796 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_MONO_AUDIO,
Qiang Xu1ee98022017-11-21 19:52:55797 IsMonoAudioEnabled(),
798 ash::A11Y_NOTIFICATION_NONE);
warx533c8f62016-04-12 01:19:43799 NotifyAccessibilityStatusChanged(details);
warx533c8f62016-04-12 01:19:43800}
801
Daniel Erat477c56d2017-12-13 21:42:54802void AccessibilityManager::SetDarkenScreen(bool darken) {
803 // TODO(mash): Support forcing backlights off from within Chrome:
804 // https://crbug.com/793112
805 if (GetAshConfig() == ash::Config::MASH)
806 return;
807
808 if (darken && !scoped_backlights_forced_off_) {
809 scoped_backlights_forced_off_ =
810 ash::Shell::Get()->backlights_forced_off_setter()->ForceBacklightsOff();
811 } else if (!darken && scoped_backlights_forced_off_) {
812 scoped_backlights_forced_off_.reset();
813 }
814}
815
dmazzoni756089a22016-03-15 23:55:16816void AccessibilityManager::SetCaretHighlightEnabled(bool enabled) {
817 if (!profile_)
818 return;
819
820 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32821 pref_service->SetBoolean(ash::prefs::kAccessibilityCaretHighlightEnabled,
822 enabled);
dmazzoni756089a22016-03-15 23:55:16823 pref_service->CommitPendingWrite();
824}
825
826bool AccessibilityManager::IsCaretHighlightEnabled() const {
827 return caret_highlight_enabled_;
828}
829
830void AccessibilityManager::UpdateCaretHighlightFromPref() {
831 if (!profile_)
832 return;
833
834 const bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32835 ash::prefs::kAccessibilityCaretHighlightEnabled);
dmazzoni756089a22016-03-15 23:55:16836
837 if (caret_highlight_enabled_ == enabled)
838 return;
839 caret_highlight_enabled_ = enabled;
840
mincha0b24ab2017-03-31 22:16:01841 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_CARET_HIGHLIGHT,
842 enabled, ash::A11Y_NOTIFICATION_NONE);
843 NotifyAccessibilityStatusChanged(details);
dmazzonib93107c2016-03-22 21:51:18844 UpdateAccessibilityHighlightingFromPrefs();
dmazzoni756089a22016-03-15 23:55:16845}
846
847void AccessibilityManager::SetCursorHighlightEnabled(bool enabled) {
848 if (!profile_)
849 return;
850
851 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32852 pref_service->SetBoolean(ash::prefs::kAccessibilityCursorHighlightEnabled,
dmazzoni756089a22016-03-15 23:55:16853 enabled);
854 pref_service->CommitPendingWrite();
855}
856
857bool AccessibilityManager::IsCursorHighlightEnabled() const {
858 return cursor_highlight_enabled_;
859}
860
861void AccessibilityManager::UpdateCursorHighlightFromPref() {
862 if (!profile_)
863 return;
864
865 const bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32866 ash::prefs::kAccessibilityCursorHighlightEnabled);
dmazzoni756089a22016-03-15 23:55:16867
868 if (cursor_highlight_enabled_ == enabled)
869 return;
870 cursor_highlight_enabled_ = enabled;
871
mincha0b24ab2017-03-31 22:16:01872 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_CURSOR_HIGHLIGHT,
873 enabled, ash::A11Y_NOTIFICATION_NONE);
874 NotifyAccessibilityStatusChanged(details);
dmazzonib93107c2016-03-22 21:51:18875 UpdateAccessibilityHighlightingFromPrefs();
dmazzoni756089a22016-03-15 23:55:16876}
877
878void AccessibilityManager::SetFocusHighlightEnabled(bool enabled) {
879 if (!profile_)
880 return;
881
882 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32883 pref_service->SetBoolean(ash::prefs::kAccessibilityFocusHighlightEnabled,
884 enabled);
dmazzoni756089a22016-03-15 23:55:16885 pref_service->CommitPendingWrite();
886}
887
888bool AccessibilityManager::IsFocusHighlightEnabled() const {
889 return focus_highlight_enabled_;
890}
891
892void AccessibilityManager::UpdateFocusHighlightFromPref() {
893 if (!profile_)
894 return;
895
dmazzoni42e4b002016-06-08 20:58:42896 bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32897 ash::prefs::kAccessibilityFocusHighlightEnabled);
dmazzoni756089a22016-03-15 23:55:16898
dmazzoni42e4b002016-06-08 20:58:42899 // Focus highlighting can't be on when spoken feedback is on, because
900 // ChromeVox does its own focus highlighting.
901 if (profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32902 ash::prefs::kAccessibilitySpokenFeedbackEnabled))
dmazzoni42e4b002016-06-08 20:58:42903 enabled = false;
904
dmazzoni756089a22016-03-15 23:55:16905 if (focus_highlight_enabled_ == enabled)
906 return;
907 focus_highlight_enabled_ = enabled;
908
mincha0b24ab2017-03-31 22:16:01909 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_FOCUS_HIGHLIGHT,
910 enabled, ash::A11Y_NOTIFICATION_NONE);
911 NotifyAccessibilityStatusChanged(details);
dmazzonib93107c2016-03-22 21:51:18912 UpdateAccessibilityHighlightingFromPrefs();
dmazzoni756089a22016-03-15 23:55:16913}
914
minchd9d542482017-04-07 19:29:56915void AccessibilityManager::EnableTapDragging(bool enabled) {
916 if (!profile_)
917 return;
918
919 PrefService* pref_service = profile_->GetPrefs();
920 pref_service->SetBoolean(prefs::kTapDraggingEnabled, enabled);
921 pref_service->CommitPendingWrite();
922}
923
minch0bfec0b2017-04-10 17:50:09924bool AccessibilityManager::IsTapDraggingEnabled() const {
minchd9d542482017-04-07 19:29:56925 return tap_dragging_enabled_;
926}
927
928void AccessibilityManager::UpdateTapDraggingFromPref() {
929 if (!profile_)
930 return;
931
932 const bool enabled =
933 profile_->GetPrefs()->GetBoolean(prefs::kTapDraggingEnabled);
934
935 if (tap_dragging_enabled_ == enabled)
936 return;
937 tap_dragging_enabled_ = enabled;
938
939 AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_TAP_DRAGGING,
940 enabled, ash::A11Y_NOTIFICATION_NONE);
941 NotifyAccessibilityStatusChanged(details);
942
943 system::TouchpadSettings touchpad_settings;
944 touchpad_settings.SetTapDragging(enabled);
945}
946
dmazzoni756089a22016-03-15 23:55:16947void AccessibilityManager::SetSelectToSpeakEnabled(bool enabled) {
948 if (!profile_)
949 return;
950
951 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32952 pref_service->SetBoolean(ash::prefs::kAccessibilitySelectToSpeakEnabled,
953 enabled);
dmazzoni756089a22016-03-15 23:55:16954 pref_service->CommitPendingWrite();
955}
956
957bool AccessibilityManager::IsSelectToSpeakEnabled() const {
958 return select_to_speak_enabled_;
959}
960
961void AccessibilityManager::UpdateSelectToSpeakFromPref() {
962 if (!profile_)
963 return;
964
965 const bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32966 ash::prefs::kAccessibilitySelectToSpeakEnabled);
dmazzoni756089a22016-03-15 23:55:16967
968 if (select_to_speak_enabled_ == enabled)
969 return;
970 select_to_speak_enabled_ = enabled;
971
Katie Dektar0c0f37952017-12-18 18:35:33972 if (enabled)
dtseng4702f8e2017-01-11 18:54:12973 select_to_speak_loader_->Load(profile_, base::Closure() /* done_cb */);
Katie Dektar0c0f37952017-12-18 18:35:33974 else
dmazzoni5288b2612016-09-16 23:05:39975 select_to_speak_loader_->Unload();
dmazzoni756089a22016-03-15 23:55:16976}
977
978void AccessibilityManager::SetSwitchAccessEnabled(bool enabled) {
979 if (!profile_)
980 return;
981
982 PrefService* pref_service = profile_->GetPrefs();
James Cookc63b9fd2017-08-18 18:48:32983 pref_service->SetBoolean(ash::prefs::kAccessibilitySwitchAccessEnabled,
984 enabled);
dmazzoni756089a22016-03-15 23:55:16985 pref_service->CommitPendingWrite();
986}
987
988bool AccessibilityManager::IsSwitchAccessEnabled() const {
989 return switch_access_enabled_;
990}
991
992void AccessibilityManager::UpdateSwitchAccessFromPref() {
993 if (!profile_)
994 return;
995
996 const bool enabled = profile_->GetPrefs()->GetBoolean(
James Cookc63b9fd2017-08-18 18:48:32997 ash::prefs::kAccessibilitySwitchAccessEnabled);
dmazzoni756089a22016-03-15 23:55:16998
Dominic Mazzonic85a5c92017-08-31 18:53:30999 // The Switch Access setting is behind a flag. Don't enable the feature
1000 // even if the preference is enabled, if the flag isn't also set.
1001 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
1002 if (!command_line->HasSwitch(
1003 chromeos::switches::kEnableExperimentalAccessibilityFeatures)) {
1004 if (enabled) {
1005 LOG(WARNING) << "Switch access enabled but experimental accessibility "
1006 << "features flag is not set.";
1007 }
1008 return;
1009 }
1010
dmazzoni756089a22016-03-15 23:55:161011 if (switch_access_enabled_ == enabled)
1012 return;
1013 switch_access_enabled_ = enabled;
1014
elichtenberg0746c1bd2017-02-22 07:59:151015 if (enabled) {
1016 switch_access_loader_->Load(profile_, base::Closure() /* done_cb */);
elichtenbergc4b4bf462017-02-28 20:48:101017 switch_access_event_handler_.reset(
1018 new chromeos::SwitchAccessEventHandler());
elichtenberg0746c1bd2017-02-22 07:59:151019 } else {
1020 switch_access_loader_->Unload();
elichtenbergc4b4bf462017-02-28 20:48:101021 switch_access_event_handler_.reset(nullptr);
elichtenberg0746c1bd2017-02-22 07:59:151022 }
dmazzoni756089a22016-03-15 23:55:161023}
1024
dmazzonib93107c2016-03-22 21:51:181025void AccessibilityManager::UpdateAccessibilityHighlightingFromPrefs() {
1026 if (!focus_highlight_enabled_ && !caret_highlight_enabled_ &&
1027 !cursor_highlight_enabled_) {
1028 if (accessibility_highlight_manager_)
1029 accessibility_highlight_manager_.reset();
1030 return;
1031 }
1032
dmazzoni7fb1f572016-06-18 00:06:171033 if (!accessibility_highlight_manager_) {
dmazzonib93107c2016-03-22 21:51:181034 accessibility_highlight_manager_.reset(new AccessibilityHighlightManager());
dmazzoni7fb1f572016-06-18 00:06:171035 accessibility_highlight_manager_->RegisterObservers();
1036 }
dmazzonib93107c2016-03-22 21:51:181037
1038 accessibility_highlight_manager_->HighlightFocus(focus_highlight_enabled_);
1039 accessibility_highlight_manager_->HighlightCaret(caret_highlight_enabled_);
1040 accessibility_highlight_manager_->HighlightCursor(cursor_highlight_enabled_);
1041}
1042
[email protected]a81b2c32014-03-28 06:35:011043bool AccessibilityManager::IsBrailleDisplayConnected() const {
1044 return braille_display_connected_;
1045}
1046
[email protected]8c79e3f2013-10-30 01:05:141047void AccessibilityManager::CheckBrailleState() {
[email protected]a81b2c32014-03-28 06:35:011048 BrailleController* braille_controller = GetBrailleController();
1049 if (!scoped_braille_observer_.IsObserving(braille_controller))
1050 scoped_braille_observer_.Add(braille_controller);
[email protected]8c79e3f2013-10-30 01:05:141051 BrowserThread::PostTaskAndReplyWithResult(
James Cook12ccadd2017-10-09 03:53:341052 BrowserThread::IO, FROM_HERE,
[email protected]a81b2c32014-03-28 06:35:011053 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 =
Qiang(Joe) Xua0f644592017-12-01 02:16:501078 (spoken_feedback_enabled_ && braille_display_connected_);
[email protected]2e5e0b12014-05-07 13:30:201079 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,
Qiang(Joe) Xua0f644592017-12-01 02:16:501155 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,
Qiang Xu1ee98022017-11-21 19:52:551175 base::Bind(&AccessibilityManager::OnMonoAudioChanged,
warx533c8f62016-04-12 01:19:431176 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(
James Cook12ccadd2017-10-09 03:53:341210 base::Bind(&AccessibilityManager::UpdateChromeOSAccessibilityHistograms,
1211 base::Unretained(this)));
dmazzoni337c5af2016-09-13 23:08:571212
dmazzoni337c5af2016-09-13 23:08:571213 extensions::ExtensionRegistry* registry =
1214 extensions::ExtensionRegistry::Get(profile);
1215 if (!extension_registry_observer_.IsObserving(registry))
1216 extension_registry_observer_.Add(registry);
[email protected]1dfebfc2013-06-04 03:14:321217 }
1218
[email protected]0aae2fe2013-07-05 07:04:421219 large_cursor_pref_handler_.HandleProfileChanged(profile_, profile);
1220 spoken_feedback_pref_handler_.HandleProfileChanged(profile_, profile);
1221 high_contrast_pref_handler_.HandleProfileChanged(profile_, profile);
minchd9d542482017-04-07 19:29:561222 sticky_keys_pref_handler_.HandleProfileChanged(profile_, profile);
[email protected]1c881562013-10-12 07:52:581223 autoclick_pref_handler_.HandleProfileChanged(profile_, profile);
[email protected]84d652d2013-10-23 13:57:571224 autoclick_delay_pref_handler_.HandleProfileChanged(profile_, profile);
[email protected]42b471f2014-01-31 20:31:291225 virtual_keyboard_pref_handler_.HandleProfileChanged(profile_, profile);
warx533c8f62016-04-12 01:19:431226 mono_audio_pref_handler_.HandleProfileChanged(profile_, profile);
dmazzoni756089a22016-03-15 23:55:161227 caret_highlight_pref_handler_.HandleProfileChanged(profile_, profile);
1228 cursor_highlight_pref_handler_.HandleProfileChanged(profile_, profile);
1229 focus_highlight_pref_handler_.HandleProfileChanged(profile_, profile);
minchd9d542482017-04-07 19:29:561230 tap_dragging_pref_handler_.HandleProfileChanged(profile_, profile);
dmazzoni756089a22016-03-15 23:55:161231 select_to_speak_pref_handler_.HandleProfileChanged(profile_, profile);
1232 switch_access_pref_handler_.HandleProfileChanged(profile_, profile);
[email protected]0aae2fe2013-07-05 07:04:421233
[email protected]a81b2c32014-03-28 06:35:011234 bool had_profile = (profile_ != NULL);
1235 profile_ = profile;
1236
1237 if (!had_profile && profile)
[email protected]8c79e3f2013-10-30 01:05:141238 CheckBrailleState();
[email protected]2e5e0b12014-05-07 13:30:201239 else
1240 UpdateBrailleImeState();
James Cookfc97f0a2017-08-16 20:05:351241 UpdateAlwaysShowMenuFromPref();
[email protected]93a534e2013-06-20 16:41:441242 UpdateStickyKeysFromPref();
Qiang(Joe) Xua0f644592017-12-01 02:16:501243 UpdateSpokenFeedbackFromPref();
[email protected]1c881562013-10-12 07:52:581244 UpdateAutoclickFromPref();
[email protected]84d652d2013-10-23 13:57:571245 UpdateAutoclickDelayFromPref();
[email protected]e1b299b2014-01-29 23:53:411246 UpdateVirtualKeyboardFromPref();
dmazzoni756089a22016-03-15 23:55:161247 UpdateCaretHighlightFromPref();
1248 UpdateCursorHighlightFromPref();
1249 UpdateFocusHighlightFromPref();
minchd9d542482017-04-07 19:29:561250 UpdateTapDraggingFromPref();
dmazzoni756089a22016-03-15 23:55:161251 UpdateSelectToSpeakFromPref();
1252 UpdateSwitchAccessFromPref();
dmazzoni39d6d4b2016-03-29 22:18:001253
1254 // Update the panel height in the shelf layout manager when the profile
1255 // changes, since the shelf layout manager doesn't exist in the login profile.
1256 if (chromevox_panel_)
1257 chromevox_panel_->UpdatePanelHeight();
[email protected]1dfebfc2013-06-04 03:14:321258}
1259
xiyuan5d8d3ba2017-03-01 21:34:401260void AccessibilityManager::ActiveUserChanged(
1261 const user_manager::User* active_user) {
xiyuan8c6a4112017-06-19 21:03:491262 if (active_user && active_user->is_profile_created())
1263 SetProfile(ProfileManager::GetActiveUserProfile());
[email protected]c20122572013-12-16 20:35:581264}
1265
varkhac71444e52017-05-25 22:51:341266void AccessibilityManager::OnFullscreenStateChanged(bool is_fullscreen,
1267 aura::Window* root_window) {
dmazzonid47388d2016-03-31 16:03:511268 if (chromevox_panel_)
1269 chromevox_panel_->UpdateWidgetBounds();
1270}
1271
[email protected]1dfebfc2013-06-04 03:14:321272void AccessibilityManager::SetProfileForTest(Profile* profile) {
1273 SetProfile(profile);
1274}
1275
[email protected]8c79e3f2013-10-30 01:05:141276void AccessibilityManager::SetBrailleControllerForTest(
1277 BrailleController* controller) {
1278 g_braille_controller_for_test = controller;
1279}
1280
[email protected]ce89d9392013-12-11 21:05:201281base::TimeDelta AccessibilityManager::PlayShutdownSound() {
Qiang Xu89af823e2017-12-05 04:04:471282 if (!PlayEarcon(SOUND_SHUTDOWN,
1283 PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED)) {
[email protected]4f011f12014-01-15 08:22:451284 return base::TimeDelta();
Qiang Xu89af823e2017-12-05 04:04:471285 }
[email protected]4f011f12014-01-15 08:22:451286 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 &&
Qiang Xu1ee98022017-11-21 19:52:551306 details.notification_type != ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE &&
1307 details.notification_type != ACCESSIBILITY_TOGGLE_LARGE_CURSOR &&
Qiang(Joe) Xua0f644592017-12-01 02:16:501308 details.notification_type != ACCESSIBILITY_TOGGLE_MONO_AUDIO) {
James Cookc46731e2017-08-16 23:39:221309 ash::Shell::Get()->system_tray_notifier()->NotifyAccessibilityStatusChanged(
James Cookfc97f0a2017-08-16 20:05:351310 details.notify);
1311 }
[email protected]d8edc9c2014-02-25 00:06:031312}
1313
[email protected]1dfebfc2013-06-04 03:14:321314void AccessibilityManager::UpdateChromeOSAccessibilityHistograms() {
1315 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosSpokenFeedback",
1316 IsSpokenFeedbackEnabled());
1317 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosHighContrast",
1318 IsHighContrastEnabled());
1319 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosVirtualKeyboard",
[email protected]e1b299b2014-01-29 23:53:411320 IsVirtualKeyboardEnabled());
[email protected]7fb7ea42014-02-12 21:19:311321 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosStickyKeys", IsStickyKeysEnabled());
[email protected]1dfebfc2013-06-04 03:14:321322 if (MagnificationManager::Get()) {
James Cookdb81c7672017-08-30 15:18:241323 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosScreenMagnifier",
1324 MagnificationManager::Get()->IsMagnifierEnabled());
[email protected]1dfebfc2013-06-04 03:14:321325 }
[email protected]ca3a0a82013-06-18 06:52:121326 if (profile_) {
1327 const PrefService* const prefs = profile_->GetPrefs();
yawano0c3441c72017-04-11 01:09:161328
1329 bool large_cursor_enabled =
James Cookc63b9fd2017-08-18 18:48:321330 prefs->GetBoolean(ash::prefs::kAccessibilityLargeCursorEnabled);
yawano0c3441c72017-04-11 01:09:161331 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosLargeCursor",
1332 large_cursor_enabled);
yawano92daff52017-04-21 06:34:281333 if (large_cursor_enabled) {
yawano0c3441c72017-04-11 01:09:161334 UMA_HISTOGRAM_COUNTS_100(
1335 "Accessibility.CrosLargeCursorSize",
James Cookc63b9fd2017-08-18 18:48:321336 prefs->GetInteger(ash::prefs::kAccessibilityLargeCursorDipSize));
yawano0c3441c72017-04-11 01:09:161337 }
1338
[email protected]ca3a0a82013-06-18 06:52:121339 UMA_HISTOGRAM_BOOLEAN(
1340 "Accessibility.CrosAlwaysShowA11yMenu",
James Cookc63b9fd2017-08-18 18:48:321341 prefs->GetBoolean(ash::prefs::kShouldAlwaysShowAccessibilityMenu));
[email protected]0b5a0d2b2013-10-30 03:43:401342
[email protected]ced247a2014-06-13 19:14:191343 bool autoclick_enabled =
James Cookc63b9fd2017-08-18 18:48:321344 prefs->GetBoolean(ash::prefs::kAccessibilityAutoclickEnabled);
[email protected]0b5a0d2b2013-10-30 03:43:401345 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosAutoclick", autoclick_enabled);
1346 if (autoclick_enabled) {
1347 // We only want to log the autoclick delay if the user has actually
1348 // enabled autoclick.
1349 UMA_HISTOGRAM_CUSTOM_TIMES(
1350 "Accessibility.CrosAutoclickDelay",
1351 base::TimeDelta::FromMilliseconds(
James Cookc63b9fd2017-08-18 18:48:321352 prefs->GetInteger(ash::prefs::kAccessibilityAutoclickDelayMs)),
[email protected]0b5a0d2b2013-10-30 03:43:401353 base::TimeDelta::FromMilliseconds(1),
James Cookc63b9fd2017-08-18 18:48:321354 base::TimeDelta::FromMilliseconds(3000), 50);
[email protected]0b5a0d2b2013-10-30 03:43:401355 }
[email protected]ca3a0a82013-06-18 06:52:121356 }
dmazzoni756089a22016-03-15 23:55:161357 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosCaretHighlight",
1358 IsCaretHighlightEnabled());
1359 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosCursorHighlight",
1360 IsCursorHighlightEnabled());
1361 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosFocusHighlight",
1362 IsFocusHighlightEnabled());
1363 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosSelectToSpeak",
1364 IsSelectToSpeakEnabled());
1365 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosSwitchAccess",
1366 IsSwitchAccessEnabled());
[email protected]1dfebfc2013-06-04 03:14:321367}
1368
1369void AccessibilityManager::Observe(
1370 int type,
1371 const content::NotificationSource& source,
1372 const content::NotificationDetails& details) {
1373 switch (type) {
[email protected]093d9ba2013-07-23 19:26:211374 case chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE: {
[email protected]9cf54f362013-07-01 07:28:121375 // Update |profile_| when entering the login screen.
[email protected]c20122572013-12-16 20:35:581376 Profile* profile = ProfileManager::GetActiveUserProfile();
[email protected]d888cdc2013-06-24 17:06:201377 if (ProfileHelper::IsSigninProfile(profile))
1378 SetProfile(profile);
[email protected]1dfebfc2013-06-04 03:14:321379 break;
[email protected]d888cdc2013-06-24 17:06:201380 }
Yuki Awanod59b6492017-07-28 00:52:111381 case chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED:
1382 // Update |profile_| when login user profile is prepared.
1383 // NOTIFICATION_SESSION_STARTED is not fired from UserSessionManager, but
1384 // profile may be changed by UserSessionManager in OOBE flow.
1385 SetProfile(ProfileManager::GetActiveUserProfile());
1386 break;
[email protected]e6f20642013-06-11 17:05:461387 case chrome::NOTIFICATION_SESSION_STARTED:
1388 // Update |profile_| when entering a session.
[email protected]c20122572013-12-16 20:35:581389 SetProfile(ProfileManager::GetActiveUserProfile());
[email protected]0e9504d2013-11-05 02:33:291390
[email protected]c20122572013-12-16 20:35:581391 // Add a session state observer to be able to monitor session changes.
xiyuan5d8d3ba2017-03-01 21:34:401392 if (!session_state_observer_.get())
[email protected]c20122572013-12-16 20:35:581393 session_state_observer_.reset(
xiyuan5d8d3ba2017-03-01 21:34:401394 new user_manager::ScopedUserSessionStateObserver(this));
[email protected]1dfebfc2013-06-04 03:14:321395 break;
[email protected]1dfebfc2013-06-04 03:14:321396 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
[email protected]e6f20642013-06-11 17:05:461397 // Update |profile_| when exiting a session or shutting down.
1398 Profile* profile = content::Source<Profile>(source).ptr();
1399 if (profile_ == profile)
1400 SetProfile(NULL);
[email protected]1dfebfc2013-06-04 03:14:321401 break;
1402 }
[email protected]1dfebfc2013-06-04 03:14:321403 }
1404}
1405
[email protected]2e5e0b12014-05-07 13:30:201406void AccessibilityManager::OnBrailleDisplayStateChanged(
[email protected]8c79e3f2013-10-30 01:05:141407 const DisplayState& display_state) {
[email protected]a81b2c32014-03-28 06:35:011408 braille_display_connected_ = display_state.available;
[email protected]2e5e0b12014-05-07 13:30:201409 if (braille_display_connected_) {
Qiang(Joe) Xua0f644592017-12-01 02:16:501410 EnableSpokenFeedback(true, ash::A11Y_NOTIFICATION_SHOW);
[email protected]2e5e0b12014-05-07 13:30:201411 }
1412 UpdateBrailleImeState();
[email protected]a81b2c32014-03-28 06:35:011413
1414 AccessibilityStatusEventDetails details(
1415 ACCESSIBILITY_BRAILLE_DISPLAY_CONNECTION_STATE_CHANGED,
jamescooka7f8dab2016-06-21 01:44:031416 braille_display_connected_, ash::A11Y_NOTIFICATION_SHOW);
[email protected]a81b2c32014-03-28 06:35:011417 NotifyAccessibilityStatusChanged(details);
[email protected]8c79e3f2013-10-30 01:05:141418}
[email protected]0e9504d2013-11-05 02:33:291419
[email protected]2e5e0b12014-05-07 13:30:201420void AccessibilityManager::OnBrailleKeyEvent(const KeyEvent& event) {
1421 // Ensure the braille IME is active on braille keyboard (dots) input.
1422 if ((event.command ==
1423 extensions::api::braille_display_private::KEY_COMMAND_DOTS) &&
1424 !braille_ime_current_) {
[email protected]f0881cf2014-08-15 23:31:421425 input_method::InputMethodManager::Get()
1426 ->GetActiveIMEState()
jamescook2d60f032017-06-01 00:55:211427 ->ChangeInputMethod(extension_ime_util::kBrailleImeEngineId,
[email protected]f0881cf2014-08-15 23:31:421428 false /* show_message */);
[email protected]2e5e0b12014-05-07 13:30:201429 }
1430}
1431
dtsengfb6d7cd2016-01-20 23:00:131432void AccessibilityManager::OnExtensionUnloaded(
1433 content::BrowserContext* browser_context,
1434 const extensions::Extension* extension,
limasdf0deef2042017-05-03 19:17:171435 extensions::UnloadedExtensionReason reason) {
dtsengfb6d7cd2016-01-20 23:00:131436 if (extension->id() == keyboard_listener_extension_id_) {
1437 keyboard_listener_extension_id_ = std::string();
1438 keyboard_listener_capture_ = false;
dtsengfb6d7cd2016-01-20 23:00:131439 }
1440}
1441
1442void AccessibilityManager::OnShutdown(extensions::ExtensionRegistry* registry) {
1443 extension_registry_observer_.Remove(registry);
1444}
1445
dmazzoni337c5af2016-09-13 23:08:571446void AccessibilityManager::PostLoadChromeVox() {
[email protected]ee8bbd972014-02-03 06:52:471447 // Do any setup work needed immediately after ChromeVox actually loads.
sadrulcdc2bb42016-07-13 19:44:511448 PlayEarcon(SOUND_SPOKEN_FEEDBACK_ENABLED, PlaySoundOption::ALWAYS);
[email protected]0e9504d2013-11-05 02:33:291449
dtseng4702f8e2017-01-11 18:54:121450 extensions::EventRouter* event_router =
1451 extensions::EventRouter::Get(profile_);
1452 CHECK(event_router);
dtseng703a2042015-01-22 17:46:511453
dtseng4702f8e2017-01-11 18:54:121454 std::unique_ptr<base::ListValue> event_args(new base::ListValue());
1455 std::unique_ptr<extensions::Event> event(new extensions::Event(
1456 extensions::events::ACCESSIBILITY_PRIVATE_ON_INTRODUCE_CHROME_VOX,
1457 extensions::api::accessibility_private::OnIntroduceChromeVox::kEventName,
1458 std::move(event_args)));
1459 event_router->DispatchEventWithLazyListener(
1460 extension_misc::kChromeVoxExtensionId, std::move(event));
dmazzoni94a4f882015-11-13 05:46:521461
1462 if (!chromevox_panel_) {
tbarziccd5ad222017-03-24 04:46:311463 chromevox_panel_ = new ChromeVoxPanel(
1464 profile_,
1465 session_manager::SessionManager::Get()->IsUserSessionBlocked());
dmazzoni94a4f882015-11-13 05:46:521466 chromevox_panel_widget_observer_.reset(
1467 new ChromeVoxPanelWidgetObserver(chromevox_panel_->GetWidget(), this));
1468 }
dtsengd50debe32016-12-29 06:23:371469
1470 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
Dominic Mazzonic85a5c92017-08-31 18:53:301471 ::switches::kEnableAudioFocus)) {
dtsengd50debe32016-12-29 06:23:371472 base::CommandLine::ForCurrentProcess()->AppendSwitch(
Dominic Mazzonic85a5c92017-08-31 18:53:301473 ::switches::kEnableAudioFocus);
dtsengd50debe32016-12-29 06:23:371474 }
David Tsengf84b652f2017-12-16 01:09:301475
1476 keyboard_state_setter_.reset(new ScopedKeyboardStateSetter());
[email protected]0e9504d2013-11-05 02:33:291477}
1478
dmazzoni337c5af2016-09-13 23:08:571479void AccessibilityManager::PostUnloadChromeVox() {
[email protected]9d6c91362013-12-07 21:56:271480 // Do any teardown work needed immediately after ChromeVox actually unloads.
sadrulcdc2bb42016-07-13 19:44:511481 PlayEarcon(SOUND_SPOKEN_FEEDBACK_DISABLED, PlaySoundOption::ALWAYS);
Qiang Xu89af823e2017-12-05 04:04:471482
dmazzonifb33d592014-10-30 19:26:541483 // Clear the accessibility focus ring.
James Cook108e6122017-09-20 19:04:291484 ash::AccessibilityFocusRingController::GetInstance()->SetFocusRing(
dmazzoni42e4b002016-06-08 20:58:421485 std::vector<gfx::Rect>(),
James Cook108e6122017-09-20 19:04:291486 ash::AccessibilityFocusRingController::PERSIST_FOCUS_RING);
dmazzoni337c5af2016-09-13 23:08:571487
1488 if (chromevox_panel_) {
1489 chromevox_panel_->Close();
1490 chromevox_panel_ = nullptr;
1491 }
dtseng3a17f212017-03-25 08:58:521492
1493 // In case the user darkened the screen, undarken it now.
Daniel Erat477c56d2017-12-13 21:42:541494 scoped_backlights_forced_off_.reset();
David Tsengf84b652f2017-12-16 01:09:301495
1496 keyboard_state_setter_.reset();
[email protected]9d6c91362013-12-07 21:56:271497}
1498
dmazzoni63199b12016-10-19 15:44:361499void AccessibilityManager::PostSwitchChromeVoxProfile() {
tbarziccd5ad222017-03-24 04:46:311500 ReloadChromeVoxPanel();
1501}
1502
1503void AccessibilityManager::ReloadChromeVoxPanel() {
dmazzoni63199b12016-10-19 15:44:361504 if (chromevox_panel_) {
1505 chromevox_panel_->Close();
1506 chromevox_panel_ = nullptr;
1507 }
tbarziccd5ad222017-03-24 04:46:311508 chromevox_panel_ = new ChromeVoxPanel(
1509 profile_, session_manager::SessionManager::Get()->IsUserSessionBlocked());
dmazzoni63199b12016-10-19 15:44:361510 chromevox_panel_widget_observer_.reset(
1511 new ChromeVoxPanelWidgetObserver(chromevox_panel_->GetWidget(), this));
1512}
1513
dmazzoni94a4f882015-11-13 05:46:521514void AccessibilityManager::OnChromeVoxPanelClosing() {
jamescook788b4fc2017-05-18 16:16:061515 chromevox_panel_->ResetPanelHeight();
1516 chromevox_panel_widget_observer_.reset();
dmazzoni94a4f882015-11-13 05:46:521517 chromevox_panel_ = nullptr;
dmazzoni94a4f882015-11-13 05:46:521518}
1519
1520void AccessibilityManager::OnChromeVoxPanelDestroying() {
1521 chromevox_panel_widget_observer_.reset(nullptr);
1522 chromevox_panel_ = nullptr;
1523}
1524
dtsengfb6d7cd2016-01-20 23:00:131525void AccessibilityManager::SetKeyboardListenerExtensionId(
1526 const std::string& id,
1527 content::BrowserContext* context) {
1528 keyboard_listener_extension_id_ = id;
1529
1530 extensions::ExtensionRegistry* registry =
1531 extensions::ExtensionRegistry::Get(context);
1532 if (!extension_registry_observer_.IsObserving(registry) && !id.empty())
1533 extension_registry_observer_.Add(registry);
1534}
1535
elichtenberga108c8a2017-06-02 21:13:191536void AccessibilityManager::SetSwitchAccessKeys(const std::set<int>& key_codes) {
1537 if (switch_access_enabled_)
1538 switch_access_event_handler_->SetKeysToCapture(key_codes);
1539}
1540
[email protected]1dfebfc2013-06-04 03:14:321541} // namespace chromeos