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

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

Issue 1191783002: Support Compat mode inside of the desktop tree. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@commands_alt
Patch Set: Resolve focus. Created 5 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 this.currentRange_ = null; 54 this.currentRange_ = null;
55 55
56 /** 56 /**
57 * Which variant of ChromeVox is active. 57 * Which variant of ChromeVox is active.
58 * @type {ChromeVoxMode} 58 * @type {ChromeVoxMode}
59 * @private 59 * @private
60 */ 60 */
61 this.mode_ = ChromeVoxMode.CLASSIC; 61 this.mode_ = ChromeVoxMode.CLASSIC;
62 62
63 /** @type {!ClassicCompatibility} @private */ 63 /** @type {!ClassicCompatibility} @private */
64 this.compat_ = new ClassicCompatibility(this.mode_ === ChromeVoxMode.COMPAT); 64 this.compat_ = new ClassicCompatibility();
65 65
66 // Manually bind all functions to |this|. 66 // Manually bind all functions to |this|.
67 for (var func in this) { 67 for (var func in this) {
68 if (typeof(this[func]) == 'function') 68 if (typeof(this[func]) == 'function')
69 this[func] = this[func].bind(this); 69 this[func] = this[func].bind(this);
70 } 70 }
71 71
72 /** 72 /**
73 * Maps an automation event to its listener. 73 * Maps an automation event to its listener.
74 * @type {!Object<EventType, function(Object) : void>} 74 * @type {!Object<EventType, function(Object) : void>}
75 */ 75 */
76 this.listeners_ = { 76 this.listeners_ = {
77 alert: this.onEventDefault, 77 alert: this.onEventDefault,
78 focus: this.onEventDefault, 78 focus: this.onEventDefault,
79 hover: this.onEventDefault, 79 hover: this.onEventDefault,
80 loadComplete: this.onLoadComplete, 80 loadComplete: this.onLoadComplete,
81 menuStart: this.onEventDefault, 81 menuStart: this.onEventDefault,
82 menuEnd: this.onEventDefault, 82 menuEnd: this.onEventDefault,
83 menuListValueChanged: this.onEventDefault, 83 menuListValueChanged: this.onEventDefault,
84 textChanged: this.onTextOrTextSelectionChanged, 84 textChanged: this.onTextOrTextSelectionChanged,
85 textSelectionChanged: this.onTextOrTextSelectionChanged, 85 textSelectionChanged: this.onTextOrTextSelectionChanged,
86 valueChanged: this.onValueChanged 86 valueChanged: this.onValueChanged
87 }; 87 };
88 88
89 // Register listeners for ... 89 // Register listeners for ...
90 // Desktop.
91 chrome.automation.getDesktop(this.onGotDesktop); 90 chrome.automation.getDesktop(this.onGotDesktop);
91 chrome.commands.onCommand.addListener(this.onGotCommand);
92 }; 92 };
93 93
94 Background.prototype = { 94 Background.prototype = {
95 /** Forces ChromeVox Next to be active for all tabs. */ 95 /** Forces ChromeVox Next to be active for all tabs. */
96 forceChromeVoxNextActive: function() { 96 forceChromeVoxNextActive: function() {
97 this.setChromeVoxMode(ChromeVoxMode.FORCE_NEXT); 97 this.setChromeVoxMode(ChromeVoxMode.FORCE_NEXT);
98 }, 98 },
99 99
100 /** 100 /**
101 * Handles all setup once a new automation tree appears. 101 * Handles all setup once a new automation tree appears.
(...skipping 18 matching lines...) Expand all
120 type: chrome.automation.EventType.loadComplete}); 120 type: chrome.automation.EventType.loadComplete});
121 } 121 }
122 } 122 }
123 }, 123 },
124 124
125 /** 125 /**
126 * Handles chrome.commands.onCommand. 126 * Handles chrome.commands.onCommand.
127 * @param {string} command 127 * @param {string} command
128 * @param {boolean=} opt_skipCompat Whether to skip compatibility checks. 128 * @param {boolean=} opt_skipCompat Whether to skip compatibility checks.
129 */ 129 */
130 onGotCommand: function(command, opt_skipCompat) { 130 onGotCommand: function(command, opt_skipCompat) {
131 if (this.mode_ === ChromeVoxMode.CLASSIC) {
132 if (this.compat_.onGotClassicCommand(command))
133 return;
134 }
135
131 if (!this.currentRange_) 136 if (!this.currentRange_)
132 return; 137 return;
133 138
134 if (!opt_skipCompat) { 139 if (!opt_skipCompat && this.mode_ === ChromeVoxMode.COMPAT) {
135 if (this.compat_.onGotCommand(command)) 140 if (this.compat_.onGotCommand(command))
136 return; 141 return;
137 } 142 }
138 143
139 if (this.mode_ === ChromeVoxMode.CLASSIC)
140 return;
141
142 var current = this.currentRange_; 144 var current = this.currentRange_;
143 var dir = Dir.FORWARD; 145 var dir = Dir.FORWARD;
144 var pred = null; 146 var pred = null;
145 var predErrorMsg = undefined; 147 var predErrorMsg = undefined;
146 switch (command) { 148 switch (command) {
147 case 'nextCharacter': 149 case 'nextCharacter':
148 current = current.move(cursors.Unit.CHARACTER, Dir.FORWARD); 150 current = current.move(cursors.Unit.CHARACTER, Dir.FORWARD);
149 break; 151 break;
150 case 'previousCharacter': 152 case 'previousCharacter':
151 current = current.move(cursors.Unit.CHARACTER, Dir.BACKWARD); 153 current = current.move(cursors.Unit.CHARACTER, Dir.BACKWARD);
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 current = cursors.Range.fromNode(node); 323 current = cursors.Range.fromNode(node);
322 } else { 324 } else {
323 cvox.ChromeVox.tts.speak(cvox.ChromeVox.msgs.getMsg(predErrorMsg), 325 cvox.ChromeVox.tts.speak(cvox.ChromeVox.msgs.getMsg(predErrorMsg),
324 cvox.QueueMode.FLUSH); 326 cvox.QueueMode.FLUSH);
325 return; 327 return;
326 } 328 }
327 } 329 }
328 330
329 if (current) { 331 if (current) {
330 // TODO(dtseng): Figure out what it means to focus a range. 332 // TODO(dtseng): Figure out what it means to focus a range.
331 current.getStart().getNode().focus(); 333 var actionNode = current.getStart().getNode();
334 if (actionNode.role == chrome.automation.RoleType.inlineTextBox)
335 actionNode = actionNode.parent;
336 actionNode.focus();
332 337
333 var prevRange = this.currentRange_; 338 var prevRange = this.currentRange_;
334 this.currentRange_ = current; 339 this.currentRange_ = current;
340
335 new Output().withSpeechAndBraille( 341 new Output().withSpeechAndBraille(
336 this.currentRange_, prevRange, Output.EventType.NAVIGATE) 342 this.currentRange_, prevRange, Output.EventType.NAVIGATE)
337 .go(); 343 .go();
338 } 344 }
339 }, 345 },
340 346
341 /** 347 /**
342 * Provides all feedback once ChromeVox's focus changes. 348 * Provides all feedback once ChromeVox's focus changes.
343 * @param {Object} evt 349 * @param {Object} evt
344 */ 350 */
345 onEventDefault: function(evt) { 351 onEventDefault: function(evt) {
346 var node = evt.target; 352 var node = evt.target;
347 353
348 if (!node) 354 if (!node)
349 return; 355 return;
350 356
351 var prevRange = this.currentRange_; 357 var prevRange = this.currentRange_;
352 358
353 this.currentRange_ = cursors.Range.fromNode(node); 359 this.currentRange_ = cursors.Range.fromNode(node);
354 360
355 // Check to see if we've crossed roots. Only care about focused roots. 361 // Check to see if we've crossed roots. Continue if we've crossed roots or
356 if (!prevRange || 362 // are not within web content.
363 if (node.root.role == 'desktop' ||
364 !prevRange ||
357 (prevRange.getStart().getNode().root != node.root && 365 (prevRange.getStart().getNode().root != node.root &&
358 node.root.focused)) 366 node.root.focused))
359 this.setupChromeVoxVariants_(node.root.docUrl || ''); 367 this.setupChromeVoxVariants_(node.root.docUrl || '');
360 368
361 // Don't process nodes inside of web content if ChromeVox Next is inactive. 369 // Don't process nodes inside of web content if ChromeVox Next is inactive.
362 if (node.root.role != chrome.automation.RoleType.desktop && 370 if (node.root.role != chrome.automation.RoleType.desktop &&
363 this.mode_ === ChromeVoxMode.CLASSIC) { 371 this.mode_ === ChromeVoxMode.CLASSIC) {
364 chrome.accessibilityPrivate.setFocusRing([]); 372 chrome.accessibilityPrivate.setFocusRing([]);
365 return; 373 return;
366 } 374 }
367 375
376 // Don't output if focused node hasn't changed.
377 if (prevRange &&
378 evt.type == 'focus' &&
379 this.currentRange_.equals(prevRange))
380 return;
381
368 new Output().withSpeechAndBraille( 382 new Output().withSpeechAndBraille(
369 this.currentRange_, prevRange, evt.type) 383 this.currentRange_, prevRange, evt.type)
370 .go(); 384 .go();
371 }, 385 },
372 386
373 /** 387 /**
374 * Provides all feedback once a load complete event fires. 388 * Provides all feedback once a load complete event fires.
375 * @param {Object} evt 389 * @param {Object} evt
376 */ 390 */
377 onLoadComplete: function(evt) { 391 onLoadComplete: function(evt) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 } 519 }
506 output.withSpeech(range, null, Output.EventType.NAVIGATE); 520 output.withSpeech(range, null, Output.EventType.NAVIGATE);
507 output.go(); 521 output.go();
508 }, 522 },
509 523
510 /** 524 /**
511 * @return {boolean} 525 * @return {boolean}
512 * @private 526 * @private
513 */ 527 */
514 isWhitelistedForCompat_: function(url) { 528 isWhitelistedForCompat_: function(url) {
515 return url.indexOf('chrome://md-settings') != -1; 529 return url.indexOf('chrome://md-settings') != -1 || url === '';
516 }, 530 },
517 531
518 /** 532 /**
519 * @private 533 * @private
520 * @param {string} url 534 * @param {string} url
521 * @return {boolean} Whether the given |url| is whitelisted. 535 * @return {boolean} Whether the given |url| is whitelisted.
522 */ 536 */
523 isWhitelistedForNext_: function(url) { 537 isWhitelistedForNext_: function(url) {
524 return this.whitelist_.some(function(item) { 538 return this.whitelist_.some(function(item) {
525 return url.indexOf(item) != -1; 539 return url.indexOf(item) != -1;
526 }.bind(this)); 540 }.bind(this));
527 }, 541 },
528 542
529 /** 543 /**
530 * Setup ChromeVox variants. 544 * Setup ChromeVox variants.
531 * @param {string} url 545 * @param {string} url
532 * @private 546 * @private
533 */ 547 */
534 setupChromeVoxVariants_: function(url) { 548 setupChromeVoxVariants_: function(url) {
535 this.compat_.active = this.isWhitelistedForCompat_(url);
536 var mode = this.mode_; 549 var mode = this.mode_;
537 if (this.compat_.active) 550 if (mode != ChromeVoxMode.FORCE_NEXT) {
538 mode = ChromeVoxMode.COMPAT; 551 if (this.isWhitelistedForCompat_(url))
539 else if (this.isWhitelistedForNext_(url)) 552 mode = ChromeVoxMode.COMPAT;
540 mode = ChromeVoxMode.NEXT; 553 else if (this.isWhitelistedForNext_(url))
541 else if (mode != ChromeVoxMode.FORCE_NEXT) 554 mode = ChromeVoxMode.NEXT;
542 mode = ChromeVoxMode.CLASSIC; 555 else
556 mode = ChromeVoxMode.CLASSIC;
557 }
543 558
544 this.setChromeVoxMode(mode); 559 this.setChromeVoxMode(mode);
545 }, 560 },
546 561
547 /** 562 /**
548 * Disables classic ChromeVox. 563 * Disables classic ChromeVox.
549 * @param {number} tabId The tab where ChromeVox classic is running in. 564 * @param {number} tabId The tab where ChromeVox classic is running in.
550 */ 565 */
551 disableClassicChromeVox_: function(tabId) { 566 disableClassicChromeVox_: function(tabId) {
552 chrome.tabs.executeScript( 567 chrome.tabs.executeScript(
553 tabId, 568 tabId,
554 {'code': 'try { window.disableChromeVox(); } catch(e) { }\n', 569 {'code': 'try { window.disableChromeVox(); } catch(e) { }\n',
555 'allFrames': true}); 570 'allFrames': true});
556 }, 571 },
557 572
558 /** 573 /**
559 * Sets the current ChromeVox mode. 574 * Sets the current ChromeVox mode.
560 * @param {ChromeVoxMode} mode 575 * @param {ChromeVoxMode} mode
561 */ 576 */
562 setChromeVoxMode: function(mode) { 577 setChromeVoxMode: function(mode) {
563 if (mode === ChromeVoxMode.NEXT ||
564 mode === ChromeVoxMode.COMPAT ||
565 mode === ChromeVoxMode.FORCE_NEXT) {
566 if (!chrome.commands.onCommand.hasListener(this.onGotCommand))
567 chrome.commands.onCommand.addListener(this.onGotCommand);
568 } else {
569 if (chrome.commands.onCommand.hasListener(this.onGotCommand))
570 chrome.commands.onCommand.removeListener(this.onGotCommand);
571 }
572
573 chrome.tabs.query({active: true}, function(tabs) { 578 chrome.tabs.query({active: true}, function(tabs) {
574 if (mode === ChromeVoxMode.CLASSIC) { 579 if (mode === ChromeVoxMode.CLASSIC) {
575 // This case should do nothing because Classic gets injected by the 580 // This case should do nothing because Classic gets injected by the
576 // extension system via our manifest. Once ChromeVox Next is enabled 581 // extension system via our manifest. Once ChromeVox Next is enabled
577 // for tabs, re-enable. 582 // for tabs, re-enable.
578 // cvox.ChromeVox.injectChromeVoxIntoTabs(tabs); 583 // cvox.ChromeVox.injectChromeVoxIntoTabs(tabs);
579 } else { 584 } else {
580 tabs.forEach(function(tab) { 585 tabs.forEach(function(tab) {
581 this.disableClassicChromeVox_(tab.id); 586 this.disableClassicChromeVox_(tab.id);
582 }.bind(this)); 587 }.bind(this));
583 } 588 }
584 }.bind(this)); 589 }.bind(this));
585 590
586 this.compat_.active = mode === ChromeVoxMode.COMPAT;
587 this.mode_ = mode; 591 this.mode_ = mode;
588 } 592 }
589 }; 593 };
590 594
591 /** @type {Background} */ 595 /** @type {Background} */
592 global.backgroundObj = new Background(); 596 global.backgroundObj = new Background();
593 597
594 }); // goog.scope 598 }); // goog.scope
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698