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

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: Rebase. 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 ...
90 // Desktop.
91 chrome.automation.getDesktop(this.onGotDesktop); 89 chrome.automation.getDesktop(this.onGotDesktop);
92 }; 90 };
93 91
94 Background.prototype = { 92 Background.prototype = {
95 /** Forces ChromeVox Next to be active for all tabs. */ 93 /** Forces ChromeVox Next to be active for all tabs. */
96 forceChromeVoxNextActive: function() { 94 forceChromeVoxNextActive: function() {
97 this.setChromeVoxMode(ChromeVoxMode.FORCE_NEXT); 95 this.setChromeVoxMode(ChromeVoxMode.FORCE_NEXT);
98 }, 96 },
99 97
100 /** 98 /**
(...skipping 19 matching lines...) Expand all
120 type: chrome.automation.EventType.loadComplete}); 118 type: chrome.automation.EventType.loadComplete});
121 } 119 }
122 } 120 }
123 }, 121 },
124 122
125 /** 123 /**
126 * Handles chrome.commands.onCommand. 124 * Handles chrome.commands.onCommand.
127 * @param {string} command 125 * @param {string} command
128 * @param {boolean=} opt_skipCompat Whether to skip compatibility checks. 126 * @param {boolean=} opt_skipCompat Whether to skip compatibility checks.
129 */ 127 */
130 onGotCommand: function(command, opt_skipCompat) { 128 onGotCommand: function(command, opt_skipCompat) {
131 if (!this.currentRange_) 129 if (!this.currentRange_)
132 return; 130 return;
133 131
134 if (!opt_skipCompat) { 132 if (!opt_skipCompat && this.mode_ === ChromeVoxMode.COMPAT) {
135 if (this.compat_.onGotCommand(command)) 133 if (this.compat_.onGotCommand(command))
136 return; 134 return;
137 } 135 }
138 136
139 if (this.mode_ === ChromeVoxMode.CLASSIC)
140 return;
141
142 var current = this.currentRange_; 137 var current = this.currentRange_;
143 var dir = Dir.FORWARD; 138 var dir = Dir.FORWARD;
144 var pred = null; 139 var pred = null;
145 var predErrorMsg = undefined; 140 var predErrorMsg = undefined;
146 switch (command) { 141 switch (command) {
147 case 'nextCharacter': 142 case 'nextCharacter':
148 current = current.move(cursors.Unit.CHARACTER, Dir.FORWARD); 143 current = current.move(cursors.Unit.CHARACTER, Dir.FORWARD);
149 break; 144 break;
150 case 'previousCharacter': 145 case 'previousCharacter':
151 current = current.move(cursors.Unit.CHARACTER, Dir.BACKWARD); 146 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); 316 current = cursors.Range.fromNode(node);
322 } else { 317 } else {
323 cvox.ChromeVox.tts.speak(cvox.ChromeVox.msgs.getMsg(predErrorMsg), 318 cvox.ChromeVox.tts.speak(cvox.ChromeVox.msgs.getMsg(predErrorMsg),
324 cvox.QueueMode.FLUSH); 319 cvox.QueueMode.FLUSH);
325 return; 320 return;
326 } 321 }
327 } 322 }
328 323
329 if (current) { 324 if (current) {
330 // TODO(dtseng): Figure out what it means to focus a range. 325 // TODO(dtseng): Figure out what it means to focus a range.
331 current.getStart().getNode().focus(); 326 var actionNode = current.getStart().getNode();
327 if (actionNode.role == chrome.automation.RoleType.inlineTextBox)
328 actionNode = actionNode.parent;
329 actionNode.focus();
332 330
333 var prevRange = this.currentRange_; 331 var prevRange = this.currentRange_;
334 this.currentRange_ = current; 332 this.currentRange_ = current;
333
335 new Output().withSpeechAndBraille( 334 new Output().withSpeechAndBraille(
336 this.currentRange_, prevRange, Output.EventType.NAVIGATE) 335 this.currentRange_, prevRange, Output.EventType.NAVIGATE)
337 .go(); 336 .go();
338 } 337 }
339 }, 338 },
340 339
341 /** 340 /**
342 * Provides all feedback once ChromeVox's focus changes. 341 * Provides all feedback once ChromeVox's focus changes.
343 * @param {Object} evt 342 * @param {Object} evt
344 */ 343 */
345 onEventDefault: function(evt) { 344 onEventDefault: function(evt) {
346 var node = evt.target; 345 var node = evt.target;
347 346
348 if (!node) 347 if (!node)
349 return; 348 return;
350 349
351 var prevRange = this.currentRange_; 350 var prevRange = this.currentRange_;
352 351
353 this.currentRange_ = cursors.Range.fromNode(node); 352 this.currentRange_ = cursors.Range.fromNode(node);
354 353
355 // Check to see if we've crossed roots. Only care about focused roots. 354 // Check to see if we've crossed roots. Continue if we've crossed roots or
356 if (!prevRange || 355 // are not within web content.
356 if (node.root.role == 'desktop' ||
357 !prevRange ||
357 (prevRange.getStart().getNode().root != node.root && 358 (prevRange.getStart().getNode().root != node.root &&
358 node.root.focused)) 359 node.state.focused))
359 this.setupChromeVoxVariants_(node.root.docUrl || ''); 360 this.setupChromeVoxVariants_(node.root.docUrl || '');
360 361
361 // Don't process nodes inside of web content if ChromeVox Next is inactive. 362 // Don't process nodes inside of web content if ChromeVox Next is inactive.
362 if (node.root.role != chrome.automation.RoleType.desktop && 363 if (node.root.role != chrome.automation.RoleType.desktop &&
363 this.mode_ === ChromeVoxMode.CLASSIC) { 364 this.mode_ === ChromeVoxMode.CLASSIC) {
364 chrome.accessibilityPrivate.setFocusRing([]); 365 chrome.accessibilityPrivate.setFocusRing([]);
365 return; 366 return;
366 } 367 }
367 368
369 // Don't output if focused node hasn't changed.
370 if (prevRange &&
371 evt.type == 'focus' &&
372 this.currentRange_.equals(prevRange))
373 return;
374
368 new Output().withSpeechAndBraille( 375 new Output().withSpeechAndBraille(
369 this.currentRange_, prevRange, evt.type) 376 this.currentRange_, prevRange, evt.type)
370 .go(); 377 .go();
371 }, 378 },
372 379
373 /** 380 /**
374 * Provides all feedback once a load complete event fires. 381 * Provides all feedback once a load complete event fires.
375 * @param {Object} evt 382 * @param {Object} evt
376 */ 383 */
377 onLoadComplete: function(evt) { 384 onLoadComplete: function(evt) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 } 512 }
506 output.withSpeech(range, null, Output.EventType.NAVIGATE); 513 output.withSpeech(range, null, Output.EventType.NAVIGATE);
507 output.go(); 514 output.go();
508 }, 515 },
509 516
510 /** 517 /**
511 * @return {boolean} 518 * @return {boolean}
512 * @private 519 * @private
513 */ 520 */
514 isWhitelistedForCompat_: function(url) { 521 isWhitelistedForCompat_: function(url) {
515 return url.indexOf('chrome://md-settings') != -1; 522 return url.indexOf('chrome://md-settings') != -1 || url === '';
516 }, 523 },
517 524
518 /** 525 /**
519 * @private 526 * @private
520 * @param {string} url 527 * @param {string} url
521 * @return {boolean} Whether the given |url| is whitelisted. 528 * @return {boolean} Whether the given |url| is whitelisted.
522 */ 529 */
523 isWhitelistedForNext_: function(url) { 530 isWhitelistedForNext_: function(url) {
524 return this.whitelist_.some(function(item) { 531 return this.whitelist_.some(function(item) {
525 return url.indexOf(item) != -1; 532 return url.indexOf(item) != -1;
526 }.bind(this)); 533 }.bind(this));
527 }, 534 },
528 535
529 /** 536 /**
530 * Setup ChromeVox variants. 537 * Setup ChromeVox variants.
531 * @param {string} url 538 * @param {string} url
532 * @private 539 * @private
533 */ 540 */
534 setupChromeVoxVariants_: function(url) { 541 setupChromeVoxVariants_: function(url) {
535 this.compat_.active = this.isWhitelistedForCompat_(url);
536 var mode = this.mode_; 542 var mode = this.mode_;
537 if (this.compat_.active) 543 if (mode != ChromeVoxMode.FORCE_NEXT) {
538 mode = ChromeVoxMode.COMPAT; 544 if (this.isWhitelistedForCompat_(url))
539 else if (this.isWhitelistedForNext_(url)) 545 mode = ChromeVoxMode.COMPAT;
540 mode = ChromeVoxMode.NEXT; 546 else if (this.isWhitelistedForNext_(url))
541 else if (mode != ChromeVoxMode.FORCE_NEXT) 547 mode = ChromeVoxMode.NEXT;
542 mode = ChromeVoxMode.CLASSIC; 548 else
549 mode = ChromeVoxMode.CLASSIC;
550 }
543 551
544 this.setChromeVoxMode(mode); 552 this.setChromeVoxMode(mode);
545 }, 553 },
546 554
547 /** 555 /**
548 * Disables classic ChromeVox. 556 * Disables classic ChromeVox.
549 * @param {number} tabId The tab where ChromeVox classic is running in. 557 * @param {number} tabId The tab where ChromeVox classic is running in.
550 */ 558 */
551 disableClassicChromeVox_: function(tabId) { 559 disableClassicChromeVox_: function(tabId) {
552 chrome.tabs.executeScript( 560 chrome.tabs.executeScript(
(...skipping 17 matching lines...) Expand all
570 chrome.commands.onCommand.removeListener(this.onGotCommand); 578 chrome.commands.onCommand.removeListener(this.onGotCommand);
571 } 579 }
572 580
573 chrome.tabs.query({active: true}, function(tabs) { 581 chrome.tabs.query({active: true}, function(tabs) {
574 if (mode === ChromeVoxMode.CLASSIC) { 582 if (mode === ChromeVoxMode.CLASSIC) {
575 // This case should do nothing because Classic gets injected by the 583 // This case should do nothing because Classic gets injected by the
576 // extension system via our manifest. Once ChromeVox Next is enabled 584 // extension system via our manifest. Once ChromeVox Next is enabled
577 // for tabs, re-enable. 585 // for tabs, re-enable.
578 // cvox.ChromeVox.injectChromeVoxIntoTabs(tabs); 586 // cvox.ChromeVox.injectChromeVoxIntoTabs(tabs);
579 } else { 587 } else {
588 // When in compat mode, if the focus is within the desktop tree proper,
589 // then do not disable content scripts.
590 if (this.currentRange_.getStart().getNode().root.role == 'desktop')
591 return;
592
580 tabs.forEach(function(tab) { 593 tabs.forEach(function(tab) {
581 this.disableClassicChromeVox_(tab.id); 594 this.disableClassicChromeVox_(tab.id);
582 }.bind(this)); 595 }.bind(this));
583 } 596 }
584 }.bind(this)); 597 }.bind(this));
585 598
586 this.compat_.active = mode === ChromeVoxMode.COMPAT;
587 this.mode_ = mode; 599 this.mode_ = mode;
588 } 600 }
589 }; 601 };
590 602
591 /** @type {Background} */ 603 /** @type {Background} */
592 global.backgroundObj = new Background(); 604 global.backgroundObj = new Background();
593 605
594 }); // goog.scope 606 }); // goog.scope
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698