| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 /** | 5 /** |
| 6 * @fileoverview The entry point for all ChromeVox2 related code for the | 6 * @fileoverview The entry point for all ChromeVox2 related code for the |
| 7 * background page. | 7 * background page. |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 goog.provide('Background'); | 10 goog.provide('Background'); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 /** | 82 /** |
| 83 * Maps an automation event to its listener. | 83 * Maps an automation event to its listener. |
| 84 * @type {!Object.<EventType, function(Object) : void>} | 84 * @type {!Object.<EventType, function(Object) : void>} |
| 85 */ | 85 */ |
| 86 this.listeners_ = { | 86 this.listeners_ = { |
| 87 alert: this.onEventDefault, | 87 alert: this.onEventDefault, |
| 88 focus: this.onEventDefault, | 88 focus: this.onEventDefault, |
| 89 menuStart: this.onEventDefault, | 89 menuStart: this.onEventDefault, |
| 90 menuEnd: this.onEventDefault, | 90 menuEnd: this.onEventDefault, |
| 91 loadComplete: this.onLoadComplete, | 91 loadComplete: this.onLoadComplete, |
| 92 textSelectionChanged: this.onTextSelectionChanged | 92 textChanged: this.onTextOrTextSelectionChanged, |
| 93 textSelectionChanged: this.onTextOrTextSelectionChanged, |
| 94 valueChanged: this.onEventDefault |
| 93 }; | 95 }; |
| 94 | 96 |
| 95 // Register listeners for ... | 97 // Register listeners for ... |
| 96 // Desktop. | 98 // Desktop. |
| 97 chrome.automation.getDesktop(this.onGotTree); | 99 chrome.automation.getDesktop(this.onGotTree); |
| 98 | 100 |
| 99 // Tabs. | 101 // Tabs. |
| 100 chrome.tabs.onUpdated.addListener(this.onTabUpdated); | 102 chrome.tabs.onUpdated.addListener(this.onTabUpdated); |
| 101 | |
| 102 // Commands. | |
| 103 chrome.commands.onCommand.addListener(this.onGotCommand); | |
| 104 }; | 103 }; |
| 105 | 104 |
| 106 Background.prototype = { | 105 Background.prototype = { |
| 107 /** | 106 /** |
| 108 * Handles chrome.tabs.onUpdated. | 107 * Handles chrome.tabs.onUpdated. |
| 109 * @param {number} tabId | 108 * @param {number} tabId |
| 110 * @param {Object} changeInfo | 109 * @param {Object} changeInfo |
| 111 */ | 110 */ |
| 112 onTabUpdated: function(tabId, changeInfo) { | 111 onTabUpdated: function(tabId, changeInfo) { |
| 113 if (changeInfo.status != 'complete') | 112 if (changeInfo.status != 'complete') |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 * Provides all feedback once ChromeVox's focus changes. | 236 * Provides all feedback once ChromeVox's focus changes. |
| 238 * @param {Object} evt | 237 * @param {Object} evt |
| 239 */ | 238 */ |
| 240 onEventDefault: function(evt) { | 239 onEventDefault: function(evt) { |
| 241 var node = evt.target; | 240 var node = evt.target; |
| 242 if (!node) | 241 if (!node) |
| 243 return; | 242 return; |
| 244 | 243 |
| 245 var prevRange = this.currentRange_; | 244 var prevRange = this.currentRange_; |
| 246 this.currentRange_ = cursors.Range.fromNode(node); | 245 this.currentRange_ = cursors.Range.fromNode(node); |
| 246 |
| 247 // Don't process nodes inside of web content if ChromeVox Next is inactive. |
| 248 if (node.root.role == chrome.automation.RoleType.rootWebArea && |
| 249 !this.active_) |
| 250 return; |
| 251 |
| 247 new Output(this.currentRange_, prevRange, evt.type); | 252 new Output(this.currentRange_, prevRange, evt.type); |
| 248 }, | 253 }, |
| 249 | 254 |
| 250 /** | 255 /** |
| 251 * Provides all feedback once a load complete event fires. | 256 * Provides all feedback once a load complete event fires. |
| 252 * @param {Object} evt | 257 * @param {Object} evt |
| 253 */ | 258 */ |
| 254 onLoadComplete: function(evt) { | 259 onLoadComplete: function(evt) { |
| 255 var node = AutomationUtil.findNodePost(evt.target, | 260 var node = AutomationUtil.findNodePost(evt.target, |
| 256 Dir.FORWARD, | 261 Dir.FORWARD, |
| 257 AutomationPredicate.leaf); | 262 AutomationPredicate.leaf); |
| 258 if (node) | 263 if (node) |
| 259 this.currentRange_ = cursors.Range.fromNode(node); | 264 this.currentRange_ = cursors.Range.fromNode(node); |
| 260 | 265 |
| 261 if (this.currentRange_) | 266 if (this.currentRange_) |
| 262 new Output(this.currentRange_, null, evt.type); | 267 new Output(this.currentRange_, null, evt.type); |
| 263 }, | 268 }, |
| 264 | 269 |
| 265 /** | 270 /** |
| 266 * Provides all feedback once a text selection change event fires. | 271 * Provides all feedback once a text selection change event fires. |
| 267 * @param {Object} evt | 272 * @param {Object} evt |
| 268 */ | 273 */ |
| 269 onTextSelectionChanged: function(evt) { | 274 onTextOrTextSelectionChanged: function(evt) { |
| 270 if (!this.currentRange_) | 275 if (!this.currentRange_) |
| 271 this.currentRange_ = cursors.Range.fromNode(evt.target); | 276 this.currentRange_ = cursors.Range.fromNode(evt.target); |
| 272 | 277 |
| 273 var textChangeEvent = new cvox.TextChangeEvent( | 278 var textChangeEvent = new cvox.TextChangeEvent( |
| 274 evt.target.attributes.value, | 279 evt.target.attributes.value, |
| 275 evt.target.attributes.textSelStart, | 280 evt.target.attributes.textSelStart, |
| 276 evt.target.attributes.textSelEnd, | 281 evt.target.attributes.textSelEnd, |
| 277 true); // triggered by user | 282 true); // triggered by user |
| 278 if (!this.editableTextHandler || | 283 if (!this.editableTextHandler || |
| 279 evt.target != this.currentRange_.getStart().getNode()) { | 284 evt.target != this.currentRange_.getStart().getNode()) { |
| 280 this.editableTextHandler = | 285 this.editableTextHandler = |
| 281 new cvox.ChromeVoxEditableTextBase( | 286 new cvox.ChromeVoxEditableTextBase( |
| 282 textChangeEvent.value, | 287 textChangeEvent.value, |
| 283 textChangeEvent.start, | 288 textChangeEvent.start, |
| 284 textChangeEvent.end, | 289 textChangeEvent.end, |
| 285 evt.target.state['protected'], | 290 evt.target.state['protected'], |
| 286 cvox.ChromeVox.tts); | 291 cvox.ChromeVox.tts); |
| 287 } | 292 } |
| 288 | 293 |
| 289 this.editableTextHandler.changed(textChangeEvent); | 294 this.editableTextHandler.changed(textChangeEvent); |
| 295 new Output(this.currentRange_, null, evt.type, {braille: true}); |
| 290 }, | 296 }, |
| 291 | 297 |
| 292 /** | 298 /** |
| 293 * @private | 299 * @private |
| 294 * @param {string} url | 300 * @param {string} url |
| 295 * @return {boolean} Whether the given |url| is whitelisted. | 301 * @return {boolean} Whether the given |url| is whitelisted. |
| 296 */ | 302 */ |
| 297 isWhitelisted_: function(url) { | 303 isWhitelisted_: function(url) { |
| 298 return this.whitelist_.some(function(item) { | 304 return this.whitelist_.some(function(item) { |
| 299 return url.indexOf(item) != -1; | 305 return url.indexOf(item) != -1; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 316 * @param {{classic: boolean, next: boolean}=} opt_options Forceably set. | 322 * @param {{classic: boolean, next: boolean}=} opt_options Forceably set. |
| 317 */ | 323 */ |
| 318 toggleChromeVoxVersion: function(opt_options) { | 324 toggleChromeVoxVersion: function(opt_options) { |
| 319 if (!opt_options) { | 325 if (!opt_options) { |
| 320 opt_options = {}; | 326 opt_options = {}; |
| 321 opt_options.next = !this.active_; | 327 opt_options.next = !this.active_; |
| 322 opt_options.classic = !opt_options.next; | 328 opt_options.classic = !opt_options.next; |
| 323 } | 329 } |
| 324 | 330 |
| 325 if (opt_options.next) { | 331 if (opt_options.next) { |
| 332 if (!chrome.commands.onCommand.hasListener(this.onGotCommand)) |
| 333 chrome.commands.onCommand.addListener(this.onGotCommand); |
| 334 |
| 326 chrome.automation.getTree(this.onGotTree); | 335 chrome.automation.getTree(this.onGotTree); |
| 327 this.active_ = true; | 336 this.active_ = true; |
| 328 } else { | 337 } else { |
| 338 if (chrome.commands.onCommand.hasListener(this.onGotCommand)) |
| 339 chrome.commands.onCommand.removeListener(this.onGotCommand); |
| 340 |
| 329 if (this.active_) { | 341 if (this.active_) { |
| 330 for (var eventType in this.listeners_) { | 342 for (var eventType in this.listeners_) { |
| 331 this.currentRange_.getStart().getNode().root.removeEventListener( | 343 this.currentRange_.getStart().getNode().root.removeEventListener( |
| 332 eventType, this.listeners_[eventType], true); | 344 eventType, this.listeners_[eventType], true); |
| 333 } | 345 } |
| 334 } | 346 } |
| 335 this.active_ = false; | 347 this.active_ = false; |
| 336 } | 348 } |
| 337 | 349 |
| 338 chrome.tabs.query({active: true}, function(tabs) { | 350 chrome.tabs.query({active: true}, function(tabs) { |
| 339 if (opt_options.classic) { | 351 if (opt_options.classic) { |
| 340 cvox.ChromeVox.injectChromeVoxIntoTabs(tabs); | 352 cvox.ChromeVox.injectChromeVoxIntoTabs(tabs); |
| 341 } else { | 353 } else { |
| 342 tabs.forEach(function(tab) { | 354 tabs.forEach(function(tab) { |
| 343 this.disableClassicChromeVox_(tab.id); | 355 this.disableClassicChromeVox_(tab.id); |
| 344 }.bind(this)); | 356 }.bind(this)); |
| 345 } | 357 } |
| 346 }.bind(this)); | 358 }.bind(this)); |
| 347 } | 359 } |
| 348 }; | 360 }; |
| 349 | 361 |
| 350 /** @type {Background} */ | 362 /** @type {Background} */ |
| 351 global.backgroundObj = new Background(); | 363 global.backgroundObj = new Background(); |
| 352 | 364 |
| 353 }); // goog.scope | 365 }); // goog.scope |
| OLD | NEW |