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

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

Issue 2939273002: DO NOT SUBMIT: what chrome/browser/resources/ could eventually look like with clang-format (Closed)
Patch Set: Created 3 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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 /** @type {!cvox.AbstractEarcons} @private */ 86 /** @type {!cvox.AbstractEarcons} @private */
87 this.classicEarcons_ = cvox.ChromeVox.earcons || new cvox.ClassicEarcons(); 87 this.classicEarcons_ = cvox.ChromeVox.earcons || new cvox.ClassicEarcons();
88 88
89 /** @type {!cvox.AbstractEarcons} @private */ 89 /** @type {!cvox.AbstractEarcons} @private */
90 this.nextEarcons_ = new NextEarcons(); 90 this.nextEarcons_ = new NextEarcons();
91 91
92 // Turn cvox.ChromeVox.earcons into a getter that returns either the 92 // Turn cvox.ChromeVox.earcons into a getter that returns either the
93 // Next earcons or the Classic earcons depending on the current mode. 93 // Next earcons or the Classic earcons depending on the current mode.
94 Object.defineProperty(cvox.ChromeVox, 'earcons', { 94 Object.defineProperty(cvox.ChromeVox, 'earcons', {
95 get: (function() { 95 get: (function() {
96 if (this.mode === ChromeVoxMode.FORCE_NEXT || 96 if (this.mode === ChromeVoxMode.FORCE_NEXT ||
97 this.mode === ChromeVoxMode.NEXT) { 97 this.mode === ChromeVoxMode.NEXT) {
98 return this.nextEarcons_; 98 return this.nextEarcons_;
99 } else { 99 } else {
100 return this.classicEarcons_; 100 return this.classicEarcons_;
101 } 101 }
102 }).bind(this) 102 }).bind(this)
103 }); 103 });
104 104
105 if (cvox.ChromeVox.isChromeOS) { 105 if (cvox.ChromeVox.isChromeOS) {
106 Object.defineProperty(cvox.ChromeVox, 'modKeyStr', { 106 Object.defineProperty(cvox.ChromeVox, 'modKeyStr', {
107 get: function() { 107 get: function() {
108 return (this.mode == ChromeVoxMode.CLASSIC || 108 return (this.mode == ChromeVoxMode.CLASSIC ||
109 this.mode == ChromeVoxMode.CLASSIC_COMPAT) ? 109 this.mode == ChromeVoxMode.CLASSIC_COMPAT) ?
110 'Search+Shift' : 'Search'; 110 'Search+Shift' :
111 'Search';
111 }.bind(this) 112 }.bind(this)
112 }); 113 });
113 114
114 Object.defineProperty(cvox.ChromeVox, 'typingEcho', { 115 Object.defineProperty(cvox.ChromeVox, 'typingEcho', {
115 get: function() { 116 get: function() {
116 return parseInt(localStorage['typingEcho'], 10); 117 return parseInt(localStorage['typingEcho'], 10);
117 }.bind(this), 118 }.bind(this),
118 set: function(v) { 119 set: function(v) {
119 localStorage['typingEcho'] = v; 120 localStorage['typingEcho'] = v;
120 }.bind(this) 121 }.bind(this)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 this.focusRecoveryMap_ = new WeakMap(); 168 this.focusRecoveryMap_ = new WeakMap();
168 169
169 chrome.automation.getDesktop(function(desktop) { 170 chrome.automation.getDesktop(function(desktop) {
170 /** @type {string} */ 171 /** @type {string} */
171 this.chromeChannel_ = desktop.chromeChannel; 172 this.chromeChannel_ = desktop.chromeChannel;
172 }.bind(this)); 173 }.bind(this));
173 174
174 // Record a metric with the mode we're in on startup. 175 // Record a metric with the mode we're in on startup.
175 var useNext = localStorage['useClassic'] != 'true'; 176 var useNext = localStorage['useClassic'] != 'true';
176 chrome.metricsPrivate.recordValue( 177 chrome.metricsPrivate.recordValue(
177 { metricName: 'Accessibility.CrosChromeVoxNext', 178 {
179 metricName: 'Accessibility.CrosChromeVoxNext',
178 type: chrome.metricsPrivate.MetricTypeType.HISTOGRAM_LINEAR, 180 type: chrome.metricsPrivate.MetricTypeType.HISTOGRAM_LINEAR,
179 min: 1, // According to histogram.h, this should be 1 for enums. 181 min: 1, // According to histogram.h, this should be 1 for enums.
180 max: 2, // Maximum should be exclusive. 182 max: 2, // Maximum should be exclusive.
181 buckets: 3 }, // Number of buckets: 0, 1 and overflowing 2. 183 buckets: 3
184 }, // Number of buckets: 0, 1 and overflowing 2.
182 useNext ? 1 : 0); 185 useNext ? 1 : 0);
183 }; 186 };
184 187
185 /** 188 /**
186 * Map from gesture names (AXGesture defined in ui/accessibility/ax_enums.idl) 189 * Map from gesture names (AXGesture defined in ui/accessibility/ax_enums.idl)
187 * to commands when in Classic mode. 190 * to commands when in Classic mode.
188 * @type {Object<string, string>} 191 * @type {Object<string, string>}
189 * @const 192 * @const
190 */ 193 */
191 Background.GESTURE_CLASSIC_COMMAND_MAP = { 194 Background.GESTURE_CLASSIC_COMMAND_MAP = {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 }); 241 });
239 } else { 242 } else {
240 target = this.getCurrentRange().start.node; 243 target = this.getCurrentRange().start.node;
241 } 244 }
242 245
243 if (!target) 246 if (!target)
244 return useNext ? ChromeVoxMode.FORCE_NEXT : ChromeVoxMode.CLASSIC; 247 return useNext ? ChromeVoxMode.FORCE_NEXT : ChromeVoxMode.CLASSIC;
245 248
246 // Closure complains, but clearly, |target| is not null. 249 // Closure complains, but clearly, |target| is not null.
247 var topLevelRoot = 250 var topLevelRoot =
248 AutomationUtil.getTopLevelRoot(/** @type {!AutomationNode} */(target)); 251 AutomationUtil.getTopLevelRoot(/** @type {!AutomationNode} */ (target));
249 if (!topLevelRoot) 252 if (!topLevelRoot)
250 return useNext ? ChromeVoxMode.FORCE_NEXT : 253 return useNext ? ChromeVoxMode.FORCE_NEXT : ChromeVoxMode.CLASSIC_COMPAT;
251 ChromeVoxMode.CLASSIC_COMPAT;
252 254
253 var docUrl = topLevelRoot.docUrl || ''; 255 var docUrl = topLevelRoot.docUrl || '';
254 var nextSite = this.isWhitelistedForNext_(docUrl); 256 var nextSite = this.isWhitelistedForNext_(docUrl);
255 var classicCompat = 257 var classicCompat = this.isWhitelistedForClassicCompat_(docUrl);
256 this.isWhitelistedForClassicCompat_(docUrl);
257 if (classicCompat && !useNext) 258 if (classicCompat && !useNext)
258 return ChromeVoxMode.CLASSIC_COMPAT; 259 return ChromeVoxMode.CLASSIC_COMPAT;
259 else if (nextSite) 260 else if (nextSite)
260 return ChromeVoxMode.NEXT; 261 return ChromeVoxMode.NEXT;
261 else if (!useNext) 262 else if (!useNext)
262 return ChromeVoxMode.CLASSIC; 263 return ChromeVoxMode.CLASSIC;
263 else 264 else
264 return ChromeVoxMode.FORCE_NEXT; 265 return ChromeVoxMode.FORCE_NEXT;
265 }, 266 },
266 267
(...skipping 16 matching lines...) Expand all
283 284
284 // Classic modes do not use the new focus highlight. 285 // Classic modes do not use the new focus highlight.
285 if (newMode == ChromeVoxMode.CLASSIC) 286 if (newMode == ChromeVoxMode.CLASSIC)
286 chrome.accessibilityPrivate.setFocusRing([]); 287 chrome.accessibilityPrivate.setFocusRing([]);
287 288
288 // Switch on/off content scripts. 289 // Switch on/off content scripts.
289 // note that |this.currentRange_| can *change* because the request is 290 // note that |this.currentRange_| can *change* because the request is
290 // async. Save it to ensure we're looking at the currentRange at this moment 291 // async. Save it to ensure we're looking at the currentRange at this moment
291 // in time. 292 // in time.
292 var cur = this.currentRange_; 293 var cur = this.currentRange_;
293 chrome.tabs.query({active: true, 294 chrome.tabs.query({active: true, lastFocusedWindow: true}, function(tabs) {
294 lastFocusedWindow: true}, function(tabs) {
295 if (newMode == ChromeVoxMode.CLASSIC) { 295 if (newMode == ChromeVoxMode.CLASSIC) {
296 // Generally, we don't want to inject classic content scripts as it is 296 // Generally, we don't want to inject classic content scripts as it is
297 // done by the extension system at document load. The exception is when 297 // done by the extension system at document load. The exception is when
298 // we toggle classic on manually as part of a user command. 298 // we toggle classic on manually as part of a user command.
299 if (oldMode == ChromeVoxMode.FORCE_NEXT) { 299 if (oldMode == ChromeVoxMode.FORCE_NEXT) {
300 cvox.ChromeVox.injectChromeVoxIntoTabs(tabs); 300 cvox.ChromeVox.injectChromeVoxIntoTabs(tabs);
301 } 301 }
302 } else if (newMode === ChromeVoxMode.FORCE_NEXT) { 302 } else if (newMode === ChromeVoxMode.FORCE_NEXT) {
303 this.disableClassicChromeVox_(); 303 this.disableClassicChromeVox_();
304 } else { 304 } else {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 chrome.metricsPrivate.recordUserAction( 355 chrome.metricsPrivate.recordUserAction(
356 'Accessibility.ChromeVox.ToggleNextOff'); 356 'Accessibility.ChromeVox.ToggleNextOff');
357 } 357 }
358 358
359 localStorage['useClassic'] = !useNext; 359 localStorage['useClassic'] = !useNext;
360 if (useNext) 360 if (useNext)
361 this.setCurrentRangeToFocus_(); 361 this.setCurrentRangeToFocus_();
362 else 362 else
363 this.setCurrentRange(null); 363 this.setCurrentRange(null);
364 364
365 var announce = Msgs.getMsg(useNext ? 365 var announce =
366 'switch_to_next' : 'switch_to_classic'); 366 Msgs.getMsg(useNext ? 'switch_to_next' : 'switch_to_classic');
367 cvox.ChromeVox.tts.speak( 367 cvox.ChromeVox.tts.speak(
368 announce, cvox.QueueMode.FLUSH, {doNotInterrupt: true}); 368 announce, cvox.QueueMode.FLUSH, {doNotInterrupt: true});
369 369
370 // If the new mode is Classic, return false now so we don't announce 370 // If the new mode is Classic, return false now so we don't announce
371 // anything more. 371 // anything more.
372 return useNext; 372 return useNext;
373 }, 373 },
374 374
375 /** 375 /**
376 * @override 376 * @override
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 opt_focus = opt_focus === undefined ? true : opt_focus; 432 opt_focus = opt_focus === undefined ? true : opt_focus;
433 opt_speechProps = opt_speechProps || {}; 433 opt_speechProps = opt_speechProps || {};
434 var prevRange = this.currentRange_; 434 var prevRange = this.currentRange_;
435 if (opt_focus) 435 if (opt_focus)
436 this.setFocusToRange_(range, prevRange); 436 this.setFocusToRange_(range, prevRange);
437 437
438 this.setCurrentRange(range); 438 this.setCurrentRange(range);
439 439
440 var o = new Output(); 440 var o = new Output();
441 var selectedRange; 441 var selectedRange;
442 if (this.pageSel_ && 442 if (this.pageSel_ && this.pageSel_.isValid() && range.isValid()) {
443 this.pageSel_.isValid() &&
444 range.isValid()) {
445 // Compute the direction of the endpoints of each range. 443 // Compute the direction of the endpoints of each range.
446 444
447 // Casts are ok because isValid checks node start and end nodes are 445 // Casts are ok because isValid checks node start and end nodes are
448 // non-null; Closure just doesn't eval enough to see it. 446 // non-null; Closure just doesn't eval enough to see it.
449 var startDir = 447 var startDir = AutomationUtil.getDirection(
450 AutomationUtil.getDirection(this.pageSel_.start.node, 448 this.pageSel_.start.node,
451 /** @type {!AutomationNode} */ (range.start.node)); 449 /** @type {!AutomationNode} */ (range.start.node));
452 var endDir = 450 var endDir = AutomationUtil.getDirection(
453 AutomationUtil.getDirection(this.pageSel_.end.node, 451 this.pageSel_.end.node,
454 /** @type {!AutomationNode} */ (range.end.node)); 452 /** @type {!AutomationNode} */ (range.end.node));
455 453
456 // Selection across roots isn't supported. 454 // Selection across roots isn't supported.
457 var pageRootStart = this.pageSel_.start.node.root; 455 var pageRootStart = this.pageSel_.start.node.root;
458 var pageRootEnd = this.pageSel_.end.node.root; 456 var pageRootEnd = this.pageSel_.end.node.root;
459 var curRootStart = range.start.node.root; 457 var curRootStart = range.start.node.root;
460 var curRootEnd = range.end.node.root; 458 var curRootEnd = range.end.node.root;
461 459
462 // Disallow crossing over the start of the page selection and roots. 460 // Disallow crossing over the start of the page selection and roots.
463 if (startDir == Dir.BACKWARD || 461 if (startDir == Dir.BACKWARD || pageRootStart != pageRootEnd ||
464 pageRootStart != pageRootEnd || 462 pageRootStart != curRootStart || pageRootEnd != curRootEnd) {
465 pageRootStart != curRootStart ||
466 pageRootEnd != curRootEnd) {
467 o.format('@end_selection'); 463 o.format('@end_selection');
468 this.pageSel_ = null; 464 this.pageSel_ = null;
469 } else { 465 } else {
470 // Expand or shrink requires different feedback. 466 // Expand or shrink requires different feedback.
471 var msg; 467 var msg;
472 if (endDir == Dir.FORWARD && 468 if (endDir == Dir.FORWARD &&
473 (this.pageSel_.end.node != range.end.node || 469 (this.pageSel_.end.node != range.end.node ||
474 this.pageSel_.end.index <= range.end.index)) { 470 this.pageSel_.end.index <= range.end.index)) {
475 msg = '@selected'; 471 msg = '@selected';
476 } else { 472 } else {
477 msg = '@unselected'; 473 msg = '@unselected';
478 selectedRange = prevRange; 474 selectedRange = prevRange;
479 } 475 }
480 this.pageSel_ = new cursors.Range( 476 this.pageSel_ = new cursors.Range(this.pageSel_.start, range.end);
481 this.pageSel_.start,
482 range.end
483 );
484 if (this.pageSel_) 477 if (this.pageSel_)
485 this.pageSel_.select(); 478 this.pageSel_.select();
486 } 479 }
487 } else { 480 } else {
488 // Ensure we don't select the editable when we first encounter it. 481 // Ensure we don't select the editable when we first encounter it.
489 var lca = null; 482 var lca = null;
490 if (range.start.node && prevRange.start.node) { 483 if (range.start.node && prevRange.start.node) {
491 lca = AutomationUtil.getLeastCommonAncestor(prevRange.start.node, 484 lca = AutomationUtil.getLeastCommonAncestor(
492 range.start.node); 485 prevRange.start.node, range.start.node);
493 } 486 }
494 if (!lca || lca.state[StateType.EDITABLE] || 487 if (!lca || lca.state[StateType.EDITABLE] ||
495 !range.start.node.state[StateType.EDITABLE]) 488 !range.start.node.state[StateType.EDITABLE])
496 range.select(); 489 range.select();
497 } 490 }
498 491
499 o.withRichSpeechAndBraille( 492 o.withRichSpeechAndBraille(
500 selectedRange || range, prevRange, Output.EventType.NAVIGATE) 493 selectedRange || range, prevRange, Output.EventType.NAVIGATE)
501 .withQueueMode(cvox.QueueMode.FLUSH); 494 .withQueueMode(cvox.QueueMode.FLUSH);
502 495
503 if (msg) 496 if (msg)
504 o.format(msg); 497 o.format(msg);
505 498
506 for (var prop in opt_speechProps) 499 for (var prop in opt_speechProps)
507 o.format('!' + prop); 500 o.format('!' + prop);
508 501
509 o.go(); 502 o.go();
510 }, 503 },
511 504
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 return true; 559 return true;
567 }, 560 },
568 561
569 /** 562 /**
570 * Returns true if the url should have Classic running. 563 * Returns true if the url should have Classic running.
571 * @return {boolean} 564 * @return {boolean}
572 * @private 565 * @private
573 */ 566 */
574 shouldEnableClassicForUrl_: function(url) { 567 shouldEnableClassicForUrl_: function(url) {
575 return this.mode != ChromeVoxMode.FORCE_NEXT && 568 return this.mode != ChromeVoxMode.FORCE_NEXT &&
576 !this.isBlacklistedForClassic_(url) && 569 !this.isBlacklistedForClassic_(url) && !this.isWhitelistedForNext_(url);
577 !this.isWhitelistedForNext_(url);
578 }, 570 },
579 571
580 /** 572 /**
581 * Compat mode is on if any of the following are true: 573 * Compat mode is on if any of the following are true:
582 * 1. a url is blacklisted for Classic. 574 * 1. a url is blacklisted for Classic.
583 * 2. the current range is not within web content. 575 * 2. the current range is not within web content.
584 * @param {string} url 576 * @param {string} url
585 * @return {boolean} 577 * @return {boolean}
586 */ 578 */
587 isWhitelistedForClassicCompat_: function(url) { 579 isWhitelistedForClassicCompat_: function(url) {
588 return (this.isBlacklistedForClassic_(url) || (this.getCurrentRange() && 580 return (this.isBlacklistedForClassic_(url) ||
589 !this.getCurrentRange().isWebRange() && 581 (this.getCurrentRange() && !this.getCurrentRange().isWebRange() &&
590 this.getCurrentRange().start.node.state[StateType.FOCUSED])) || false; 582 this.getCurrentRange().start.node.state[StateType.FOCUSED])) ||
583 false;
591 }, 584 },
592 585
593 /** 586 /**
594 * @param {string} url 587 * @param {string} url
595 * @return {boolean} 588 * @return {boolean}
596 * @private 589 * @private
597 */ 590 */
598 isBlacklistedForClassic_: function(url) { 591 isBlacklistedForClassic_: function(url) {
599 if (this.classicBlacklistRegExp_.test(url)) 592 if (this.classicBlacklistRegExp_.test(url))
600 return true; 593 return true;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
671 */ 664 */
672 onMessage_: function(msg, port) { 665 onMessage_: function(msg, port) {
673 var target = msg['target']; 666 var target = msg['target'];
674 var action = msg['action']; 667 var action = msg['action'];
675 668
676 switch (target) { 669 switch (target) {
677 case 'next': 670 case 'next':
678 if (action == 'getIsClassicEnabled') { 671 if (action == 'getIsClassicEnabled') {
679 var url = msg['url']; 672 var url = msg['url'];
680 var isClassicEnabled = this.shouldEnableClassicForUrl_(url); 673 var isClassicEnabled = this.shouldEnableClassicForUrl_(url);
681 port.postMessage({ 674 port.postMessage(
682 target: 'next', 675 {target: 'next', isClassicEnabled: isClassicEnabled});
683 isClassicEnabled: isClassicEnabled
684 });
685 } else if (action == 'enableClassicCompatForUrl') { 676 } else if (action == 'enableClassicCompatForUrl') {
686 var url = msg['url']; 677 var url = msg['url'];
687 this.classicBlacklist_.add(url); 678 this.classicBlacklist_.add(url);
688 if (this.currentRange_ && this.currentRange_.start.node) 679 if (this.currentRange_ && this.currentRange_.start.node)
689 this.setCurrentRange(this.currentRange_); 680 this.setCurrentRange(this.currentRange_);
690 } else if (action == 'onCommand') { 681 } else if (action == 'onCommand') {
691 CommandHandler.onCommand(msg['command']); 682 CommandHandler.onCommand(msg['command']);
692 } else if (action == 'flushNextUtterance') { 683 } else if (action == 'flushNextUtterance') {
693 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); 684 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH);
694 } 685 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 * @param {string} gesture The gesture to handle, based on the AXGesture enum 725 * @param {string} gesture The gesture to handle, based on the AXGesture enum
735 * defined in ui/accessibility/ax_enums.idl 726 * defined in ui/accessibility/ax_enums.idl
736 * @return {boolean} True if this gesture was handled. 727 * @return {boolean} True if this gesture was handled.
737 * @private 728 * @private
738 */ 729 */
739 handleClassicGesture_: function(gesture) { 730 handleClassicGesture_: function(gesture) {
740 var command = Background.GESTURE_CLASSIC_COMMAND_MAP[gesture]; 731 var command = Background.GESTURE_CLASSIC_COMMAND_MAP[gesture];
741 if (!command) 732 if (!command)
742 return false; 733 return false;
743 734
744 var msg = { 735 var msg = {'message': 'USER_COMMAND', 'command': command};
745 'message': 'USER_COMMAND',
746 'command': command
747 };
748 cvox.ExtensionBridge.send(msg); 736 cvox.ExtensionBridge.send(msg);
749 return true; 737 return true;
750 }, 738 },
751 739
752 /** @private */ 740 /** @private */
753 setCurrentRangeToFocus_: function() { 741 setCurrentRangeToFocus_: function() {
754 chrome.automation.getFocus(function(focus) { 742 chrome.automation.getFocus(function(focus) {
755 if (focus) 743 if (focus)
756 this.setCurrentRange(cursors.Range.fromNode(focus)); 744 this.setCurrentRange(cursors.Range.fromNode(focus));
757 else 745 else
758 this.setCurrentRange(null); 746 this.setCurrentRange(null);
759 }.bind(this)); 747 }.bind(this));
760 }, 748 },
761 749
762 /** 750 /**
763 * @param {!cursors.Range} range 751 * @param {!cursors.Range} range
764 * @param {cursors.Range} prevRange 752 * @param {cursors.Range} prevRange
765 * @private 753 * @private
766 */ 754 */
767 setFocusToRange_: function(range, prevRange) { 755 setFocusToRange_: function(range, prevRange) {
768 var start = range.start.node; 756 var start = range.start.node;
769 var end = range.end.node; 757 var end = range.end.node;
770 758
771 // First, see if we've crossed a root. Remove once webview handles focus 759 // First, see if we've crossed a root. Remove once webview handles focus
772 // correctly. 760 // correctly.
773 if (prevRange && prevRange.start.node && start) { 761 if (prevRange && prevRange.start.node && start) {
774 var entered = AutomationUtil.getUniqueAncestors( 762 var entered =
775 prevRange.start.node, start); 763 AutomationUtil.getUniqueAncestors(prevRange.start.node, start);
776 var embeddedObject = entered.find(function(f) { 764 var embeddedObject = entered.find(function(f) {
777 return f.role == RoleType.EMBEDDED_OBJECT; }); 765 return f.role == RoleType.EMBEDDED_OBJECT;
766 });
778 if (embeddedObject && !embeddedObject.state[StateType.FOCUSED]) 767 if (embeddedObject && !embeddedObject.state[StateType.FOCUSED])
779 embeddedObject.focus(); 768 embeddedObject.focus();
780 } 769 }
781 770
782 if (start.state[StateType.FOCUSED] || end.state[StateType.FOCUSED]) 771 if (start.state[StateType.FOCUSED] || end.state[StateType.FOCUSED])
783 return; 772 return;
784 773
785 var isFocusableLinkOrControl = function(node) { 774 var isFocusableLinkOrControl = function(node) {
786 return node.state[StateType.FOCUSABLE] && 775 return node.state[StateType.FOCUSABLE] &&
787 AutomationPredicate.linkOrControl(node); 776 AutomationPredicate.linkOrControl(node);
788 }; 777 };
789 778
790 // Next, try to focus the start or end node. 779 // Next, try to focus the start or end node.
791 if (!AutomationPredicate.structuralContainer(start) && 780 if (!AutomationPredicate.structuralContainer(start) &&
792 start.state[StateType.FOCUSABLE]) { 781 start.state[StateType.FOCUSABLE]) {
793 if (!start.state[StateType.FOCUSED]) 782 if (!start.state[StateType.FOCUSED])
794 start.focus(); 783 start.focus();
795 return; 784 return;
796 } else if (!AutomationPredicate.structuralContainer(end) && 785 } else if (
786 !AutomationPredicate.structuralContainer(end) &&
797 end.state[StateType.FOCUSABLE]) { 787 end.state[StateType.FOCUSABLE]) {
798 if (!end.state[StateType.FOCUSED]) 788 if (!end.state[StateType.FOCUSED])
799 end.focus(); 789 end.focus();
800 return; 790 return;
801 } 791 }
802 792
803 // If a common ancestor of |start| and |end| is a link, focus that. 793 // If a common ancestor of |start| and |end| is a link, focus that.
804 var ancestor = AutomationUtil.getLeastCommonAncestor(start, end); 794 var ancestor = AutomationUtil.getLeastCommonAncestor(start, end);
805 while (ancestor && ancestor.root == start.root) { 795 while (ancestor && ancestor.root == start.root) {
806 if (isFocusableLinkOrControl(ancestor)) { 796 if (isFocusableLinkOrControl(ancestor)) {
(...skipping 13 matching lines...) Expand all
820 }; 810 };
821 811
822 /** 812 /**
823 * Converts a list of globs, as used in the extension manifest, to a regular 813 * Converts a list of globs, as used in the extension manifest, to a regular
824 * expression that matches if and only if any of the globs in the list matches. 814 * expression that matches if and only if any of the globs in the list matches.
825 * @param {!Array<string>} globs 815 * @param {!Array<string>} globs
826 * @return {!RegExp} 816 * @return {!RegExp}
827 * @private 817 * @private
828 */ 818 */
829 Background.globsToRegExp_ = function(globs) { 819 Background.globsToRegExp_ = function(globs) {
830 return new RegExp('^(' + globs.map(function(glob) { 820 return new RegExp(
831 return glob.replace(/[.+^$(){}|[\]\\]/g, '\\$&') 821 '^(' +
832 .replace(/\*/g, '.*') 822 globs
833 .replace(/\?/g, '.'); 823 .map(function(glob) {
834 }).join('|') + ')$'); 824 return glob.replace(/[.+^$(){}|[\]\\]/g, '\\$&')
825 .replace(/\*/g, '.*')
826 .replace(/\?/g, '.');
827 })
828 .join('|') +
829 ')$');
835 }; 830 };
836 831
837 new Background(); 832 new Background();
838 833
839 }); // goog.scope 834 }); // goog.scope
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698