Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js

Issue 2079073002: Make ChromeVox Next a setting in options page. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 /** @type {boolean} @private */ 139 /** @type {boolean} @private */
140 this.inExcursion_ = false; 140 this.inExcursion_ = false;
141 141
142 if (!chrome.accessibilityPrivate.setKeyboardListener) 142 if (!chrome.accessibilityPrivate.setKeyboardListener)
143 chrome.accessibilityPrivate.setKeyboardListener = function() {}; 143 chrome.accessibilityPrivate.setKeyboardListener = function() {};
144 144
145 if (cvox.ChromeVox.isChromeOS) { 145 if (cvox.ChromeVox.isChromeOS) {
146 chrome.accessibilityPrivate.onAccessibilityGesture.addListener( 146 chrome.accessibilityPrivate.onAccessibilityGesture.addListener(
147 this.onAccessibilityGesture_); 147 this.onAccessibilityGesture_);
148 148
149 if (localStorage['mode']) {
150 var mode = localStorage['mode'];
151 this.setMode(mode);
152 }
153
149 Notifications.onStartup(); 154 Notifications.onStartup();
150 }}; 155 }};
151 156
152 /** 157 /**
153 * @const {string} 158 * @const {string}
154 */ 159 */
155 Background.ISSUE_URL = 'https://code.google.com/p/chromium/issues/entry?' + 160 Background.ISSUE_URL = 'https://code.google.com/p/chromium/issues/entry?' +
156 'labels=Type-Bug,Pri-2,cvox2,OS-Chrome&' + 161 'labels=Type-Bug,Pri-2,cvox2,OS-Chrome&' +
157 'components=UI>accessibility&' + 162 'components=UI>accessibility&' +
158 'description='; 163 'description=';
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 __proto__: ChromeVoxState.prototype, 198 __proto__: ChromeVoxState.prototype,
194 199
195 /** 200 /**
196 * @override 201 * @override
197 */ 202 */
198 getMode: function() { 203 getMode: function() {
199 return this.mode_; 204 return this.mode_;
200 }, 205 },
201 206
202 /** 207 /**
208 * This method sets the global mode for ChromeVox.
209 * The following transitions are supported:
210 * classic to force next
211 * compat to force next
212 * force next to classic
213 * force next to compat
203 * @override 214 * @override
204 */ 215 */
205 setMode: function(mode, opt_injectClassic) { 216 setMode: function(mode, opt_injectClassic) {
217 var newMode = mode;
218 var oldMode = this.mode_;
219 this.mode_ = newMode;
220 localStorage['mode'] = mode;
dmazzoni 2016/06/20 19:49:03 Do you want to be setting the mode to things like
David Tseng 2016/06/20 22:31:08 Now only storing the "nextness" state.
221
206 // Switching key maps potentially affects the key codes that involve 222 // Switching key maps potentially affects the key codes that involve
207 // sequencing. Without resetting this list, potentially stale key codes 223 // sequencing. Without resetting this list, potentially stale key codes
208 // remain. The key codes themselves get pushed in 224 // remain. The key codes themselves get pushed in
209 // cvox.KeySequence.deserialize which gets called by cvox.KeyMap. 225 // cvox.KeySequence.deserialize which gets called by cvox.KeyMap.
210 cvox.ChromeVox.sequenceSwitchKeyCodes = []; 226 cvox.ChromeVox.sequenceSwitchKeyCodes = [];
211 if (mode === ChromeVoxMode.CLASSIC || mode === ChromeVoxMode.COMPAT) 227 if (window['prefs']) {
212 window['prefs'].switchToKeyMap('keymap_classic'); 228 if (newMode === ChromeVoxMode.CLASSIC || mode === ChromeVoxMode.COMPAT)
213 else 229 window['prefs'].switchToKeyMap('keymap_classic');
214 window['prefs'].switchToKeyMap('keymap_next'); 230 else
231 window['prefs'].switchToKeyMap('keymap_next');
232 }
215 233
216 if (mode == ChromeVoxMode.CLASSIC) { 234 if (newMode == ChromeVoxMode.CLASSIC) {
217 if (chrome.commands && 235 if (chrome.commands &&
218 chrome.commands.onCommand.hasListener(this.onGotCommand)) 236 chrome.commands.onCommand.hasListener(this.onGotCommand))
219 chrome.commands.onCommand.removeListener(this.onGotCommand); 237 chrome.commands.onCommand.removeListener(this.onGotCommand);
220 chrome.accessibilityPrivate.setKeyboardListener(false, false); 238 chrome.accessibilityPrivate.setKeyboardListener(false, false);
221 } else { 239 } else {
222 if (chrome.commands && 240 if (chrome.commands &&
223 !chrome.commands.onCommand.hasListener(this.onGotCommand)) 241 !chrome.commands.onCommand.hasListener(this.onGotCommand))
224 chrome.commands.onCommand.addListener(this.onGotCommand); 242 chrome.commands.onCommand.addListener(this.onGotCommand);
225 chrome.accessibilityPrivate.setKeyboardListener( 243 chrome.accessibilityPrivate.setKeyboardListener(
226 true, cvox.ChromeVox.isStickyPrefOn); 244 true, cvox.ChromeVox.isStickyPrefOn);
227 } 245 }
228 246
229 // note that |this.currentRange_| can *change* because the request is 247 // note that |this.currentRange_| can *change* because the request is
230 // async. Save it to ensure we're looking at the currentRange at this moment 248 // async. Save it to ensure we're looking at the currentRange at this moment
231 // in time. 249 // in time.
232 var cur = this.currentRange_; 250 var cur = this.currentRange_;
233 chrome.tabs.query({active: true}, function(tabs) { 251 chrome.tabs.query({active: true}, function(tabs) {
234 if (mode === ChromeVoxMode.CLASSIC) { 252 if (newMode === ChromeVoxMode.CLASSIC) {
235 // Generally, we don't want to inject classic content scripts as it is 253 // Generally, we don't want to inject classic content scripts as it is
236 // done by the extension system at document load. The exception is when 254 // done by the extension system at document load. The exception is when
237 // we toggle classic on manually as part of a user command. 255 // we toggle classic on manually as part of a user command.
238 if (opt_injectClassic) 256 if (opt_injectClassic)
239 cvox.ChromeVox.injectChromeVoxIntoTabs(tabs); 257 cvox.ChromeVox.injectChromeVoxIntoTabs(tabs);
240 } else { 258 } else {
241 // When in compat mode, if the focus is within the desktop tree proper, 259 // When in compat mode, if the focus is within the desktop tree proper,
242 // then do not disable content scripts. 260 // then do not disable content scripts.
243 if (cur && !cur.isWebRange()) 261 if (cur && !cur.isWebRange())
244 return; 262 return;
245 263
246 this.disableClassicChromeVox_(); 264 this.disableClassicChromeVox_();
247 } 265 }
248 }.bind(this)); 266 }.bind(this));
249 267
250 // If switching out of a ChromeVox Next mode, make sure we cancel 268 // If switching out of a ChromeVox Next mode, make sure we cancel
251 // the progress loading sound just in case. 269 // the progress loading sound just in case.
252 if ((this.mode_ === ChromeVoxMode.NEXT || 270 if ((oldMode === ChromeVoxMode.NEXT ||
253 this.mode_ === ChromeVoxMode.FORCE_NEXT) && 271 oldMode === ChromeVoxMode.FORCE_NEXT) &&
254 this.mode_ != mode) { 272 oldMode != mode) {
255 cvox.ChromeVox.earcons.cancelEarcon(cvox.Earcon.PAGE_START_LOADING); 273 cvox.ChromeVox.earcons.cancelEarcon(cvox.Earcon.PAGE_START_LOADING);
256 } 274 }
257 275
258 if (mode === ChromeVoxMode.NEXT || 276 if (newMode === ChromeVoxMode.NEXT ||
259 mode === ChromeVoxMode.FORCE_NEXT) { 277 newMode === ChromeVoxMode.FORCE_NEXT) {
260 (new PanelCommand(PanelCommandType.ENABLE_MENUS)).send(); 278 (new PanelCommand(PanelCommandType.ENABLE_MENUS)).send();
261 if (cvox.TabsApiHandler) 279 if (cvox.TabsApiHandler)
262 cvox.TabsApiHandler.shouldOutputSpeechAndBraille = false; 280 cvox.TabsApiHandler.shouldOutputSpeechAndBraille = false;
263 } else { 281 } else {
264 (new PanelCommand(PanelCommandType.DISABLE_MENUS)).send(); 282 (new PanelCommand(PanelCommandType.DISABLE_MENUS)).send();
265 if (cvox.TabsApiHandler) 283 if (cvox.TabsApiHandler)
266 cvox.TabsApiHandler.shouldOutputSpeechAndBraille = true; 284 cvox.TabsApiHandler.shouldOutputSpeechAndBraille = true;
267 } 285 }
268 286
269 // If switching to Classic from any automation-API-based mode, 287 // If switching to Classic from any automation-API-based mode,
270 // clear the focus ring. 288 // clear the focus ring.
271 if (mode === ChromeVoxMode.CLASSIC && mode != this.mode_) { 289 if (newMode === ChromeVoxMode.CLASSIC && newMode != oldMode) {
272 if (cvox.ChromeVox.isChromeOS) 290 if (cvox.ChromeVox.isChromeOS)
273 chrome.accessibilityPrivate.setFocusRing([]); 291 chrome.accessibilityPrivate.setFocusRing([]);
274 } 292 }
275 293
276 // If switching away from Classic to any automation-API-based mode, 294 // If switching away from Classic to any automation-API-based mode,
277 // update the range based on what's focused. 295 // update the range based on what's focused.
278 if (this.mode_ === ChromeVoxMode.CLASSIC && mode != this.mode_) { 296 if (oldMode === ChromeVoxMode.CLASSIC && newMode != oldMode) {
279 chrome.automation.getFocus((function(focus) { 297 chrome.automation.getFocus((function(focus) {
280 if (focus) 298 if (focus)
281 this.setCurrentRange(cursors.Range.fromNode(focus)); 299 this.setCurrentRange(cursors.Range.fromNode(focus));
282 }).bind(this)); 300 }).bind(this));
283 } 301 }
284
285 this.mode_ = mode;
286 }, 302 },
287 303
288 /** 304 /**
289 * Mode refreshes takes into account both |url| and the current ChromeVox 305 * Toggles between force next and classic/compat modes.
290 * range. The latter gets used to decide if the user is or isn't in web 306 * This toggle automatically handles deciding between classic/compat based on
291 * content. The focused state also needs to be set for this info to be 307 * the start of the current range.
292 * reliable. 308 * @param {boolean=} opt_setValue Directly set to force next (true) or
309 * classic/compat (false).
310 * @return {boolean} True to announce current position.
311 */
312 toggleMode: function(opt_setValue) {
dmazzoni 2016/06/20 19:49:03 maybe this should be toggleNext since there are fo
David Tseng 2016/06/20 22:31:08 Done.
313 var useClassicOrCompatForCurrentRange = function() {
314 var start;
315 if (this.currentRange && this.currentRange.isValid())
316 start = this.currentRange.start.node;
317 if (!start)
318 return ChromeVoxMode.CLASSIC;
dmazzoni 2016/06/20 19:49:03 indentation
David Tseng 2016/06/20 22:31:08 Done.
319
320 var root = AutomationUtil.getTopLevelRoot(start);
321 if (!root)
322 return ChromeVoxMode.CLASSIC;
323 return this.isWhitelistedForCompat_(root.docUrl) ?
324 ChromeVoxMode.COMPAT : ChromeVoxMode.CLASSIC;
325 }.bind(this);
326
327 var newMode;
328 if (opt_setValue !== undefined) {
329 if (opt_setValue)
330 newMode = ChromeVoxMode.FORCE_NEXT;
331 else
332 newMode = useClassicOrCompatForCurrentRange();
333 } else {
334 if (this.mode_ == ChromeVoxMode.FORCE_NEXT)
335 newMode = useClassicOrCompatForCurrentRange();
336 else
337 newMode = ChromeVoxMode.FORCE_NEXT;
338 }
339 this.setMode(newMode, true);
dmazzoni 2016/06/20 19:49:03 Can you just call refreshMode() here? It seems li
David Tseng 2016/06/20 22:31:08 RefreshMode differs in the mode transitions it all
dmazzoni 2016/06/20 22:41:44 Why not just refreshMode to handle all of those ca
340
341 var isClassic =
342 newMode == ChromeVoxMode.CLASSIC || newMode == ChromeVoxMode.COMPAT;
343
344 var announce = Msgs.getMsg(isClassic ?
345 'switch_to_classic' : 'switch_to_next');
346
347 cvox.ChromeVox.tts.speak(
348 announce, cvox.QueueMode.FLUSH, {doNotInterrupt: true});
349
350 Notifications.onModeChange();
351
352 // If the new mode is Classic, return false now so we don't announce
353 // anything more.
354 return newMode != ChromeVoxMode.CLASSIC;
355 },
356
357 /**
358 * Refreshes ChromeVox's mode based on a node.
359 * Note that this method disallows switching from force next mode to any other
360 * mode. See toggleMode.
293 * @override 361 * @override
294 */ 362 */
295 refreshMode: function(node) { 363 refreshMode: function(node) {
296 // Mode changes are based upon the top level web root. 364 // Mode changes are based upon the top level web root.
297 var root = node.root; 365 var root = AutomationUtil.getTopLevelRoot(node);
298 while (root &&
299 root.parent &&
300 root.parent.root &&
301 root.parent.root.role != RoleType.desktop) {
302 root = root.parent.root;
303 }
304
305 var url = ''; 366 var url = '';
306 if (root && root.role == RoleType.rootWebArea) 367 if (root)
307 url = root.docUrl; 368 url = root.docUrl;
308 369
309 var mode = this.mode_; 370 var mode = this.mode_;
310 if (mode != ChromeVoxMode.FORCE_NEXT) { 371 if (mode != ChromeVoxMode.FORCE_NEXT) {
311 if (this.isWhitelistedForNext_(url)) { 372 if (this.isWhitelistedForNext_(url)) {
312 mode = ChromeVoxMode.NEXT; 373 mode = ChromeVoxMode.NEXT;
313 } else if (this.isBlacklistedForClassic_(url) || (this.currentRange_ && 374 } else if (this.isWhitelistedForCompat_(url)) {
314 !this.currentRange_.isWebRange() &&
315 this.currentRange_.start.node.state.focused)) {
316 mode = ChromeVoxMode.COMPAT; 375 mode = ChromeVoxMode.COMPAT;
317 } else { 376 } else {
318 mode = ChromeVoxMode.CLASSIC; 377 mode = ChromeVoxMode.CLASSIC;
319 } 378 }
320 } 379 }
321 380
322 this.setMode(mode); 381 this.setMode(mode);
323 }, 382 },
324 383
325 /** 384 /**
326 * @override 385 * @override
327 */ 386 */
328 getCurrentRange: function() { 387 getCurrentRange: function() {
329 if (this.currentRange_ && this.currentRange_.isValid()) 388 if (this.currentRange_ && this.currentRange_.isValid())
330 return this.currentRange_; 389 return this.currentRange_;
331 return null; 390 return null;
332 }, 391 },
333 392
334 /** 393 /**
335 * @override 394 * @override
336 */ 395 */
337 setCurrentRange: function(newRange) { 396 setCurrentRange: function(newRange) {
338 if (!newRange) 397 if (!newRange)
339 return; 398 return;
340 399
341 // Is the range invalid? 400 // Is the range invalid?
342 if (newRange.start.node.role === undefined || 401 if (!newRange.isValid()) {
343 newRange.end.node.role === undefined) {
344 // Restore range to the focused location. 402 // Restore range to the focused location.
345 chrome.automation.getFocus(function(f) { 403 chrome.automation.getFocus(function(f) {
346 newRange = cursors.Range.fromNode(f); 404 newRange = cursors.Range.fromNode(f);
347 }); 405 });
348 } 406 }
349 407
350 if (!this.inExcursion_) 408 if (!this.inExcursion_)
351 this.savedRange_ = new cursors.Range(newRange.start, newRange.end); 409 this.savedRange_ = new cursors.Range(newRange.start, newRange.end);
352 410
353 this.currentRange_ = newRange; 411 this.currentRange_ = newRange;
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 return false; 658 return false;
601 659
602 cvox.ChromeVox.isActive = !cvox.ChromeVox.isActive; 660 cvox.ChromeVox.isActive = !cvox.ChromeVox.isActive;
603 if (!cvox.ChromeVox.isActive) { 661 if (!cvox.ChromeVox.isActive) {
604 var msg = Msgs.getMsg('chromevox_inactive'); 662 var msg = Msgs.getMsg('chromevox_inactive');
605 cvox.ChromeVox.tts.speak(msg, cvox.QueueMode.FLUSH); 663 cvox.ChromeVox.tts.speak(msg, cvox.QueueMode.FLUSH);
606 return false; 664 return false;
607 } 665 }
608 break; 666 break;
609 case 'toggleChromeVoxVersion': 667 case 'toggleChromeVoxVersion':
610 var newMode; 668 if (!this.toggleMode())
611 if (this.mode_ == ChromeVoxMode.FORCE_NEXT) { 669 return false;
612 var inWeb = current.isWebRange();
613 newMode = inWeb ? ChromeVoxMode.CLASSIC : ChromeVoxMode.COMPAT;
614 } else {
615 newMode = ChromeVoxMode.FORCE_NEXT;
616 }
617 this.setMode(newMode, true);
618
619 var isClassic =
620 newMode == ChromeVoxMode.CLASSIC || newMode == ChromeVoxMode.COMPAT;
621
622 // Leaving unlocalized as 'next' isn't an official name.
623 cvox.ChromeVox.tts.speak(isClassic ?
624 'classic' : 'next', cvox.QueueMode.FLUSH, {doNotInterrupt: true});
625
626 // If the new mode is Classic, return now so we don't announce
627 // anything more.
628 if (newMode == ChromeVoxMode.CLASSIC)
629 return false;
630 break; 670 break;
631 case 'toggleStickyMode': 671 case 'toggleStickyMode':
632 cvox.ChromeVoxBackground.setPref('sticky', 672 cvox.ChromeVoxBackground.setPref('sticky',
633 !cvox.ChromeVox.isStickyPrefOn, 673 !cvox.ChromeVox.isStickyPrefOn,
634 true); 674 true);
635 675
636 if (cvox.ChromeVox.isStickyPrefOn) 676 if (cvox.ChromeVox.isStickyPrefOn)
637 chrome.accessibilityPrivate.setKeyboardListener(true, true); 677 chrome.accessibilityPrivate.setKeyboardListener(true, true);
638 else 678 else
639 chrome.accessibilityPrivate.setKeyboardListener(true, false); 679 chrome.accessibilityPrivate.setKeyboardListener(true, false);
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 * @return {boolean} 1030 * @return {boolean}
991 * @private 1031 * @private
992 */ 1032 */
993 shouldEnableClassicForUrl_: function(url) { 1033 shouldEnableClassicForUrl_: function(url) {
994 return this.mode_ != ChromeVoxMode.FORCE_NEXT && 1034 return this.mode_ != ChromeVoxMode.FORCE_NEXT &&
995 !this.isBlacklistedForClassic_(url) && 1035 !this.isBlacklistedForClassic_(url) &&
996 !this.isWhitelistedForNext_(url); 1036 !this.isWhitelistedForNext_(url);
997 }, 1037 },
998 1038
999 /** 1039 /**
1040 * Compat mode is on if any of the following are true:
1041 * 1. a url is blacklisted for Classic.
1042 * 2. the current range is not within web content.
1043 * @param {string} url
1044 */
1045 isWhitelistedForCompat_: function(url) {
1046 return this.isBlacklistedForClassic_(url) || (this.currentRange_ &&
1047 !this.currentRange_.isWebRange() &&
1048 this.currentRange_.start.node.state.focused);
1049 },
1050
1051 /**
1000 * @param {string} url 1052 * @param {string} url
1001 * @return {boolean} 1053 * @return {boolean}
1002 * @private 1054 * @private
1003 */ 1055 */
1004 isBlacklistedForClassic_: function(url) { 1056 isBlacklistedForClassic_: function(url) {
1005 return this.classicBlacklistRegExp_.test(url); 1057 return this.classicBlacklistRegExp_.test(url);
1006 }, 1058 },
1007 1059
1008 /** 1060 /**
1009 * @param {string} url 1061 * @param {string} url
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
1194 return glob.replace(/[.+^$(){}|[\]\\]/g, '\\$&') 1246 return glob.replace(/[.+^$(){}|[\]\\]/g, '\\$&')
1195 .replace(/\*/g, '.*') 1247 .replace(/\*/g, '.*')
1196 .replace(/\?/g, '.'); 1248 .replace(/\?/g, '.');
1197 }).join('|') + ')$'); 1249 }).join('|') + ')$');
1198 }; 1250 };
1199 1251
1200 /** @type {Background} */ 1252 /** @type {Background} */
1201 global.backgroundObj = new Background(); 1253 global.backgroundObj = new Background();
1202 1254
1203 }); // goog.scope 1255 }); // goog.scope
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698