| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" | 5 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #include "base/memory/singleton.h" | 26 #include "base/memory/singleton.h" |
| 27 #include "base/metrics/histogram.h" | 27 #include "base/metrics/histogram.h" |
| 28 #include "base/path_service.h" | 28 #include "base/path_service.h" |
| 29 #include "base/strings/string_split.h" | 29 #include "base/strings/string_split.h" |
| 30 #include "base/strings/string_util.h" | 30 #include "base/strings/string_util.h" |
| 31 #include "base/time/time.h" | 31 #include "base/time/time.h" |
| 32 #include "base/values.h" | 32 #include "base/values.h" |
| 33 #include "chrome/browser/accessibility/accessibility_extension_api.h" | 33 #include "chrome/browser/accessibility/accessibility_extension_api.h" |
| 34 #include "chrome/browser/browser_process.h" | 34 #include "chrome/browser/browser_process.h" |
| 35 #include "chrome/browser/chrome_notification_types.h" | 35 #include "chrome/browser/chrome_notification_types.h" |
| 36 #include "chrome/browser/chromeos/accessibility/accessibility_extension_loader.h
" |
| 36 #include "chrome/browser/chromeos/accessibility/accessibility_highlight_manager.
h" | 37 #include "chrome/browser/chromeos/accessibility/accessibility_highlight_manager.
h" |
| 37 #include "chrome/browser/chromeos/accessibility/magnification_manager.h" | 38 #include "chrome/browser/chromeos/accessibility/magnification_manager.h" |
| 38 #include "chrome/browser/chromeos/login/lock/screen_locker.h" | |
| 39 #include "chrome/browser/chromeos/login/ui/login_display_host.h" | |
| 40 #include "chrome/browser/chromeos/login/ui/webui_login_view.h" | |
| 41 #include "chrome/browser/chromeos/profiles/profile_helper.h" | 39 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| 42 #include "chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h" | 40 #include "chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h" |
| 43 #include "chrome/browser/extensions/api/braille_display_private/stub_braille_con
troller.h" | 41 #include "chrome/browser/extensions/api/braille_display_private/stub_braille_con
troller.h" |
| 44 #include "chrome/browser/extensions/component_loader.h" | |
| 45 #include "chrome/browser/extensions/extension_service.h" | 42 #include "chrome/browser/extensions/extension_service.h" |
| 46 #include "chrome/browser/extensions/tab_helper.h" | |
| 47 #include "chrome/browser/prefs/incognito_mode_prefs.h" | 43 #include "chrome/browser/prefs/incognito_mode_prefs.h" |
| 48 #include "chrome/browser/profiles/profile.h" | 44 #include "chrome/browser/profiles/profile.h" |
| 49 #include "chrome/browser/profiles/profile_manager.h" | 45 #include "chrome/browser/profiles/profile_manager.h" |
| 50 #include "chrome/common/chrome_paths.h" | 46 #include "chrome/common/chrome_paths.h" |
| 51 #include "chrome/common/extensions/api/accessibility_private.h" | 47 #include "chrome/common/extensions/api/accessibility_private.h" |
| 52 #include "chrome/common/extensions/extension_constants.h" | 48 #include "chrome/common/extensions/extension_constants.h" |
| 53 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" | |
| 54 #include "chrome/common/pref_names.h" | 49 #include "chrome/common/pref_names.h" |
| 55 #include "chrome/grit/browser_resources.h" | 50 #include "chrome/grit/browser_resources.h" |
| 56 #include "chromeos/audio/audio_a11y_controller.h" | 51 #include "chromeos/audio/audio_a11y_controller.h" |
| 57 #include "chromeos/audio/chromeos_sounds.h" | 52 #include "chromeos/audio/chromeos_sounds.h" |
| 58 #include "chromeos/login/login_state.h" | 53 #include "chromeos/login/login_state.h" |
| 59 #include "components/prefs/pref_member.h" | 54 #include "components/prefs/pref_member.h" |
| 60 #include "components/prefs/pref_service.h" | 55 #include "components/prefs/pref_service.h" |
| 61 #include "components/user_manager/user_manager.h" | 56 #include "components/user_manager/user_manager.h" |
| 62 #include "content/public/browser/browser_accessibility_state.h" | 57 #include "content/public/browser/browser_accessibility_state.h" |
| 63 #include "content/public/browser/browser_thread.h" | 58 #include "content/public/browser/browser_thread.h" |
| 64 #include "content/public/browser/notification_details.h" | 59 #include "content/public/browser/notification_details.h" |
| 65 #include "content/public/browser/notification_service.h" | 60 #include "content/public/browser/notification_service.h" |
| 66 #include "content/public/browser/notification_source.h" | 61 #include "content/public/browser/notification_source.h" |
| 67 #include "content/public/browser/render_process_host.h" | |
| 68 #include "content/public/browser/render_view_host.h" | 62 #include "content/public/browser/render_view_host.h" |
| 69 #include "content/public/browser/web_contents.h" | |
| 70 #include "content/public/browser/web_ui.h" | 63 #include "content/public/browser/web_ui.h" |
| 71 #include "content/public/common/content_switches.h" | 64 #include "content/public/common/content_switches.h" |
| 72 #include "extensions/browser/event_router.h" | 65 #include "extensions/browser/event_router.h" |
| 73 #include "extensions/browser/extension_api_frame_id_map.h" | |
| 74 #include "extensions/browser/extension_registry.h" | 66 #include "extensions/browser/extension_registry.h" |
| 75 #include "extensions/browser/extension_system.h" | 67 #include "extensions/browser/extension_system.h" |
| 76 #include "extensions/browser/file_reader.h" | |
| 77 #include "extensions/browser/script_executor.h" | |
| 78 #include "extensions/common/extension.h" | 68 #include "extensions/common/extension.h" |
| 79 #include "extensions/common/extension_messages.h" | 69 #include "extensions/common/extension_messages.h" |
| 80 #include "extensions/common/extension_resource.h" | 70 #include "extensions/common/extension_resource.h" |
| 81 #include "extensions/common/host_id.h" | 71 #include "extensions/common/host_id.h" |
| 82 #include "media/audio/sounds/sounds_manager.h" | 72 #include "media/audio/sounds/sounds_manager.h" |
| 83 #include "ui/base/ime/chromeos/input_method_manager.h" | 73 #include "ui/base/ime/chromeos/input_method_manager.h" |
| 84 #include "ui/base/resource/resource_bundle.h" | 74 #include "ui/base/resource/resource_bundle.h" |
| 85 #include "ui/keyboard/keyboard_controller.h" | 75 #include "ui/keyboard/keyboard_controller.h" |
| 86 #include "ui/keyboard/keyboard_util.h" | 76 #include "ui/keyboard/keyboard_util.h" |
| 87 | 77 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 111 if (g_braille_controller_for_test) | 101 if (g_braille_controller_for_test) |
| 112 return g_braille_controller_for_test; | 102 return g_braille_controller_for_test; |
| 113 // Don't use the real braille controller for tests to avoid automatically | 103 // Don't use the real braille controller for tests to avoid automatically |
| 114 // starting ChromeVox which confuses some tests. | 104 // starting ChromeVox which confuses some tests. |
| 115 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 105 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 116 if (command_line->HasSwitch(switches::kTestType)) | 106 if (command_line->HasSwitch(switches::kTestType)) |
| 117 return StubBrailleController::GetInstance(); | 107 return StubBrailleController::GetInstance(); |
| 118 return BrailleController::GetInstance(); | 108 return BrailleController::GetInstance(); |
| 119 } | 109 } |
| 120 | 110 |
| 121 base::FilePath GetChromeVoxPath() { | |
| 122 base::FilePath path; | |
| 123 if (!PathService::Get(chrome::DIR_RESOURCES, &path)) | |
| 124 NOTREACHED(); | |
| 125 path = path.Append(extension_misc::kChromeVoxExtensionPath); | |
| 126 return path; | |
| 127 } | |
| 128 | |
| 129 // Uses the ScriptExecutor associated with the given |render_view_host| to | |
| 130 // execute the given |code|. | |
| 131 void ExecuteScriptHelper( | |
| 132 content::RenderViewHost* render_view_host, | |
| 133 const std::string& code, | |
| 134 const std::string& extension_id) { | |
| 135 content::WebContents* web_contents = | |
| 136 content::WebContents::FromRenderViewHost(render_view_host); | |
| 137 if (!web_contents) | |
| 138 return; | |
| 139 if (!extensions::TabHelper::FromWebContents(web_contents)) | |
| 140 extensions::TabHelper::CreateForWebContents(web_contents); | |
| 141 extensions::TabHelper::FromWebContents(web_contents) | |
| 142 ->script_executor() | |
| 143 ->ExecuteScript(HostID(HostID::EXTENSIONS, extension_id), | |
| 144 extensions::ScriptExecutor::JAVASCRIPT, code, | |
| 145 extensions::ScriptExecutor::INCLUDE_SUB_FRAMES, | |
| 146 extensions::ExtensionApiFrameIdMap::kTopFrameId, | |
| 147 extensions::ScriptExecutor::DONT_MATCH_ABOUT_BLANK, | |
| 148 extensions::UserScript::DOCUMENT_IDLE, | |
| 149 extensions::ScriptExecutor::ISOLATED_WORLD, | |
| 150 extensions::ScriptExecutor::DEFAULT_PROCESS, | |
| 151 GURL(), // No webview src. | |
| 152 GURL(), // No file url. | |
| 153 false, // Not user gesture. | |
| 154 extensions::ScriptExecutor::NO_RESULT, | |
| 155 extensions::ScriptExecutor::ExecuteScriptCallback()); | |
| 156 } | |
| 157 | |
| 158 // Helper class that directly loads an extension's content scripts into | |
| 159 // all of the frames corresponding to a given RenderViewHost. | |
| 160 class ContentScriptLoader { | |
| 161 public: | |
| 162 // Initialize the ContentScriptLoader with the ID of the extension | |
| 163 // and the RenderViewHost where the scripts should be loaded. | |
| 164 ContentScriptLoader(const std::string& extension_id, | |
| 165 int render_process_id, | |
| 166 int render_view_id) | |
| 167 : extension_id_(extension_id), | |
| 168 render_process_id_(render_process_id), | |
| 169 render_view_id_(render_view_id) {} | |
| 170 | |
| 171 // Call this once with the ExtensionResource corresponding to each | |
| 172 // content script to be loaded. | |
| 173 void AppendScript(extensions::ExtensionResource resource) { | |
| 174 resources_.push(resource); | |
| 175 } | |
| 176 | |
| 177 // Finally, call this method once to fetch all of the resources and | |
| 178 // load them. This method will delete this object when done. | |
| 179 void Run() { | |
| 180 if (resources_.empty()) { | |
| 181 delete this; | |
| 182 return; | |
| 183 } | |
| 184 | |
| 185 extensions::ExtensionResource resource = resources_.front(); | |
| 186 resources_.pop(); | |
| 187 scoped_refptr<FileReader> reader(new FileReader(resource, base::Bind( | |
| 188 &ContentScriptLoader::OnFileLoaded, base::Unretained(this)))); | |
| 189 reader->Start(); | |
| 190 } | |
| 191 | |
| 192 private: | |
| 193 void OnFileLoaded(bool success, const std::string& data) { | |
| 194 if (success) { | |
| 195 RenderViewHost* render_view_host = | |
| 196 RenderViewHost::FromID(render_process_id_, render_view_id_); | |
| 197 if (render_view_host) | |
| 198 ExecuteScriptHelper(render_view_host, data, extension_id_); | |
| 199 } | |
| 200 Run(); | |
| 201 } | |
| 202 | |
| 203 std::string extension_id_; | |
| 204 int render_process_id_; | |
| 205 int render_view_id_; | |
| 206 std::queue<extensions::ExtensionResource> resources_; | |
| 207 }; | |
| 208 | |
| 209 void InjectChromeVoxContentScript( | |
| 210 ExtensionService* extension_service, | |
| 211 int render_process_id, | |
| 212 int render_view_id, | |
| 213 const base::Closure& done_cb); | |
| 214 | |
| 215 void LoadChromeVoxExtension( | |
| 216 Profile* profile, | |
| 217 RenderViewHost* render_view_host, | |
| 218 base::Closure done_cb) { | |
| 219 ExtensionService* extension_service = | |
| 220 extensions::ExtensionSystem::Get(profile)->extension_service(); | |
| 221 if (render_view_host) { | |
| 222 // Wrap the passed in callback to inject the content script. | |
| 223 done_cb = base::Bind( | |
| 224 &InjectChromeVoxContentScript, | |
| 225 extension_service, | |
| 226 render_view_host->GetProcess()->GetID(), | |
| 227 render_view_host->GetRoutingID(), | |
| 228 done_cb); | |
| 229 } | |
| 230 | |
| 231 extension_service->component_loader()->AddComponentWithGuestManifest( | |
| 232 GetChromeVoxPath(), extension_misc::kChromeVoxExtensionId, done_cb); | |
| 233 } | |
| 234 | |
| 235 void InjectChromeVoxContentScript( | |
| 236 ExtensionService* extension_service, | |
| 237 int render_process_id, | |
| 238 int render_view_id, | |
| 239 const base::Closure& done_cb) { | |
| 240 // Make sure to always run |done_cb|. ChromeVox was loaded even if we end up | |
| 241 // not injecting into this particular render view. | |
| 242 base::ScopedClosureRunner done_runner(done_cb); | |
| 243 RenderViewHost* render_view_host = | |
| 244 RenderViewHost::FromID(render_process_id, render_view_id); | |
| 245 if (!render_view_host) | |
| 246 return; | |
| 247 const content::WebContents* web_contents = | |
| 248 content::WebContents::FromRenderViewHost(render_view_host); | |
| 249 GURL content_url; | |
| 250 if (web_contents) | |
| 251 content_url = web_contents->GetLastCommittedURL(); | |
| 252 const extensions::Extension* extension = | |
| 253 extensions::ExtensionRegistry::Get(extension_service->profile()) | |
| 254 ->enabled_extensions() | |
| 255 .GetByID(extension_misc::kChromeVoxExtensionId); | |
| 256 | |
| 257 // Set a flag to tell ChromeVox that it's just been enabled, | |
| 258 // so that it won't interrupt our speech feedback enabled message. | |
| 259 ExecuteScriptHelper(render_view_host, "window.INJECTED_AFTER_LOAD = true;", | |
| 260 extension->id()); | |
| 261 | |
| 262 // Inject ChromeVox' content scripts. | |
| 263 ContentScriptLoader* loader = new ContentScriptLoader( | |
| 264 extension->id(), render_view_host->GetProcess()->GetID(), | |
| 265 render_view_host->GetRoutingID()); | |
| 266 | |
| 267 const extensions::UserScriptList& content_scripts = | |
| 268 extensions::ContentScriptsInfo::GetContentScripts(extension); | |
| 269 for (size_t i = 0; i < content_scripts.size(); i++) { | |
| 270 const extensions::UserScript& script = content_scripts[i]; | |
| 271 if (web_contents && !script.MatchesURL(content_url)) | |
| 272 continue; | |
| 273 for (size_t j = 0; j < script.js_scripts().size(); ++j) { | |
| 274 const extensions::UserScript::File& file = script.js_scripts()[j]; | |
| 275 extensions::ExtensionResource resource = extension->GetResource( | |
| 276 file.relative_path()); | |
| 277 loader->AppendScript(resource); | |
| 278 } | |
| 279 } | |
| 280 loader->Run(); // It cleans itself up when done. | |
| 281 } | |
| 282 | |
| 283 void UnloadChromeVoxExtension(Profile* profile) { | |
| 284 base::FilePath path = GetChromeVoxPath(); | |
| 285 ExtensionService* extension_service = | |
| 286 extensions::ExtensionSystem::Get(profile)->extension_service(); | |
| 287 extension_service->component_loader()->Remove(path); | |
| 288 } | |
| 289 | |
| 290 } // namespace | 111 } // namespace |
| 291 | 112 |
| 292 class ChromeVoxPanelWidgetObserver : public views::WidgetObserver { | 113 class ChromeVoxPanelWidgetObserver : public views::WidgetObserver { |
| 293 public: | 114 public: |
| 294 ChromeVoxPanelWidgetObserver(views::Widget* widget, | 115 ChromeVoxPanelWidgetObserver(views::Widget* widget, |
| 295 AccessibilityManager* manager) | 116 AccessibilityManager* manager) |
| 296 : widget_(widget), manager_(manager) { | 117 : widget_(widget), manager_(manager) { |
| 297 widget_->AddObserver(this); | 118 widget_->AddObserver(this); |
| 298 } | 119 } |
| 299 | 120 |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 394 g_accessibility_manager = NULL; | 215 g_accessibility_manager = NULL; |
| 395 } | 216 } |
| 396 | 217 |
| 397 // static | 218 // static |
| 398 AccessibilityManager* AccessibilityManager::Get() { | 219 AccessibilityManager* AccessibilityManager::Get() { |
| 399 return g_accessibility_manager; | 220 return g_accessibility_manager; |
| 400 } | 221 } |
| 401 | 222 |
| 402 AccessibilityManager::AccessibilityManager() | 223 AccessibilityManager::AccessibilityManager() |
| 403 : profile_(NULL), | 224 : profile_(NULL), |
| 404 chrome_vox_loaded_on_lock_screen_(false), | |
| 405 chrome_vox_loaded_on_user_screen_(false), | |
| 406 large_cursor_pref_handler_(prefs::kAccessibilityLargeCursorEnabled), | 225 large_cursor_pref_handler_(prefs::kAccessibilityLargeCursorEnabled), |
| 407 spoken_feedback_pref_handler_(prefs::kAccessibilitySpokenFeedbackEnabled), | 226 spoken_feedback_pref_handler_(prefs::kAccessibilitySpokenFeedbackEnabled), |
| 408 high_contrast_pref_handler_(prefs::kAccessibilityHighContrastEnabled), | 227 high_contrast_pref_handler_(prefs::kAccessibilityHighContrastEnabled), |
| 409 autoclick_pref_handler_(prefs::kAccessibilityAutoclickEnabled), | 228 autoclick_pref_handler_(prefs::kAccessibilityAutoclickEnabled), |
| 410 autoclick_delay_pref_handler_(prefs::kAccessibilityAutoclickDelayMs), | 229 autoclick_delay_pref_handler_(prefs::kAccessibilityAutoclickDelayMs), |
| 411 virtual_keyboard_pref_handler_( | 230 virtual_keyboard_pref_handler_( |
| 412 prefs::kAccessibilityVirtualKeyboardEnabled), | 231 prefs::kAccessibilityVirtualKeyboardEnabled), |
| 413 mono_audio_pref_handler_(prefs::kAccessibilityMonoAudioEnabled), | 232 mono_audio_pref_handler_(prefs::kAccessibilityMonoAudioEnabled), |
| 414 caret_highlight_pref_handler_(prefs::kAccessibilityCaretHighlightEnabled), | 233 caret_highlight_pref_handler_(prefs::kAccessibilityCaretHighlightEnabled), |
| 415 cursor_highlight_pref_handler_( | 234 cursor_highlight_pref_handler_( |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 bundle.GetRawDataResource(IDR_SOUND_SPOKEN_FEEDBACK_ENABLED_WAV)); | 282 bundle.GetRawDataResource(IDR_SOUND_SPOKEN_FEEDBACK_ENABLED_WAV)); |
| 464 manager->Initialize( | 283 manager->Initialize( |
| 465 SOUND_SPOKEN_FEEDBACK_DISABLED, | 284 SOUND_SPOKEN_FEEDBACK_DISABLED, |
| 466 bundle.GetRawDataResource(IDR_SOUND_SPOKEN_FEEDBACK_DISABLED_WAV)); | 285 bundle.GetRawDataResource(IDR_SOUND_SPOKEN_FEEDBACK_DISABLED_WAV)); |
| 467 manager->Initialize(SOUND_PASSTHROUGH, | 286 manager->Initialize(SOUND_PASSTHROUGH, |
| 468 bundle.GetRawDataResource(IDR_SOUND_PASSTHROUGH_WAV)); | 287 bundle.GetRawDataResource(IDR_SOUND_PASSTHROUGH_WAV)); |
| 469 manager->Initialize(SOUND_EXIT_SCREEN, | 288 manager->Initialize(SOUND_EXIT_SCREEN, |
| 470 bundle.GetRawDataResource(IDR_SOUND_EXIT_SCREEN_WAV)); | 289 bundle.GetRawDataResource(IDR_SOUND_EXIT_SCREEN_WAV)); |
| 471 manager->Initialize(SOUND_ENTER_SCREEN, | 290 manager->Initialize(SOUND_ENTER_SCREEN, |
| 472 bundle.GetRawDataResource(IDR_SOUND_ENTER_SCREEN_WAV)); | 291 bundle.GetRawDataResource(IDR_SOUND_ENTER_SCREEN_WAV)); |
| 292 |
| 293 base::FilePath resources_path; |
| 294 if (!PathService::Get(chrome::DIR_RESOURCES, &resources_path)) |
| 295 NOTREACHED(); |
| 296 chromevox_loader_ = base::WrapUnique(new AccessibilityExtensionLoader( |
| 297 extension_misc::kChromeVoxExtensionId, |
| 298 resources_path.Append(extension_misc::kChromeVoxExtensionPath))); |
| 473 } | 299 } |
| 474 | 300 |
| 475 AccessibilityManager::~AccessibilityManager() { | 301 AccessibilityManager::~AccessibilityManager() { |
| 476 CHECK(this == g_accessibility_manager); | 302 CHECK(this == g_accessibility_manager); |
| 477 AccessibilityStatusEventDetails details(ACCESSIBILITY_MANAGER_SHUTDOWN, false, | 303 AccessibilityStatusEventDetails details(ACCESSIBILITY_MANAGER_SHUTDOWN, false, |
| 478 ash::A11Y_NOTIFICATION_NONE); | 304 ash::A11Y_NOTIFICATION_NONE); |
| 479 NotifyAccessibilityStatusChanged(details); | 305 NotifyAccessibilityStatusChanged(details); |
| 480 input_method::InputMethodManager::Get()->RemoveObserver(this); | 306 input_method::InputMethodManager::Get()->RemoveObserver(this); |
| 481 | 307 |
| 482 if (chromevox_panel_) { | 308 if (chromevox_panel_) { |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 spoken_feedback_enabled_ = enabled; | 447 spoken_feedback_enabled_ = enabled; |
| 622 | 448 |
| 623 AccessibilityStatusEventDetails details( | 449 AccessibilityStatusEventDetails details( |
| 624 ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK, | 450 ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK, |
| 625 enabled, | 451 enabled, |
| 626 spoken_feedback_notification_); | 452 spoken_feedback_notification_); |
| 627 | 453 |
| 628 NotifyAccessibilityStatusChanged(details); | 454 NotifyAccessibilityStatusChanged(details); |
| 629 | 455 |
| 630 if (enabled) { | 456 if (enabled) { |
| 631 LoadChromeVox(); | 457 chromevox_loader_->Load(profile_, "window.INJECTED_AFTER_LOAD = true;", |
| 458 base::Bind(&AccessibilityManager::PostLoadChromeVox, |
| 459 weak_ptr_factory_.GetWeakPtr())); |
| 460 |
| 632 } else { | 461 } else { |
| 633 UnloadChromeVox(); | 462 chromevox_loader_->Unload(); |
| 634 } | 463 } |
| 635 UpdateBrailleImeState(); | 464 UpdateBrailleImeState(); |
| 636 | 465 |
| 637 // ChromeVox focus highlighting overrides the other focus highlighting. | 466 // ChromeVox focus highlighting overrides the other focus highlighting. |
| 638 UpdateFocusHighlightFromPref(); | 467 UpdateFocusHighlightFromPref(); |
| 639 } | 468 } |
| 640 | 469 |
| 641 void AccessibilityManager::LoadChromeVox() { | |
| 642 base::Closure done_cb = base::Bind(&AccessibilityManager::PostLoadChromeVox, | |
| 643 weak_ptr_factory_.GetWeakPtr(), | |
| 644 profile_); | |
| 645 ScreenLocker* screen_locker = ScreenLocker::default_screen_locker(); | |
| 646 if (screen_locker && screen_locker->locked()) { | |
| 647 // If on the lock screen, loads ChromeVox only to the lock screen as for | |
| 648 // now. On unlock, it will be loaded to the user screen. | |
| 649 // (see. AccessibilityManager::Observe()) | |
| 650 LoadChromeVoxToLockScreen(done_cb); | |
| 651 } else { | |
| 652 LoadChromeVoxToUserScreen(done_cb); | |
| 653 } | |
| 654 } | |
| 655 | |
| 656 void AccessibilityManager::LoadChromeVoxToUserScreen( | |
| 657 const base::Closure& done_cb) { | |
| 658 if (chrome_vox_loaded_on_user_screen_) | |
| 659 return; | |
| 660 | |
| 661 // Determine whether an OOBE screen is currently being shown. If so, | |
| 662 // ChromeVox will be injected directly into that screen. | |
| 663 content::WebUI* login_web_ui = NULL; | |
| 664 | |
| 665 if (ProfileHelper::IsSigninProfile(profile_)) { | |
| 666 LoginDisplayHost* login_display_host = LoginDisplayHost::default_host(); | |
| 667 if (login_display_host) { | |
| 668 WebUILoginView* web_ui_login_view = | |
| 669 login_display_host->GetWebUILoginView(); | |
| 670 if (web_ui_login_view) | |
| 671 login_web_ui = web_ui_login_view->GetWebUI(); | |
| 672 } | |
| 673 | |
| 674 // Lock screen uses the signin progile. | |
| 675 chrome_vox_loaded_on_lock_screen_ = true; | |
| 676 } | |
| 677 | |
| 678 chrome_vox_loaded_on_user_screen_ = true; | |
| 679 LoadChromeVoxExtension( | |
| 680 profile_, login_web_ui ? | |
| 681 login_web_ui->GetWebContents()->GetRenderViewHost() : NULL, | |
| 682 done_cb); | |
| 683 } | |
| 684 | |
| 685 void AccessibilityManager::LoadChromeVoxToLockScreen( | |
| 686 const base::Closure& done_cb) { | |
| 687 if (chrome_vox_loaded_on_lock_screen_) | |
| 688 return; | |
| 689 | |
| 690 ScreenLocker* screen_locker = ScreenLocker::default_screen_locker(); | |
| 691 if (screen_locker && screen_locker->locked()) { | |
| 692 content::WebUI* lock_web_ui = screen_locker->GetAssociatedWebUI(); | |
| 693 if (lock_web_ui) { | |
| 694 Profile* profile = Profile::FromWebUI(lock_web_ui); | |
| 695 chrome_vox_loaded_on_lock_screen_ = true; | |
| 696 LoadChromeVoxExtension( | |
| 697 profile, | |
| 698 lock_web_ui->GetWebContents()->GetRenderViewHost(), | |
| 699 done_cb); | |
| 700 } | |
| 701 } | |
| 702 } | |
| 703 | |
| 704 void AccessibilityManager::UnloadChromeVox() { | |
| 705 if (chromevox_panel_) { | |
| 706 chromevox_panel_->Close(); | |
| 707 chromevox_panel_ = nullptr; | |
| 708 } | |
| 709 | |
| 710 if (chrome_vox_loaded_on_lock_screen_) | |
| 711 UnloadChromeVoxFromLockScreen(); | |
| 712 | |
| 713 if (chrome_vox_loaded_on_user_screen_) { | |
| 714 UnloadChromeVoxExtension(profile_); | |
| 715 chrome_vox_loaded_on_user_screen_ = false; | |
| 716 } | |
| 717 | |
| 718 PostUnloadChromeVox(profile_); | |
| 719 } | |
| 720 | |
| 721 void AccessibilityManager::UnloadChromeVoxFromLockScreen() { | |
| 722 // Lock screen uses the signin progile. | |
| 723 Profile* signin_profile = ProfileHelper::GetSigninProfile(); | |
| 724 UnloadChromeVoxExtension(signin_profile); | |
| 725 chrome_vox_loaded_on_lock_screen_ = false; | |
| 726 } | |
| 727 | |
| 728 bool AccessibilityManager::IsSpokenFeedbackEnabled() { | 470 bool AccessibilityManager::IsSpokenFeedbackEnabled() { |
| 729 return spoken_feedback_enabled_; | 471 return spoken_feedback_enabled_; |
| 730 } | 472 } |
| 731 | 473 |
| 732 void AccessibilityManager::ToggleSpokenFeedback( | 474 void AccessibilityManager::ToggleSpokenFeedback( |
| 733 ash::AccessibilityNotificationVisibility notify) { | 475 ash::AccessibilityNotificationVisibility notify) { |
| 734 EnableSpokenFeedback(!IsSpokenFeedbackEnabled(), notify); | 476 EnableSpokenFeedback(!IsSpokenFeedbackEnabled(), notify); |
| 735 } | 477 } |
| 736 | 478 |
| 737 void AccessibilityManager::EnableHighContrast(bool enabled) { | 479 void AccessibilityManager::EnableHighContrast(bool enabled) { |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1239 local_state_pref_change_registrar_->Init(g_browser_process->local_state()); | 981 local_state_pref_change_registrar_->Init(g_browser_process->local_state()); |
| 1240 local_state_pref_change_registrar_->Add( | 982 local_state_pref_change_registrar_->Add( |
| 1241 prefs::kApplicationLocale, | 983 prefs::kApplicationLocale, |
| 1242 base::Bind(&AccessibilityManager::OnLocaleChanged, | 984 base::Bind(&AccessibilityManager::OnLocaleChanged, |
| 1243 base::Unretained(this))); | 985 base::Unretained(this))); |
| 1244 | 986 |
| 1245 content::BrowserAccessibilityState::GetInstance()->AddHistogramCallback( | 987 content::BrowserAccessibilityState::GetInstance()->AddHistogramCallback( |
| 1246 base::Bind( | 988 base::Bind( |
| 1247 &AccessibilityManager::UpdateChromeOSAccessibilityHistograms, | 989 &AccessibilityManager::UpdateChromeOSAccessibilityHistograms, |
| 1248 base::Unretained(this))); | 990 base::Unretained(this))); |
| 991 |
| 992 chromevox_loader_->SetProfile(profile); |
| 993 |
| 994 extensions::ExtensionRegistry* registry = |
| 995 extensions::ExtensionRegistry::Get(profile); |
| 996 if (!extension_registry_observer_.IsObserving(registry)) |
| 997 extension_registry_observer_.Add(registry); |
| 1249 } | 998 } |
| 1250 | 999 |
| 1251 large_cursor_pref_handler_.HandleProfileChanged(profile_, profile); | 1000 large_cursor_pref_handler_.HandleProfileChanged(profile_, profile); |
| 1252 spoken_feedback_pref_handler_.HandleProfileChanged(profile_, profile); | 1001 spoken_feedback_pref_handler_.HandleProfileChanged(profile_, profile); |
| 1253 high_contrast_pref_handler_.HandleProfileChanged(profile_, profile); | 1002 high_contrast_pref_handler_.HandleProfileChanged(profile_, profile); |
| 1254 autoclick_pref_handler_.HandleProfileChanged(profile_, profile); | 1003 autoclick_pref_handler_.HandleProfileChanged(profile_, profile); |
| 1255 autoclick_delay_pref_handler_.HandleProfileChanged(profile_, profile); | 1004 autoclick_delay_pref_handler_.HandleProfileChanged(profile_, profile); |
| 1256 virtual_keyboard_pref_handler_.HandleProfileChanged(profile_, profile); | 1005 virtual_keyboard_pref_handler_.HandleProfileChanged(profile_, profile); |
| 1257 mono_audio_pref_handler_.HandleProfileChanged(profile_, profile); | 1006 mono_audio_pref_handler_.HandleProfileChanged(profile_, profile); |
| 1258 caret_highlight_pref_handler_.HandleProfileChanged(profile_, profile); | 1007 caret_highlight_pref_handler_.HandleProfileChanged(profile_, profile); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1319 base::TimeDelta AccessibilityManager::PlayShutdownSound() { | 1068 base::TimeDelta AccessibilityManager::PlayShutdownSound() { |
| 1320 if (!system_sounds_enabled_) | 1069 if (!system_sounds_enabled_) |
| 1321 return base::TimeDelta(); | 1070 return base::TimeDelta(); |
| 1322 system_sounds_enabled_ = false; | 1071 system_sounds_enabled_ = false; |
| 1323 if (!PlayEarcon(SOUND_SHUTDOWN, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED)) | 1072 if (!PlayEarcon(SOUND_SHUTDOWN, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED)) |
| 1324 return base::TimeDelta(); | 1073 return base::TimeDelta(); |
| 1325 return media::SoundsManager::Get()->GetDuration(SOUND_SHUTDOWN); | 1074 return media::SoundsManager::Get()->GetDuration(SOUND_SHUTDOWN); |
| 1326 } | 1075 } |
| 1327 | 1076 |
| 1328 void AccessibilityManager::InjectChromeVox(RenderViewHost* render_view_host) { | 1077 void AccessibilityManager::InjectChromeVox(RenderViewHost* render_view_host) { |
| 1329 LoadChromeVoxExtension(profile_, render_view_host, base::Closure()); | 1078 chromevox_loader_->InjectContentScript(render_view_host); |
| 1330 } | 1079 } |
| 1331 | 1080 |
| 1332 std::unique_ptr<AccessibilityStatusSubscription> | 1081 std::unique_ptr<AccessibilityStatusSubscription> |
| 1333 AccessibilityManager::RegisterCallback(const AccessibilityStatusCallback& cb) { | 1082 AccessibilityManager::RegisterCallback(const AccessibilityStatusCallback& cb) { |
| 1334 return callback_list_.Add(cb); | 1083 return callback_list_.Add(cb); |
| 1335 } | 1084 } |
| 1336 | 1085 |
| 1337 void AccessibilityManager::NotifyAccessibilityStatusChanged( | 1086 void AccessibilityManager::NotifyAccessibilityStatusChanged( |
| 1338 AccessibilityStatusEventDetails& details) { | 1087 AccessibilityStatusEventDetails& details) { |
| 1339 callback_list_.Notify(details); | 1088 callback_list_.Notify(details); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1419 // Update |profile_| when exiting a session or shutting down. | 1168 // Update |profile_| when exiting a session or shutting down. |
| 1420 Profile* profile = content::Source<Profile>(source).ptr(); | 1169 Profile* profile = content::Source<Profile>(source).ptr(); |
| 1421 if (profile_ == profile) | 1170 if (profile_ == profile) |
| 1422 SetProfile(NULL); | 1171 SetProfile(NULL); |
| 1423 break; | 1172 break; |
| 1424 } | 1173 } |
| 1425 case chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED: { | 1174 case chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED: { |
| 1426 bool is_screen_locked = *content::Details<bool>(details).ptr(); | 1175 bool is_screen_locked = *content::Details<bool>(details).ptr(); |
| 1427 if (spoken_feedback_enabled_) { | 1176 if (spoken_feedback_enabled_) { |
| 1428 if (is_screen_locked) | 1177 if (is_screen_locked) |
| 1429 LoadChromeVoxToLockScreen(base::Closure()); | 1178 chromevox_loader_->LoadToLockScreen(base::Closure()); |
| 1430 // If spoken feedback was enabled, make sure it is also enabled on | 1179 // If spoken feedback was enabled, make sure it is also enabled on |
| 1431 // the user screen. | 1180 // the user screen. |
| 1432 // The status tray gets verbalized by user screen ChromeVox, so we need | 1181 // The status tray gets verbalized by user screen ChromeVox, so we need |
| 1433 // to load it on the user screen even if the screen is locked. | 1182 // to load it on the user screen even if the screen is locked. |
| 1434 LoadChromeVoxToUserScreen(base::Closure()); | 1183 chromevox_loader_->LoadToUserScreen(base::Closure()); |
| 1435 } | 1184 } |
| 1436 break; | 1185 break; |
| 1437 } | 1186 } |
| 1438 } | 1187 } |
| 1439 } | 1188 } |
| 1440 | 1189 |
| 1441 void AccessibilityManager::OnBrailleDisplayStateChanged( | 1190 void AccessibilityManager::OnBrailleDisplayStateChanged( |
| 1442 const DisplayState& display_state) { | 1191 const DisplayState& display_state) { |
| 1443 braille_display_connected_ = display_state.available; | 1192 braille_display_connected_ = display_state.available; |
| 1444 if (braille_display_connected_) { | 1193 if (braille_display_connected_) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1464 } | 1213 } |
| 1465 } | 1214 } |
| 1466 | 1215 |
| 1467 void AccessibilityManager::OnExtensionUnloaded( | 1216 void AccessibilityManager::OnExtensionUnloaded( |
| 1468 content::BrowserContext* browser_context, | 1217 content::BrowserContext* browser_context, |
| 1469 const extensions::Extension* extension, | 1218 const extensions::Extension* extension, |
| 1470 extensions::UnloadedExtensionInfo::Reason reason) { | 1219 extensions::UnloadedExtensionInfo::Reason reason) { |
| 1471 if (extension->id() == keyboard_listener_extension_id_) { | 1220 if (extension->id() == keyboard_listener_extension_id_) { |
| 1472 keyboard_listener_extension_id_ = std::string(); | 1221 keyboard_listener_extension_id_ = std::string(); |
| 1473 keyboard_listener_capture_ = false; | 1222 keyboard_listener_capture_ = false; |
| 1474 extension_registry_observer_.Remove( | 1223 } |
| 1475 extensions::ExtensionRegistry::Get(browser_context)); | 1224 |
| 1225 if (extension->id() == extension_misc::kChromeVoxExtensionId) { |
| 1226 // Do any teardown work needed immediately after ChromeVox actually unloads. |
| 1227 PlayEarcon(SOUND_SPOKEN_FEEDBACK_DISABLED, PlaySoundOption::ALWAYS); |
| 1228 // Clear the accessibility focus ring. |
| 1229 AccessibilityFocusRingController::GetInstance()->SetFocusRing( |
| 1230 std::vector<gfx::Rect>(), |
| 1231 AccessibilityFocusRingController::PERSIST_FOCUS_RING); |
| 1232 |
| 1233 if (chromevox_panel_) { |
| 1234 chromevox_panel_->Close(); |
| 1235 chromevox_panel_ = nullptr; |
| 1236 } |
| 1476 } | 1237 } |
| 1477 } | 1238 } |
| 1478 | 1239 |
| 1479 void AccessibilityManager::OnShutdown(extensions::ExtensionRegistry* registry) { | 1240 void AccessibilityManager::OnShutdown(extensions::ExtensionRegistry* registry) { |
| 1480 extension_registry_observer_.Remove(registry); | 1241 extension_registry_observer_.Remove(registry); |
| 1481 } | 1242 } |
| 1482 | 1243 |
| 1483 void AccessibilityManager::PostLoadChromeVox(Profile* profile) { | 1244 void AccessibilityManager::PostLoadChromeVox() { |
| 1484 // Do any setup work needed immediately after ChromeVox actually loads. | 1245 // Do any setup work needed immediately after ChromeVox actually loads. |
| 1485 PlayEarcon(SOUND_SPOKEN_FEEDBACK_ENABLED, PlaySoundOption::ALWAYS); | 1246 PlayEarcon(SOUND_SPOKEN_FEEDBACK_ENABLED, PlaySoundOption::ALWAYS); |
| 1486 | 1247 |
| 1487 if (chrome_vox_loaded_on_lock_screen_ || | 1248 if (chromevox_loader_->loaded_on_lock_screen() || |
| 1488 should_speak_chrome_vox_announcements_on_user_screen_) { | 1249 should_speak_chrome_vox_announcements_on_user_screen_) { |
| 1489 extensions::EventRouter* event_router = | 1250 extensions::EventRouter* event_router = |
| 1490 extensions::EventRouter::Get(profile); | 1251 extensions::EventRouter::Get(profile_); |
| 1491 CHECK(event_router); | 1252 CHECK(event_router); |
| 1492 | 1253 |
| 1493 std::unique_ptr<base::ListValue> event_args(new base::ListValue()); | 1254 std::unique_ptr<base::ListValue> event_args(new base::ListValue()); |
| 1494 std::unique_ptr<extensions::Event> event(new extensions::Event( | 1255 std::unique_ptr<extensions::Event> event(new extensions::Event( |
| 1495 extensions::events::ACCESSIBILITY_PRIVATE_ON_INTRODUCE_CHROME_VOX, | 1256 extensions::events::ACCESSIBILITY_PRIVATE_ON_INTRODUCE_CHROME_VOX, |
| 1496 extensions::api::accessibility_private::OnIntroduceChromeVox:: | 1257 extensions::api::accessibility_private::OnIntroduceChromeVox:: |
| 1497 kEventName, | 1258 kEventName, |
| 1498 std::move(event_args))); | 1259 std::move(event_args))); |
| 1499 event_router->DispatchEventWithLazyListener( | 1260 event_router->DispatchEventWithLazyListener( |
| 1500 extension_misc::kChromeVoxExtensionId, std::move(event)); | 1261 extension_misc::kChromeVoxExtensionId, std::move(event)); |
| 1501 } | 1262 } |
| 1502 | 1263 |
| 1503 should_speak_chrome_vox_announcements_on_user_screen_ = | 1264 should_speak_chrome_vox_announcements_on_user_screen_ = |
| 1504 chrome_vox_loaded_on_lock_screen_; | 1265 chromevox_loader_->loaded_on_lock_screen(); |
| 1505 | 1266 |
| 1506 if (!chromevox_panel_) { | 1267 if (!chromevox_panel_) { |
| 1507 chromevox_panel_ = new ChromeVoxPanel(profile_); | 1268 chromevox_panel_ = new ChromeVoxPanel(profile_); |
| 1508 chromevox_panel_widget_observer_.reset( | 1269 chromevox_panel_widget_observer_.reset( |
| 1509 new ChromeVoxPanelWidgetObserver(chromevox_panel_->GetWidget(), this)); | 1270 new ChromeVoxPanelWidgetObserver(chromevox_panel_->GetWidget(), this)); |
| 1510 } | 1271 } |
| 1511 } | 1272 } |
| 1512 | 1273 |
| 1513 void AccessibilityManager::PostUnloadChromeVox(Profile* profile) { | |
| 1514 // Do any teardown work needed immediately after ChromeVox actually unloads. | |
| 1515 PlayEarcon(SOUND_SPOKEN_FEEDBACK_DISABLED, PlaySoundOption::ALWAYS); | |
| 1516 // Clear the accessibility focus ring. | |
| 1517 AccessibilityFocusRingController::GetInstance()->SetFocusRing( | |
| 1518 std::vector<gfx::Rect>(), | |
| 1519 AccessibilityFocusRingController::PERSIST_FOCUS_RING); | |
| 1520 } | |
| 1521 | |
| 1522 void AccessibilityManager::OnChromeVoxPanelClosing() { | 1274 void AccessibilityManager::OnChromeVoxPanelClosing() { |
| 1523 aura::Window* root_window = chromevox_panel_->GetRootWindow(); | 1275 aura::Window* root_window = chromevox_panel_->GetRootWindow(); |
| 1524 chromevox_panel_widget_observer_.reset(nullptr); | 1276 chromevox_panel_widget_observer_.reset(nullptr); |
| 1525 chromevox_panel_ = nullptr; | 1277 chromevox_panel_ = nullptr; |
| 1526 | 1278 |
| 1527 ash::Shelf* shelf = ash::Shelf::ForWindow(root_window); | 1279 ash::Shelf* shelf = ash::Shelf::ForWindow(root_window); |
| 1528 if (!shelf) | 1280 if (!shelf) |
| 1529 return; | 1281 return; |
| 1530 | 1282 |
| 1531 ash::ShelfLayoutManager* shelf_layout_manager = shelf->shelf_layout_manager(); | 1283 ash::ShelfLayoutManager* shelf_layout_manager = shelf->shelf_layout_manager(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1543 content::BrowserContext* context) { | 1295 content::BrowserContext* context) { |
| 1544 keyboard_listener_extension_id_ = id; | 1296 keyboard_listener_extension_id_ = id; |
| 1545 | 1297 |
| 1546 extensions::ExtensionRegistry* registry = | 1298 extensions::ExtensionRegistry* registry = |
| 1547 extensions::ExtensionRegistry::Get(context); | 1299 extensions::ExtensionRegistry::Get(context); |
| 1548 if (!extension_registry_observer_.IsObserving(registry) && !id.empty()) | 1300 if (!extension_registry_observer_.IsObserving(registry) && !id.empty()) |
| 1549 extension_registry_observer_.Add(registry); | 1301 extension_registry_observer_.Add(registry); |
| 1550 } | 1302 } |
| 1551 | 1303 |
| 1552 } // namespace chromeos | 1304 } // namespace chromeos |
| OLD | NEW |