Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / chrome / browser / resources / chromeos / chromevox / extensions / searchvox / util.js
blob1cccde971b4b1c225db6b20db8a98ea9f725c2ed
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
3 // found in the LICENSE file.
6 /**
7 * @fileoverview Helper functions.
8 */
10 goog.provide('cvox.SearchUtil');
12 /** Utility functions. */
13 cvox.SearchUtil = function() {
16 /**
17 * Extracts the first URL from an element.
18 * @param {Node} node DOM element to extract from.
19 * @return {?string} URL.
21 cvox.SearchUtil.extractURL = function(node) {
22 if (node) {
23 if (node.tagName === 'A') {
24 return node.href;
26 var anchor = node.querySelector('a');
27 if (anchor) {
28 return anchor.href;
31 return null;
34 /**
35 * Indicates whether or not the search widget has been activated.
36 * @return {boolean} Whether or not the search widget is active.
38 cvox.SearchUtil.isSearchWidgetActive = function() {
39 var SEARCH_WIDGET_SELECT = '#cvox-search';
40 return document.querySelector(SEARCH_WIDGET_SELECT) !== null;
43 /**
44 * Adds one to and index with wrapping.
45 * @param {number} index Index to add to.
46 * @param {number} length Length to wrap at.
47 * @return {number} The new index++, wrapped if exceeding length.
49 cvox.SearchUtil.addOneWrap = function(index, length) {
50 return (index + 1) % length;
53 /**
54 * Subtracts one to and index with wrapping.
55 * @param {number} index Index to subtract from.
56 * @param {number} length Length to wrap at.
57 * @return {number} The new index--, wrapped if below 0.
59 cvox.SearchUtil.subOneWrap = function(index, length) {
60 return (index - 1 + length) % length;
63 /**
64 * Returns the id of a node's active descendant
65 * @param {Node} targetNode The node.
66 * @return {?string} The id of the active descendant.
67 * @private
69 var getActiveDescendantId_ = function(targetNode) {
70 if (!targetNode.getAttribute) {
71 return null;
74 var activeId = targetNode.getAttribute('aria-activedescendant');
75 if (!activeId) {
76 return null;
78 return activeId;
81 /**
82 * If the node is an object with an active descendant, returns the
83 * descendant node.
85 * This function will fully resolve an active descendant chain. If a circular
86 * chain is detected, it will return null.
88 * @param {Node} targetNode The node to get descendant information for.
89 * @return {Node} The descendant node or null if no node exists.
91 var getActiveDescendant = function(targetNode) {
92 var seenIds = {};
93 var node = targetNode;
95 while (node) {
96 var activeId = getActiveDescendantId_(node);
97 if (!activeId) {
98 break;
100 if (activeId in seenIds) {
101 // A circlar activeDescendant is an error, so return null.
102 return null;
104 seenIds[activeId] = true;
105 node = document.getElementById(activeId);
108 if (node == targetNode) {
109 return null;
111 return node;
115 * Dispatches a left click event on the element that is the targetNode.
116 * Clicks go in the sequence of mousedown, mouseup, and click.
117 * @param {Node} targetNode The target node of this operation.
118 * @param {boolean=} shiftKey Specifies if shift is held down.
119 * @param {boolean=} callOnClickDirectly Specifies whether or not to directly
120 * invoke the onclick method if there is one.
121 * @param {boolean=} opt_double True to issue a double click.
123 cvox.SearchUtil.clickElem = function(
124 targetNode, shiftKey, callOnClickDirectly, opt_double) {
125 // If there is an activeDescendant of the targetNode, then that is where the
126 // click should actually be targeted.
127 var activeDescendant = getActiveDescendant(targetNode);
128 if (activeDescendant) {
129 targetNode = activeDescendant;
131 if (callOnClickDirectly) {
132 var onClickFunction = null;
133 if (targetNode.onclick) {
134 onClickFunction = targetNode.onclick;
136 if (!onClickFunction && (targetNode.nodeType != 1) &&
137 targetNode.parentNode && targetNode.parentNode.onclick) {
138 onClickFunction = targetNode.parentNode.onclick;
140 var keepGoing = true;
141 if (onClickFunction) {
142 try {
143 keepGoing = onClickFunction();
144 } catch (exception) {
145 // Something went very wrong with the onclick method; we'll ignore it
146 // and just dispatch a click event normally.
149 if (!keepGoing) {
150 // The onclick method ran successfully and returned false, meaning the
151 // event should not bubble up, so we will return here.
152 return;
156 // Send a mousedown (or simply a double click if requested).
157 var evt = document.createEvent('MouseEvents');
158 var evtType = opt_double ? 'dblclick' : 'mousedown';
159 evt.initMouseEvent(evtType, true, true, document.defaultView,
160 1, 0, 0, 0, 0, false, false, shiftKey, false, 0, null);
161 // Mark any events we generate so we don't try to process our own events.
162 evt.fromCvox = true;
163 try {
164 targetNode.dispatchEvent(evt);
165 } catch (e) {}
166 //Send a mouse up
167 evt = document.createEvent('MouseEvents');
168 evt.initMouseEvent('mouseup', true, true, document.defaultView,
169 1, 0, 0, 0, 0, false, false, shiftKey, false, 0, null);
170 // Mark any events we generate so we don't try to process our own events.
171 evt.fromCvox = true;
172 try {
173 targetNode.dispatchEvent(evt);
174 } catch (e) {}
175 //Send a click
176 evt = document.createEvent('MouseEvents');
177 evt.initMouseEvent('click', true, true, document.defaultView,
178 1, 0, 0, 0, 0, false, false, shiftKey, false, 0, null);
179 // Mark any events we generate so we don't try to process our own events.
180 evt.fromCvox = true;
181 try {
182 targetNode.dispatchEvent(evt);
183 } catch (e) {}