1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/tests/mochitest/common.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,820 @@ 1.4 +//////////////////////////////////////////////////////////////////////////////// 1.5 +// Interfaces 1.6 + 1.7 +const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval; 1.8 + 1.9 +const nsIAccessibleEvent = Components.interfaces.nsIAccessibleEvent; 1.10 +const nsIAccessibleStateChangeEvent = 1.11 + Components.interfaces.nsIAccessibleStateChangeEvent; 1.12 +const nsIAccessibleCaretMoveEvent = 1.13 + Components.interfaces.nsIAccessibleCaretMoveEvent; 1.14 +const nsIAccessibleTextChangeEvent = 1.15 + Components.interfaces.nsIAccessibleTextChangeEvent; 1.16 +const nsIAccessibleVirtualCursorChangeEvent = 1.17 + Components.interfaces.nsIAccessibleVirtualCursorChangeEvent; 1.18 + 1.19 +const nsIAccessibleStates = Components.interfaces.nsIAccessibleStates; 1.20 +const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole; 1.21 +const nsIAccessibleScrollType = Components.interfaces.nsIAccessibleScrollType; 1.22 +const nsIAccessibleCoordinateType = Components.interfaces.nsIAccessibleCoordinateType; 1.23 + 1.24 +const nsIAccessibleRelation = Components.interfaces.nsIAccessibleRelation; 1.25 + 1.26 +const nsIAccessible = Components.interfaces.nsIAccessible; 1.27 + 1.28 +const nsIAccessibleDocument = Components.interfaces.nsIAccessibleDocument; 1.29 +const nsIAccessibleApplication = Components.interfaces.nsIAccessibleApplication; 1.30 + 1.31 +const nsIAccessibleText = Components.interfaces.nsIAccessibleText; 1.32 +const nsIAccessibleEditableText = Components.interfaces.nsIAccessibleEditableText; 1.33 + 1.34 +const nsIAccessibleHyperLink = Components.interfaces.nsIAccessibleHyperLink; 1.35 +const nsIAccessibleHyperText = Components.interfaces.nsIAccessibleHyperText; 1.36 + 1.37 +const nsIAccessibleCursorable = Components.interfaces.nsIAccessibleCursorable; 1.38 +const nsIAccessibleImage = Components.interfaces.nsIAccessibleImage; 1.39 +const nsIAccessiblePivot = Components.interfaces.nsIAccessiblePivot; 1.40 +const nsIAccessibleSelectable = Components.interfaces.nsIAccessibleSelectable; 1.41 +const nsIAccessibleTable = Components.interfaces.nsIAccessibleTable; 1.42 +const nsIAccessibleTableCell = Components.interfaces.nsIAccessibleTableCell; 1.43 +const nsIAccessibleTraversalRule = Components.interfaces.nsIAccessibleTraversalRule; 1.44 +const nsIAccessibleValue = Components.interfaces.nsIAccessibleValue; 1.45 + 1.46 +const nsIObserverService = Components.interfaces.nsIObserverService; 1.47 + 1.48 +const nsIDOMDocument = Components.interfaces.nsIDOMDocument; 1.49 +const nsIDOMEvent = Components.interfaces.nsIDOMEvent; 1.50 +const nsIDOMHTMLDocument = Components.interfaces.nsIDOMHTMLDocument; 1.51 +const nsIDOMNode = Components.interfaces.nsIDOMNode; 1.52 +const nsIDOMHTMLElement = Components.interfaces.nsIDOMHTMLElement; 1.53 +const nsIDOMWindow = Components.interfaces.nsIDOMWindow; 1.54 +const nsIDOMXULElement = Components.interfaces.nsIDOMXULElement; 1.55 + 1.56 +const nsIPropertyElement = Components.interfaces.nsIPropertyElement; 1.57 + 1.58 +//////////////////////////////////////////////////////////////////////////////// 1.59 +// OS detect 1.60 + 1.61 +const MAC = (navigator.platform.indexOf("Mac") != -1); 1.62 +const LINUX = (navigator.platform.indexOf("Linux") != -1); 1.63 +const SOLARIS = (navigator.platform.indexOf("SunOS") != -1); 1.64 +const WIN = (navigator.platform.indexOf("Win") != -1); 1.65 + 1.66 +//////////////////////////////////////////////////////////////////////////////// 1.67 +// Application detect 1.68 +// Firefox is assumed by default. 1.69 + 1.70 +const SEAMONKEY = navigator.userAgent.match(/ SeaMonkey\//); 1.71 + 1.72 +//////////////////////////////////////////////////////////////////////////////// 1.73 +// Accessible general 1.74 + 1.75 +const STATE_BUSY = nsIAccessibleStates.STATE_BUSY; 1.76 + 1.77 +const SCROLL_TYPE_ANYWHERE = nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE; 1.78 + 1.79 +const COORDTYPE_SCREEN_RELATIVE = nsIAccessibleCoordinateType.COORDTYPE_SCREEN_RELATIVE; 1.80 +const COORDTYPE_WINDOW_RELATIVE = nsIAccessibleCoordinateType.COORDTYPE_WINDOW_RELATIVE; 1.81 +const COORDTYPE_PARENT_RELATIVE = nsIAccessibleCoordinateType.COORDTYPE_PARENT_RELATIVE; 1.82 + 1.83 +const kEmbedChar = String.fromCharCode(0xfffc); 1.84 + 1.85 +const kDiscBulletChar = String.fromCharCode(0x2022); 1.86 +const kDiscBulletText = kDiscBulletChar + " "; 1.87 +const kCircleBulletText = String.fromCharCode(0x25e6) + " "; 1.88 +const kSquareBulletText = String.fromCharCode(0x25aa) + " "; 1.89 + 1.90 +const MAX_TRIM_LENGTH = 100; 1.91 + 1.92 +/** 1.93 + * nsIAccessibleRetrieval service. 1.94 + */ 1.95 +var gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"]. 1.96 + getService(nsIAccessibleRetrieval); 1.97 + 1.98 +/** 1.99 + * Enable/disable logging. 1.100 + */ 1.101 +function enableLogging(aModules) 1.102 +{ 1.103 + gAccRetrieval.setLogging(aModules); 1.104 +} 1.105 +function disableLogging() 1.106 +{ 1.107 + gAccRetrieval.setLogging(""); 1.108 +} 1.109 +function isLogged(aModule) 1.110 +{ 1.111 + return gAccRetrieval.isLogged(aModule); 1.112 +} 1.113 + 1.114 +/** 1.115 + * Invokes the given function when document is loaded and focused. Preferable 1.116 + * to mochitests 'addLoadEvent' function -- additionally ensures state of the 1.117 + * document accessible is not busy. 1.118 + * 1.119 + * @param aFunc the function to invoke 1.120 + */ 1.121 +function addA11yLoadEvent(aFunc, aWindow) 1.122 +{ 1.123 + function waitForDocLoad() 1.124 + { 1.125 + window.setTimeout( 1.126 + function() 1.127 + { 1.128 + var targetDocument = aWindow ? aWindow.document : document; 1.129 + var accDoc = getAccessible(targetDocument); 1.130 + var state = {}; 1.131 + accDoc.getState(state, {}); 1.132 + if (state.value & STATE_BUSY) 1.133 + return waitForDocLoad(); 1.134 + 1.135 + window.setTimeout(aFunc, 0); 1.136 + }, 1.137 + 0 1.138 + ); 1.139 + } 1.140 + 1.141 + SimpleTest.waitForFocus(waitForDocLoad, aWindow); 1.142 +} 1.143 + 1.144 +/** 1.145 + * Analogy of SimpleTest.is function used to compare objects. 1.146 + */ 1.147 +function isObject(aObj, aExpectedObj, aMsg) 1.148 +{ 1.149 + if (aObj == aExpectedObj) { 1.150 + ok(true, aMsg); 1.151 + return; 1.152 + } 1.153 + 1.154 + ok(false, 1.155 + aMsg + " - got '" + prettyName(aObj) + 1.156 + "', expected '" + prettyName(aExpectedObj) + "'"); 1.157 +} 1.158 + 1.159 +//////////////////////////////////////////////////////////////////////////////// 1.160 +// Helpers for getting DOM node/accessible 1.161 + 1.162 +/** 1.163 + * Return the DOM node by identifier (may be accessible, DOM node or ID). 1.164 + */ 1.165 +function getNode(aAccOrNodeOrID, aDocument) 1.166 +{ 1.167 + if (!aAccOrNodeOrID) 1.168 + return null; 1.169 + 1.170 + if (aAccOrNodeOrID instanceof nsIDOMNode) 1.171 + return aAccOrNodeOrID; 1.172 + 1.173 + if (aAccOrNodeOrID instanceof nsIAccessible) 1.174 + return aAccOrNodeOrID.DOMNode; 1.175 + 1.176 + node = (aDocument || document).getElementById(aAccOrNodeOrID); 1.177 + if (!node) { 1.178 + ok(false, "Can't get DOM element for " + aAccOrNodeOrID); 1.179 + return null; 1.180 + } 1.181 + 1.182 + return node; 1.183 +} 1.184 + 1.185 +/** 1.186 + * Constants indicates getAccessible doesn't fail if there is no accessible. 1.187 + */ 1.188 +const DONOTFAIL_IF_NO_ACC = 1; 1.189 + 1.190 +/** 1.191 + * Constants indicates getAccessible won't fail if accessible doesn't implement 1.192 + * the requested interfaces. 1.193 + */ 1.194 +const DONOTFAIL_IF_NO_INTERFACE = 2; 1.195 + 1.196 +/** 1.197 + * Return accessible for the given identifier (may be ID attribute or DOM 1.198 + * element or accessible object) or null. 1.199 + * 1.200 + * @param aAccOrElmOrID [in] identifier to get an accessible implementing 1.201 + * the given interfaces 1.202 + * @param aInterfaces [in, optional] the interface or an array interfaces 1.203 + * to query it/them from obtained accessible 1.204 + * @param aElmObj [out, optional] object to store DOM element which 1.205 + * accessible is obtained for 1.206 + * @param aDoNotFailIf [in, optional] no error for special cases (see 1.207 + * constants above) 1.208 + */ 1.209 +function getAccessible(aAccOrElmOrID, aInterfaces, aElmObj, aDoNotFailIf) 1.210 +{ 1.211 + if (!aAccOrElmOrID) 1.212 + return null; 1.213 + 1.214 + var elm = null; 1.215 + 1.216 + if (aAccOrElmOrID instanceof nsIAccessible) { 1.217 + elm = aAccOrElmOrID.DOMNode; 1.218 + 1.219 + } else if (aAccOrElmOrID instanceof nsIDOMNode) { 1.220 + elm = aAccOrElmOrID; 1.221 + 1.222 + } else { 1.223 + elm = document.getElementById(aAccOrElmOrID); 1.224 + if (!elm) { 1.225 + ok(false, "Can't get DOM element for " + aAccOrElmOrID); 1.226 + return null; 1.227 + } 1.228 + } 1.229 + 1.230 + if (aElmObj && (typeof aElmObj == "object")) 1.231 + aElmObj.value = elm; 1.232 + 1.233 + var acc = (aAccOrElmOrID instanceof nsIAccessible) ? aAccOrElmOrID : null; 1.234 + if (!acc) { 1.235 + try { 1.236 + acc = gAccRetrieval.getAccessibleFor(elm); 1.237 + } catch (e) { 1.238 + } 1.239 + 1.240 + if (!acc) { 1.241 + if (!(aDoNotFailIf & DONOTFAIL_IF_NO_ACC)) 1.242 + ok(false, "Can't get accessible for " + aAccOrElmOrID); 1.243 + 1.244 + return null; 1.245 + } 1.246 + } 1.247 + 1.248 + if (!aInterfaces) 1.249 + return acc; 1.250 + 1.251 + if (!(aInterfaces instanceof Array)) 1.252 + aInterfaces = [ aInterfaces ]; 1.253 + 1.254 + for (var index = 0; index < aInterfaces.length; index++) { 1.255 + try { 1.256 + acc.QueryInterface(aInterfaces[index]); 1.257 + } catch (e) { 1.258 + if (!(aDoNotFailIf & DONOTFAIL_IF_NO_INTERFACE)) 1.259 + ok(false, "Can't query " + aInterfaces[index] + " for " + aAccOrElmOrID); 1.260 + 1.261 + return null; 1.262 + } 1.263 + } 1.264 + 1.265 + return acc; 1.266 +} 1.267 + 1.268 +/** 1.269 + * Return true if the given identifier has an accessible, or exposes the wanted 1.270 + * interfaces. 1.271 + */ 1.272 +function isAccessible(aAccOrElmOrID, aInterfaces) 1.273 +{ 1.274 + return getAccessible(aAccOrElmOrID, aInterfaces, null, 1.275 + DONOTFAIL_IF_NO_ACC | DONOTFAIL_IF_NO_INTERFACE) ? 1.276 + true : false; 1.277 +} 1.278 + 1.279 +/** 1.280 + * Return an accessible that contains the DOM node for the given identifier. 1.281 + */ 1.282 +function getContainerAccessible(aAccOrElmOrID) 1.283 +{ 1.284 + var node = getNode(aAccOrElmOrID); 1.285 + if (!node) 1.286 + return null; 1.287 + 1.288 + while ((node = node.parentNode) && !isAccessible(node)); 1.289 + return node ? getAccessible(node) : null; 1.290 +} 1.291 + 1.292 +/** 1.293 + * Return root accessible for the given identifier. 1.294 + */ 1.295 +function getRootAccessible(aAccOrElmOrID) 1.296 +{ 1.297 + var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document); 1.298 + return acc ? acc.rootDocument.QueryInterface(nsIAccessible) : null; 1.299 +} 1.300 + 1.301 +/** 1.302 + * Return tab document accessible the given accessible is contained by. 1.303 + */ 1.304 +function getTabDocAccessible(aAccOrElmOrID) 1.305 +{ 1.306 + var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document); 1.307 + 1.308 + var docAcc = acc.document.QueryInterface(nsIAccessible); 1.309 + var containerDocAcc = docAcc.parent.document; 1.310 + 1.311 + // Test is running is stand-alone mode. 1.312 + if (acc.rootDocument == containerDocAcc) 1.313 + return docAcc; 1.314 + 1.315 + // In the case of running all tests together. 1.316 + return containerDocAcc.QueryInterface(nsIAccessible); 1.317 +} 1.318 + 1.319 +/** 1.320 + * Return application accessible. 1.321 + */ 1.322 +function getApplicationAccessible() 1.323 +{ 1.324 + return gAccRetrieval.getApplicationAccessible(). 1.325 + QueryInterface(nsIAccessibleApplication); 1.326 +} 1.327 + 1.328 +/** 1.329 + * A version of accessible tree testing, doesn't fail if tree is not complete. 1.330 + */ 1.331 +function testElm(aID, aTreeObj) 1.332 +{ 1.333 + testAccessibleTree(aID, aTreeObj, kSkipTreeFullCheck); 1.334 +} 1.335 + 1.336 +/** 1.337 + * Flags used for testAccessibleTree 1.338 + */ 1.339 +const kSkipTreeFullCheck = 1; 1.340 + 1.341 +/** 1.342 + * Compare expected and actual accessibles trees. 1.343 + * 1.344 + * @param aAccOrElmOrID [in] accessible identifier 1.345 + * @param aAccTree [in] JS object, each field corresponds to property of 1.346 + * accessible object. Additionally special properties 1.347 + * are presented: 1.348 + * children - an array of JS objects representing 1.349 + * children of accessible 1.350 + * states - an object having states and extraStates 1.351 + * fields 1.352 + * @param aFlags [in, optional] flags, see constants above 1.353 + */ 1.354 +function testAccessibleTree(aAccOrElmOrID, aAccTree, aFlags) 1.355 +{ 1.356 + var acc = getAccessible(aAccOrElmOrID); 1.357 + if (!acc) 1.358 + return; 1.359 + 1.360 + var accTree = aAccTree; 1.361 + 1.362 + // Support of simplified accessible tree object. 1.363 + var key = Object.keys(accTree)[0]; 1.364 + var roleName = "ROLE_" + key; 1.365 + if (roleName in nsIAccessibleRole) { 1.366 + accTree = { 1.367 + role: nsIAccessibleRole[roleName], 1.368 + children: accTree[key] 1.369 + }; 1.370 + } 1.371 + 1.372 + // Test accessible properties. 1.373 + for (var prop in accTree) { 1.374 + var msg = "Wrong value of property '" + prop + "' for " + prettyName(acc) + "."; 1.375 + 1.376 + switch (prop) { 1.377 + case "actions": { 1.378 + testActionNames(acc, accTree.actions); 1.379 + break; 1.380 + } 1.381 + 1.382 + case "attributes": 1.383 + testAttrs(acc, accTree[prop], true); 1.384 + break; 1.385 + 1.386 + case "absentAttributes": 1.387 + testAbsentAttrs(acc, accTree[prop]); 1.388 + break; 1.389 + 1.390 + case "interfaces": { 1.391 + var ifaces = (accTree[prop] instanceof Array) ? 1.392 + accTree[prop] : [ accTree[prop] ]; 1.393 + for (var i = 0; i < ifaces.length; i++) { 1.394 + ok((acc instanceof ifaces[i]), 1.395 + "No " + ifaces[i] + " interface on " + prettyName(acc)); 1.396 + } 1.397 + break; 1.398 + } 1.399 + 1.400 + case "relations": { 1.401 + for (var rel in accTree[prop]) 1.402 + testRelation(acc, window[rel], accTree[prop][rel]); 1.403 + break; 1.404 + } 1.405 + 1.406 + case "role": 1.407 + isRole(acc, accTree[prop], msg); 1.408 + break; 1.409 + 1.410 + case "states": 1.411 + case "extraStates": 1.412 + case "absentStates": 1.413 + case "absentExtraStates": { 1.414 + testStates(acc, accTree["states"], accTree["extraStates"], 1.415 + accTree["absentStates"], accTree["absentExtraStates"]); 1.416 + break; 1.417 + } 1.418 + 1.419 + case "tagName": 1.420 + is(accTree[prop], acc.DOMNode.tagName, msg); 1.421 + break; 1.422 + 1.423 + case "textAttrs": { 1.424 + var prevOffset = -1; 1.425 + for (var offset in accTree[prop]) { 1.426 + if (prevOffset !=- 1) { 1.427 + var attrs = accTree[prop][prevOffset]; 1.428 + testTextAttrs(acc, prevOffset, attrs, { }, prevOffset, offset, true); 1.429 + } 1.430 + prevOffset = offset; 1.431 + } 1.432 + 1.433 + if (prevOffset != -1) { 1.434 + var charCount = getAccessible(acc, [nsIAccessibleText]).characterCount; 1.435 + var attrs = accTree[prop][prevOffset]; 1.436 + testTextAttrs(acc, prevOffset, attrs, { }, prevOffset, charCount, true); 1.437 + } 1.438 + 1.439 + break; 1.440 + } 1.441 + 1.442 + default: 1.443 + if (prop.indexOf("todo_") == 0) 1.444 + todo(false, msg); 1.445 + else if (prop != "children") 1.446 + is(acc[prop], accTree[prop], msg); 1.447 + } 1.448 + } 1.449 + 1.450 + // Test children. 1.451 + if ("children" in accTree && accTree["children"] instanceof Array) { 1.452 + var children = acc.children; 1.453 + var childCount = children.length; 1.454 + 1.455 + is(childCount, accTree.children.length, 1.456 + "Different amount of expected children of " + prettyName(acc) + "."); 1.457 + 1.458 + if (accTree.children.length == childCount) { 1.459 + if (aFlags & kSkipTreeFullCheck) { 1.460 + for (var i = 0; i < childCount; i++) { 1.461 + var child = children.queryElementAt(i, nsIAccessible); 1.462 + testAccessibleTree(child, accTree.children[i], aFlags); 1.463 + } 1.464 + return; 1.465 + } 1.466 + 1.467 + // nsIAccessible::firstChild 1.468 + var expectedFirstChild = childCount > 0 ? 1.469 + children.queryElementAt(0, nsIAccessible) : null; 1.470 + var firstChild = null; 1.471 + try { firstChild = acc.firstChild; } catch (e) {} 1.472 + is(firstChild, expectedFirstChild, 1.473 + "Wrong first child of " + prettyName(acc)); 1.474 + 1.475 + // nsIAccessible::lastChild 1.476 + var expectedLastChild = childCount > 0 ? 1.477 + children.queryElementAt(childCount - 1, nsIAccessible) : null; 1.478 + var lastChild = null; 1.479 + try { lastChild = acc.lastChild; } catch (e) {} 1.480 + is(lastChild, expectedLastChild, 1.481 + "Wrong last child of " + prettyName(acc)); 1.482 + 1.483 + for (var i = 0; i < childCount; i++) { 1.484 + var child = children.queryElementAt(i, nsIAccessible); 1.485 + 1.486 + // nsIAccessible::parent 1.487 + var parent = null; 1.488 + try { parent = child.parent; } catch (e) {} 1.489 + is(parent, acc, "Wrong parent of " + prettyName(child)); 1.490 + 1.491 + // nsIAccessible::indexInParent 1.492 + var indexInParent = -1; 1.493 + try { indexInParent = child.indexInParent; } catch(e) {} 1.494 + is(indexInParent, i, 1.495 + "Wrong index in parent of " + prettyName(child)); 1.496 + 1.497 + // nsIAccessible::nextSibling 1.498 + var expectedNextSibling = (i < childCount - 1) ? 1.499 + children.queryElementAt(i + 1, nsIAccessible) : null; 1.500 + var nextSibling = null; 1.501 + try { nextSibling = child.nextSibling; } catch (e) {} 1.502 + is(nextSibling, expectedNextSibling, 1.503 + "Wrong next sibling of " + prettyName(child)); 1.504 + 1.505 + // nsIAccessible::previousSibling 1.506 + var expectedPrevSibling = (i > 0) ? 1.507 + children.queryElementAt(i - 1, nsIAccessible) : null; 1.508 + var prevSibling = null; 1.509 + try { prevSibling = child.previousSibling; } catch (e) {} 1.510 + is(prevSibling, expectedPrevSibling, 1.511 + "Wrong previous sibling of " + prettyName(child)); 1.512 + 1.513 + // Go down through subtree 1.514 + testAccessibleTree(child, accTree.children[i], aFlags); 1.515 + } 1.516 + } 1.517 + } 1.518 +} 1.519 + 1.520 +/** 1.521 + * Return true if accessible for the given node is in cache. 1.522 + */ 1.523 +function isAccessibleInCache(aNodeOrId) 1.524 +{ 1.525 + var node = getNode(aNodeOrId); 1.526 + return gAccRetrieval.getAccessibleFromCache(node) ? true : false; 1.527 +} 1.528 + 1.529 +/** 1.530 + * Test accessible tree for defunct accessible. 1.531 + * 1.532 + * @param aAcc [in] the defunct accessible 1.533 + * @param aNodeOrId [in] the DOM node identifier for the defunct accessible 1.534 + */ 1.535 +function testDefunctAccessible(aAcc, aNodeOrId) 1.536 +{ 1.537 + if (aNodeOrId) 1.538 + ok(!isAccessible(aNodeOrId), 1.539 + "Accessible for " + aNodeOrId + " wasn't properly shut down!"); 1.540 + 1.541 + var msg = " doesn't fail for shut down accessible " + prettyName(aNodeOrId) + "!"; 1.542 + 1.543 + // firstChild 1.544 + var success = false; 1.545 + try { 1.546 + aAcc.firstChild; 1.547 + } catch (e) { 1.548 + success = (e.result == Components.results.NS_ERROR_FAILURE) 1.549 + } 1.550 + ok(success, "firstChild" + msg); 1.551 + 1.552 + // lastChild 1.553 + success = false; 1.554 + try { 1.555 + aAcc.lastChild; 1.556 + } catch (e) { 1.557 + success = (e.result == Components.results.NS_ERROR_FAILURE) 1.558 + } 1.559 + ok(success, "lastChild" + msg); 1.560 + 1.561 + // childCount 1.562 + success = false; 1.563 + try { 1.564 + aAcc.childCount; 1.565 + } catch (e) { 1.566 + success = (e.result == Components.results.NS_ERROR_FAILURE) 1.567 + } 1.568 + ok(success, "childCount" + msg); 1.569 + 1.570 + // children 1.571 + success = false; 1.572 + try { 1.573 + aAcc.children; 1.574 + } catch (e) { 1.575 + success = (e.result == Components.results.NS_ERROR_FAILURE) 1.576 + } 1.577 + ok(success, "children" + msg); 1.578 + 1.579 + // nextSibling 1.580 + success = false; 1.581 + try { 1.582 + aAcc.nextSibling; 1.583 + } catch (e) { 1.584 + success = (e.result == Components.results.NS_ERROR_FAILURE); 1.585 + } 1.586 + ok(success, "nextSibling" + msg); 1.587 + 1.588 + // previousSibling 1.589 + success = false; 1.590 + try { 1.591 + aAcc.previousSibling; 1.592 + } catch (e) { 1.593 + success = (e.result == Components.results.NS_ERROR_FAILURE); 1.594 + } 1.595 + ok(success, "previousSibling" + msg); 1.596 + 1.597 + // parent 1.598 + success = false; 1.599 + try { 1.600 + aAcc.parent; 1.601 + } catch (e) { 1.602 + success = (e.result == Components.results.NS_ERROR_FAILURE); 1.603 + } 1.604 + ok(success, "parent" + msg); 1.605 +} 1.606 + 1.607 +/** 1.608 + * Convert role to human readable string. 1.609 + */ 1.610 +function roleToString(aRole) 1.611 +{ 1.612 + return gAccRetrieval.getStringRole(aRole); 1.613 +} 1.614 + 1.615 +/** 1.616 + * Convert states to human readable string. 1.617 + */ 1.618 +function statesToString(aStates, aExtraStates) 1.619 +{ 1.620 + var list = gAccRetrieval.getStringStates(aStates, aExtraStates); 1.621 + 1.622 + var str = ""; 1.623 + for (var index = 0; index < list.length - 1; index++) 1.624 + str += list.item(index) + ", "; 1.625 + 1.626 + if (list.length != 0) 1.627 + str += list.item(index) 1.628 + 1.629 + return str; 1.630 +} 1.631 + 1.632 +/** 1.633 + * Convert event type to human readable string. 1.634 + */ 1.635 +function eventTypeToString(aEventType) 1.636 +{ 1.637 + return gAccRetrieval.getStringEventType(aEventType); 1.638 +} 1.639 + 1.640 +/** 1.641 + * Convert relation type to human readable string. 1.642 + */ 1.643 +function relationTypeToString(aRelationType) 1.644 +{ 1.645 + return gAccRetrieval.getStringRelationType(aRelationType); 1.646 +} 1.647 + 1.648 +function getLoadContext() { 1.649 + const Ci = Components.interfaces; 1.650 + return window.QueryInterface(Ci.nsIInterfaceRequestor) 1.651 + .getInterface(Ci.nsIWebNavigation) 1.652 + .QueryInterface(Ci.nsILoadContext); 1.653 +} 1.654 + 1.655 +/** 1.656 + * Return text from clipboard. 1.657 + */ 1.658 +function getTextFromClipboard() 1.659 +{ 1.660 + var clip = Components.classes["@mozilla.org/widget/clipboard;1"]. 1.661 + getService(Components.interfaces.nsIClipboard); 1.662 + if (!clip) 1.663 + return ""; 1.664 + 1.665 + var trans = Components.classes["@mozilla.org/widget/transferable;1"]. 1.666 + createInstance(Components.interfaces.nsITransferable); 1.667 + trans.init(getLoadContext()); 1.668 + if (!trans) 1.669 + return ""; 1.670 + 1.671 + trans.addDataFlavor("text/unicode"); 1.672 + clip.getData(trans, clip.kGlobalClipboard); 1.673 + 1.674 + var str = new Object(); 1.675 + var strLength = new Object(); 1.676 + trans.getTransferData("text/unicode", str, strLength); 1.677 + 1.678 + if (str) 1.679 + str = str.value.QueryInterface(Components.interfaces.nsISupportsString); 1.680 + if (str) 1.681 + return str.data.substring(0, strLength.value / 2); 1.682 + 1.683 + return ""; 1.684 +} 1.685 + 1.686 +/** 1.687 + * Return pretty name for identifier, it may be ID, DOM node or accessible. 1.688 + */ 1.689 +function prettyName(aIdentifier) 1.690 +{ 1.691 + if (aIdentifier instanceof Array) { 1.692 + var msg = ""; 1.693 + for (var idx = 0; idx < aIdentifier.length; idx++) { 1.694 + if (msg != "") 1.695 + msg += ", "; 1.696 + 1.697 + msg += prettyName(aIdentifier[idx]); 1.698 + } 1.699 + return msg; 1.700 + } 1.701 + 1.702 + if (aIdentifier instanceof nsIAccessible) { 1.703 + var acc = getAccessible(aIdentifier); 1.704 + var msg = "[" + getNodePrettyName(acc.DOMNode); 1.705 + try { 1.706 + msg += ", role: " + roleToString(acc.role); 1.707 + if (acc.name) 1.708 + msg += ", name: '" + shortenString(acc.name) + "'"; 1.709 + } catch (e) { 1.710 + msg += "defunct"; 1.711 + } 1.712 + 1.713 + if (acc) 1.714 + msg += ", address: " + getObjAddress(acc); 1.715 + msg += "]"; 1.716 + 1.717 + return msg; 1.718 + } 1.719 + 1.720 + if (aIdentifier instanceof nsIDOMNode) 1.721 + return "[ " + getNodePrettyName(aIdentifier) + " ]"; 1.722 + 1.723 + return " '" + aIdentifier + "' "; 1.724 +} 1.725 + 1.726 +/** 1.727 + * Shorten a long string if it exceeds MAX_TRIM_LENGTH. 1.728 + * @param aString the string to shorten. 1.729 + * @returns the shortened string. 1.730 + */ 1.731 +function shortenString(aString, aMaxLength) 1.732 +{ 1.733 + if (aString.length <= MAX_TRIM_LENGTH) 1.734 + return aString; 1.735 + 1.736 + // Trim the string if its length is > MAX_TRIM_LENGTH characters. 1.737 + var trimOffset = MAX_TRIM_LENGTH / 2; 1.738 + return aString.substring(0, trimOffset - 1) + "..." + 1.739 + aString.substring(aString.length - trimOffset, aString.length); 1.740 +} 1.741 + 1.742 +//////////////////////////////////////////////////////////////////////////////// 1.743 +// General Utils 1.744 +//////////////////////////////////////////////////////////////////////////////// 1.745 +/** 1.746 + * Return main chrome window (crosses chrome boundary) 1.747 + */ 1.748 +function getMainChromeWindow(aWindow) 1.749 +{ 1.750 + return aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor) 1.751 + .getInterface(Components.interfaces.nsIWebNavigation) 1.752 + .QueryInterface(Components.interfaces.nsIDocShellTreeItem) 1.753 + .rootTreeItem 1.754 + .QueryInterface(Components.interfaces.nsIInterfaceRequestor) 1.755 + .getInterface(Components.interfaces.nsIDOMWindow); 1.756 +} 1.757 + 1.758 +/** Sets the test plugin(s) initially expected enabled state. 1.759 + * It will automatically be reset to it's previous value after the test 1.760 + * ends. 1.761 + * @param aNewEnabledState [in] the enabled state, e.g. SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED 1.762 + * @param aPluginName [in, optional] The name of the plugin, defaults to "Test Plug-in" 1.763 + */ 1.764 +function setTestPluginEnabledState(aNewEnabledState, aPluginName) 1.765 +{ 1.766 + var plugin = getTestPluginTag(aPluginName); 1.767 + var oldEnabledState = plugin.enabledState; 1.768 + plugin.enabledState = aNewEnabledState; 1.769 + SimpleTest.registerCleanupFunction(function() { 1.770 + getTestPluginTag(aPluginName).enabledState = oldEnabledState; 1.771 + }); 1.772 +} 1.773 + 1.774 +//////////////////////////////////////////////////////////////////////////////// 1.775 +// Private 1.776 +//////////////////////////////////////////////////////////////////////////////// 1.777 + 1.778 +//////////////////////////////////////////////////////////////////////////////// 1.779 +// Accessible general 1.780 + 1.781 +function getNodePrettyName(aNode) 1.782 +{ 1.783 + try { 1.784 + var tag = ""; 1.785 + if (aNode.nodeType == nsIDOMNode.DOCUMENT_NODE) { 1.786 + tag = "document"; 1.787 + } else { 1.788 + tag = aNode.localName; 1.789 + if (aNode.nodeType == nsIDOMNode.ELEMENT_NODE && aNode.hasAttribute("id")) 1.790 + tag += "@id=\"" + aNode.getAttribute("id") + "\""; 1.791 + } 1.792 + 1.793 + return "'" + tag + " node', address: " + getObjAddress(aNode); 1.794 + } catch (e) { 1.795 + return "' no node info '"; 1.796 + } 1.797 +} 1.798 + 1.799 +function getObjAddress(aObj) 1.800 +{ 1.801 + var exp = /native\s*@\s*(0x[a-f0-9]+)/g; 1.802 + var match = exp.exec(aObj.toString()); 1.803 + if (match) 1.804 + return match[1]; 1.805 + 1.806 + return aObj.toString(); 1.807 +} 1.808 + 1.809 +function getTestPluginTag(aPluginName) 1.810 +{ 1.811 + var ph = SpecialPowers.Cc["@mozilla.org/plugin/host;1"] 1.812 + .getService(SpecialPowers.Ci.nsIPluginHost); 1.813 + var tags = ph.getPluginTags(); 1.814 + var name = aPluginName || "Test Plug-in"; 1.815 + for (var tag of tags) { 1.816 + if (tag.name == name) { 1.817 + return tag; 1.818 + } 1.819 + } 1.820 + 1.821 + ok(false, "Could not find plugin tag with plugin name '" + name + "'"); 1.822 + return null; 1.823 +}