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'); |
11 goog.provide('global'); | 11 goog.provide('global'); |
12 | 12 |
13 goog.require('AutomationPredicate'); | 13 goog.require('AutomationPredicate'); |
14 goog.require('AutomationUtil'); | 14 goog.require('AutomationUtil'); |
15 goog.require('Output'); | 15 goog.require('Output'); |
16 goog.require('Output.EventType'); | 16 goog.require('Output.EventType'); |
17 goog.require('cursors.Cursor'); | 17 goog.require('cursors.Cursor'); |
18 goog.require('cvox.ChromeVoxEditableTextBase'); | 18 goog.require('cvox.ChromeVoxEditableTextBase'); |
19 goog.require('cvox.TabsApiHandler'); | |
20 | 19 |
21 // Define types here due to editable_text.js's implicit dependency with | 20 // Define types here due to editable_text.js's implicit dependency with |
22 // ChromeVoxEventWatcher. | 21 // ChromeVoxEventWatcher. |
23 /** @type {Object} */ | 22 /** @type {Object} */ |
24 cvox.ChromeVoxEventWatcher; | 23 cvox.ChromeVoxEventWatcher; |
25 /** @type {function(boolean)} */ | 24 /** @type {function(boolean)} */ |
26 cvox.ChromeVoxEventWatcher.handleTextChanged; | 25 cvox.ChromeVoxEventWatcher.handleTextChanged; |
27 /** @type {function()} */ | 26 /** @type {function()} */ |
28 cvox.ChromeVoxEventWatcher.setUpTextHandler; | 27 cvox.ChromeVoxEventWatcher.setUpTextHandler; |
29 | 28 |
30 goog.scope(function() { | 29 goog.scope(function() { |
31 var AutomationNode = chrome.automation.AutomationNode; | 30 var AutomationNode = chrome.automation.AutomationNode; |
32 var Dir = AutomationUtil.Dir; | 31 var Dir = AutomationUtil.Dir; |
33 var EventType = chrome.automation.EventType; | 32 var EventType = chrome.automation.EventType; |
34 | 33 |
35 /** | 34 /** |
36 * ChromeVox2 background page. | 35 * ChromeVox2 background page. |
37 * @constructor | 36 * @constructor |
38 */ | 37 */ |
39 Background = function() { | 38 Background = function() { |
40 /** | 39 /** |
41 * A list of site substring patterns to use with ChromeVox next. Keep these | 40 * A list of site substring patterns to use with ChromeVox next. Keep these |
42 * strings relatively specific. | 41 * strings relatively specific. |
43 * @type {!Array.<string>} | 42 * @type {!Array.<string>} |
44 * @private | 43 * @private |
45 */ | 44 */ |
46 this.whitelist_ = ['chromevox_next_test']; | 45 this.whitelist_ = ['chromevox_next_test']; |
47 | 46 |
48 /** | 47 /** |
49 * @type {cvox.TabsApiHandler} | |
50 * @private | |
51 */ | |
52 this.tabsHandler_ = new cvox.TabsApiHandler(cvox.ChromeVox.tts, | |
53 cvox.ChromeVox.braille, | |
54 cvox.ChromeVox.earcons); | |
55 | |
56 /** | |
57 * @type {cursors.Range} | 48 * @type {cursors.Range} |
58 * @private | 49 * @private |
59 */ | 50 */ |
60 this.currentRange_ = null; | 51 this.currentRange_ = null; |
61 | 52 |
62 /** | 53 /** |
63 * Whether ChromeVox Next is active. | 54 * Whether ChromeVox Next is active. |
64 * @type {boolean} | 55 * @type {boolean} |
65 * @private | 56 * @private |
66 */ | 57 */ |
(...skipping 17 matching lines...) Expand all Loading... |
84 menuEnd: this.onEventDefault, | 75 menuEnd: this.onEventDefault, |
85 menuListValueChanged: this.onEventDefault, | 76 menuListValueChanged: this.onEventDefault, |
86 loadComplete: this.onLoadComplete, | 77 loadComplete: this.onLoadComplete, |
87 textChanged: this.onTextOrTextSelectionChanged, | 78 textChanged: this.onTextOrTextSelectionChanged, |
88 textSelectionChanged: this.onTextOrTextSelectionChanged, | 79 textSelectionChanged: this.onTextOrTextSelectionChanged, |
89 valueChanged: this.onEventDefault | 80 valueChanged: this.onEventDefault |
90 }; | 81 }; |
91 | 82 |
92 // Register listeners for ... | 83 // Register listeners for ... |
93 // Desktop. | 84 // Desktop. |
94 chrome.automation.getDesktop(this.onGotTree); | 85 chrome.automation.getDesktop(this.onGotDesktop); |
95 | 86 |
96 // Tabs. | 87 // Tabs. |
97 chrome.tabs.onUpdated.addListener(this.onTabUpdated); | 88 chrome.tabs.onUpdated.addListener(this.onTabUpdated); |
98 }; | 89 }; |
99 | 90 |
100 Background.prototype = { | 91 Background.prototype = { |
101 /** | 92 /** |
102 * Handles chrome.tabs.onUpdated. | 93 * Handles chrome.tabs.onUpdated. |
103 * @param {number} tabId | 94 * @param {number} tabId |
104 * @param {Object} changeInfo | 95 * @param {Object} changeInfo |
105 */ | 96 */ |
106 onTabUpdated: function(tabId, changeInfo) { | 97 onTabUpdated: function(tabId, changeInfo) { |
107 if (changeInfo.status != 'complete') | 98 if (changeInfo.status != 'complete') |
108 return; | 99 return; |
109 chrome.tabs.get(tabId, function(tab) { | 100 chrome.tabs.get(tabId, function(tab) { |
110 if (!tab.url) | 101 if (!tab.url) |
111 return; | 102 return; |
112 | 103 |
113 var next = this.isWhitelisted_(tab.url); | 104 var next = this.isWhitelisted_(tab.url); |
114 | 105 |
115 this.toggleChromeVoxVersion({next: next, classic: !next}); | 106 this.toggleChromeVoxVersion({next: next, classic: !next}); |
116 }.bind(this)); | 107 }.bind(this)); |
117 }, | 108 }, |
118 | 109 |
119 /** | 110 /** |
120 * Handles all setup once a new automation tree appears. | 111 * Handles all setup once a new automation tree appears. |
121 * @param {chrome.automation.AutomationNode} root | 112 * @param {chrome.automation.AutomationNode} desktop |
122 */ | 113 */ |
123 onGotTree: function(root) { | 114 onGotDesktop: function(desktop) { |
124 // Register all automation event listeners. | 115 // Register all automation event listeners. |
125 for (var eventType in this.listeners_) | 116 for (var eventType in this.listeners_) |
126 root.addEventListener(eventType, this.listeners_[eventType], true); | 117 desktop.addEventListener(eventType, this.listeners_[eventType], true); |
127 | 118 |
128 if (root.attributes.docLoaded) { | 119 var root = desktop.find({role: chrome.automation.RoleType.rootWebArea, |
| 120 state: {focused: true}}); |
| 121 if (root && root.attributes.docLoaded) { |
129 this.onLoadComplete( | 122 this.onLoadComplete( |
130 {target: root, type: chrome.automation.EventType.loadComplete}); | 123 {target: root, type: chrome.automation.EventType.loadComplete}); |
131 } | 124 } |
132 }, | 125 }, |
133 | 126 |
134 /** | 127 /** |
135 * Handles chrome.commands.onCommand. | 128 * Handles chrome.commands.onCommand. |
136 * @param {string} command | 129 * @param {string} command |
137 */ | 130 */ |
138 onGotCommand: function(command) { | 131 onGotCommand: function(command) { |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 */ | 357 */ |
365 toggleChromeVoxVersion: function(opt_options) { | 358 toggleChromeVoxVersion: function(opt_options) { |
366 if (!opt_options) { | 359 if (!opt_options) { |
367 opt_options = {}; | 360 opt_options = {}; |
368 opt_options.next = !this.active_; | 361 opt_options.next = !this.active_; |
369 opt_options.classic = !opt_options.next; | 362 opt_options.classic = !opt_options.next; |
370 } | 363 } |
371 | 364 |
372 if (opt_options.next) { | 365 if (opt_options.next) { |
373 if (!chrome.commands.onCommand.hasListener(this.onGotCommand)) | 366 if (!chrome.commands.onCommand.hasListener(this.onGotCommand)) |
374 chrome.commands.onCommand.addListener(this.onGotCommand); | 367 chrome.commands.onCommand.addListener(this.onGotCommand); |
375 | 368 this.active_ = true; |
376 if (!this.active_) | |
377 chrome.automation.getTree(this.onGotTree); | |
378 this.active_ = true; | |
379 } else { | 369 } else { |
380 if (chrome.commands.onCommand.hasListener(this.onGotCommand)) | 370 if (chrome.commands.onCommand.hasListener(this.onGotCommand)) |
381 chrome.commands.onCommand.removeListener(this.onGotCommand); | 371 chrome.commands.onCommand.removeListener(this.onGotCommand); |
382 | |
383 if (this.active_) { | |
384 for (var eventType in this.listeners_) { | |
385 this.currentRange_.getStart().getNode().root.removeEventListener( | |
386 eventType, this.listeners_[eventType], true); | |
387 } | |
388 } | |
389 this.active_ = false; | 372 this.active_ = false; |
390 } | 373 } |
391 | 374 |
392 chrome.tabs.query({active: true}, function(tabs) { | 375 chrome.tabs.query({active: true}, function(tabs) { |
393 if (opt_options.classic) { | 376 if (opt_options.classic) { |
394 // This case should do nothing because Classic gets injected by the | 377 // This case should do nothing because Classic gets injected by the |
395 // extension system via our manifest. Once ChromeVox Next is enabled | 378 // extension system via our manifest. Once ChromeVox Next is enabled |
396 // for tabs, re-enable. | 379 // for tabs, re-enable. |
397 // cvox.ChromeVox.injectChromeVoxIntoTabs(tabs); | 380 // cvox.ChromeVox.injectChromeVoxIntoTabs(tabs); |
398 } else { | 381 } else { |
399 tabs.forEach(function(tab) { | 382 tabs.forEach(function(tab) { |
400 this.disableClassicChromeVox_(tab.id); | 383 this.disableClassicChromeVox_(tab.id); |
401 }.bind(this)); | 384 }.bind(this)); |
402 } | 385 } |
403 }.bind(this)); | 386 }.bind(this)); |
404 } | 387 } |
405 }; | 388 }; |
406 | 389 |
407 /** @type {Background} */ | 390 /** @type {Background} */ |
408 global.backgroundObj = new Background(); | 391 global.backgroundObj = new Background(); |
409 | 392 |
410 }); // goog.scope | 393 }); // goog.scope |
OLD | NEW |