Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 ////////////////////////////////////////////////////////////////////////////////
2 // Interfaces
4 const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
6 const nsIAccessibleEvent = Components.interfaces.nsIAccessibleEvent;
7 const nsIAccessibleStateChangeEvent =
8 Components.interfaces.nsIAccessibleStateChangeEvent;
9 const nsIAccessibleCaretMoveEvent =
10 Components.interfaces.nsIAccessibleCaretMoveEvent;
11 const nsIAccessibleTextChangeEvent =
12 Components.interfaces.nsIAccessibleTextChangeEvent;
13 const nsIAccessibleVirtualCursorChangeEvent =
14 Components.interfaces.nsIAccessibleVirtualCursorChangeEvent;
16 const nsIAccessibleStates = Components.interfaces.nsIAccessibleStates;
17 const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
18 const nsIAccessibleScrollType = Components.interfaces.nsIAccessibleScrollType;
19 const nsIAccessibleCoordinateType = Components.interfaces.nsIAccessibleCoordinateType;
21 const nsIAccessibleRelation = Components.interfaces.nsIAccessibleRelation;
23 const nsIAccessible = Components.interfaces.nsIAccessible;
25 const nsIAccessibleDocument = Components.interfaces.nsIAccessibleDocument;
26 const nsIAccessibleApplication = Components.interfaces.nsIAccessibleApplication;
28 const nsIAccessibleText = Components.interfaces.nsIAccessibleText;
29 const nsIAccessibleEditableText = Components.interfaces.nsIAccessibleEditableText;
31 const nsIAccessibleHyperLink = Components.interfaces.nsIAccessibleHyperLink;
32 const nsIAccessibleHyperText = Components.interfaces.nsIAccessibleHyperText;
34 const nsIAccessibleCursorable = Components.interfaces.nsIAccessibleCursorable;
35 const nsIAccessibleImage = Components.interfaces.nsIAccessibleImage;
36 const nsIAccessiblePivot = Components.interfaces.nsIAccessiblePivot;
37 const nsIAccessibleSelectable = Components.interfaces.nsIAccessibleSelectable;
38 const nsIAccessibleTable = Components.interfaces.nsIAccessibleTable;
39 const nsIAccessibleTableCell = Components.interfaces.nsIAccessibleTableCell;
40 const nsIAccessibleTraversalRule = Components.interfaces.nsIAccessibleTraversalRule;
41 const nsIAccessibleValue = Components.interfaces.nsIAccessibleValue;
43 const nsIObserverService = Components.interfaces.nsIObserverService;
45 const nsIDOMDocument = Components.interfaces.nsIDOMDocument;
46 const nsIDOMEvent = Components.interfaces.nsIDOMEvent;
47 const nsIDOMHTMLDocument = Components.interfaces.nsIDOMHTMLDocument;
48 const nsIDOMNode = Components.interfaces.nsIDOMNode;
49 const nsIDOMHTMLElement = Components.interfaces.nsIDOMHTMLElement;
50 const nsIDOMWindow = Components.interfaces.nsIDOMWindow;
51 const nsIDOMXULElement = Components.interfaces.nsIDOMXULElement;
53 const nsIPropertyElement = Components.interfaces.nsIPropertyElement;
55 ////////////////////////////////////////////////////////////////////////////////
56 // OS detect
58 const MAC = (navigator.platform.indexOf("Mac") != -1);
59 const LINUX = (navigator.platform.indexOf("Linux") != -1);
60 const SOLARIS = (navigator.platform.indexOf("SunOS") != -1);
61 const WIN = (navigator.platform.indexOf("Win") != -1);
63 ////////////////////////////////////////////////////////////////////////////////
64 // Application detect
65 // Firefox is assumed by default.
67 const SEAMONKEY = navigator.userAgent.match(/ SeaMonkey\//);
69 ////////////////////////////////////////////////////////////////////////////////
70 // Accessible general
72 const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;
74 const SCROLL_TYPE_ANYWHERE = nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE;
76 const COORDTYPE_SCREEN_RELATIVE = nsIAccessibleCoordinateType.COORDTYPE_SCREEN_RELATIVE;
77 const COORDTYPE_WINDOW_RELATIVE = nsIAccessibleCoordinateType.COORDTYPE_WINDOW_RELATIVE;
78 const COORDTYPE_PARENT_RELATIVE = nsIAccessibleCoordinateType.COORDTYPE_PARENT_RELATIVE;
80 const kEmbedChar = String.fromCharCode(0xfffc);
82 const kDiscBulletChar = String.fromCharCode(0x2022);
83 const kDiscBulletText = kDiscBulletChar + " ";
84 const kCircleBulletText = String.fromCharCode(0x25e6) + " ";
85 const kSquareBulletText = String.fromCharCode(0x25aa) + " ";
87 const MAX_TRIM_LENGTH = 100;
89 /**
90 * nsIAccessibleRetrieval service.
91 */
92 var gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
93 getService(nsIAccessibleRetrieval);
95 /**
96 * Enable/disable logging.
97 */
98 function enableLogging(aModules)
99 {
100 gAccRetrieval.setLogging(aModules);
101 }
102 function disableLogging()
103 {
104 gAccRetrieval.setLogging("");
105 }
106 function isLogged(aModule)
107 {
108 return gAccRetrieval.isLogged(aModule);
109 }
111 /**
112 * Invokes the given function when document is loaded and focused. Preferable
113 * to mochitests 'addLoadEvent' function -- additionally ensures state of the
114 * document accessible is not busy.
115 *
116 * @param aFunc the function to invoke
117 */
118 function addA11yLoadEvent(aFunc, aWindow)
119 {
120 function waitForDocLoad()
121 {
122 window.setTimeout(
123 function()
124 {
125 var targetDocument = aWindow ? aWindow.document : document;
126 var accDoc = getAccessible(targetDocument);
127 var state = {};
128 accDoc.getState(state, {});
129 if (state.value & STATE_BUSY)
130 return waitForDocLoad();
132 window.setTimeout(aFunc, 0);
133 },
134 0
135 );
136 }
138 SimpleTest.waitForFocus(waitForDocLoad, aWindow);
139 }
141 /**
142 * Analogy of SimpleTest.is function used to compare objects.
143 */
144 function isObject(aObj, aExpectedObj, aMsg)
145 {
146 if (aObj == aExpectedObj) {
147 ok(true, aMsg);
148 return;
149 }
151 ok(false,
152 aMsg + " - got '" + prettyName(aObj) +
153 "', expected '" + prettyName(aExpectedObj) + "'");
154 }
156 ////////////////////////////////////////////////////////////////////////////////
157 // Helpers for getting DOM node/accessible
159 /**
160 * Return the DOM node by identifier (may be accessible, DOM node or ID).
161 */
162 function getNode(aAccOrNodeOrID, aDocument)
163 {
164 if (!aAccOrNodeOrID)
165 return null;
167 if (aAccOrNodeOrID instanceof nsIDOMNode)
168 return aAccOrNodeOrID;
170 if (aAccOrNodeOrID instanceof nsIAccessible)
171 return aAccOrNodeOrID.DOMNode;
173 node = (aDocument || document).getElementById(aAccOrNodeOrID);
174 if (!node) {
175 ok(false, "Can't get DOM element for " + aAccOrNodeOrID);
176 return null;
177 }
179 return node;
180 }
182 /**
183 * Constants indicates getAccessible doesn't fail if there is no accessible.
184 */
185 const DONOTFAIL_IF_NO_ACC = 1;
187 /**
188 * Constants indicates getAccessible won't fail if accessible doesn't implement
189 * the requested interfaces.
190 */
191 const DONOTFAIL_IF_NO_INTERFACE = 2;
193 /**
194 * Return accessible for the given identifier (may be ID attribute or DOM
195 * element or accessible object) or null.
196 *
197 * @param aAccOrElmOrID [in] identifier to get an accessible implementing
198 * the given interfaces
199 * @param aInterfaces [in, optional] the interface or an array interfaces
200 * to query it/them from obtained accessible
201 * @param aElmObj [out, optional] object to store DOM element which
202 * accessible is obtained for
203 * @param aDoNotFailIf [in, optional] no error for special cases (see
204 * constants above)
205 */
206 function getAccessible(aAccOrElmOrID, aInterfaces, aElmObj, aDoNotFailIf)
207 {
208 if (!aAccOrElmOrID)
209 return null;
211 var elm = null;
213 if (aAccOrElmOrID instanceof nsIAccessible) {
214 elm = aAccOrElmOrID.DOMNode;
216 } else if (aAccOrElmOrID instanceof nsIDOMNode) {
217 elm = aAccOrElmOrID;
219 } else {
220 elm = document.getElementById(aAccOrElmOrID);
221 if (!elm) {
222 ok(false, "Can't get DOM element for " + aAccOrElmOrID);
223 return null;
224 }
225 }
227 if (aElmObj && (typeof aElmObj == "object"))
228 aElmObj.value = elm;
230 var acc = (aAccOrElmOrID instanceof nsIAccessible) ? aAccOrElmOrID : null;
231 if (!acc) {
232 try {
233 acc = gAccRetrieval.getAccessibleFor(elm);
234 } catch (e) {
235 }
237 if (!acc) {
238 if (!(aDoNotFailIf & DONOTFAIL_IF_NO_ACC))
239 ok(false, "Can't get accessible for " + aAccOrElmOrID);
241 return null;
242 }
243 }
245 if (!aInterfaces)
246 return acc;
248 if (!(aInterfaces instanceof Array))
249 aInterfaces = [ aInterfaces ];
251 for (var index = 0; index < aInterfaces.length; index++) {
252 try {
253 acc.QueryInterface(aInterfaces[index]);
254 } catch (e) {
255 if (!(aDoNotFailIf & DONOTFAIL_IF_NO_INTERFACE))
256 ok(false, "Can't query " + aInterfaces[index] + " for " + aAccOrElmOrID);
258 return null;
259 }
260 }
262 return acc;
263 }
265 /**
266 * Return true if the given identifier has an accessible, or exposes the wanted
267 * interfaces.
268 */
269 function isAccessible(aAccOrElmOrID, aInterfaces)
270 {
271 return getAccessible(aAccOrElmOrID, aInterfaces, null,
272 DONOTFAIL_IF_NO_ACC | DONOTFAIL_IF_NO_INTERFACE) ?
273 true : false;
274 }
276 /**
277 * Return an accessible that contains the DOM node for the given identifier.
278 */
279 function getContainerAccessible(aAccOrElmOrID)
280 {
281 var node = getNode(aAccOrElmOrID);
282 if (!node)
283 return null;
285 while ((node = node.parentNode) && !isAccessible(node));
286 return node ? getAccessible(node) : null;
287 }
289 /**
290 * Return root accessible for the given identifier.
291 */
292 function getRootAccessible(aAccOrElmOrID)
293 {
294 var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document);
295 return acc ? acc.rootDocument.QueryInterface(nsIAccessible) : null;
296 }
298 /**
299 * Return tab document accessible the given accessible is contained by.
300 */
301 function getTabDocAccessible(aAccOrElmOrID)
302 {
303 var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document);
305 var docAcc = acc.document.QueryInterface(nsIAccessible);
306 var containerDocAcc = docAcc.parent.document;
308 // Test is running is stand-alone mode.
309 if (acc.rootDocument == containerDocAcc)
310 return docAcc;
312 // In the case of running all tests together.
313 return containerDocAcc.QueryInterface(nsIAccessible);
314 }
316 /**
317 * Return application accessible.
318 */
319 function getApplicationAccessible()
320 {
321 return gAccRetrieval.getApplicationAccessible().
322 QueryInterface(nsIAccessibleApplication);
323 }
325 /**
326 * A version of accessible tree testing, doesn't fail if tree is not complete.
327 */
328 function testElm(aID, aTreeObj)
329 {
330 testAccessibleTree(aID, aTreeObj, kSkipTreeFullCheck);
331 }
333 /**
334 * Flags used for testAccessibleTree
335 */
336 const kSkipTreeFullCheck = 1;
338 /**
339 * Compare expected and actual accessibles trees.
340 *
341 * @param aAccOrElmOrID [in] accessible identifier
342 * @param aAccTree [in] JS object, each field corresponds to property of
343 * accessible object. Additionally special properties
344 * are presented:
345 * children - an array of JS objects representing
346 * children of accessible
347 * states - an object having states and extraStates
348 * fields
349 * @param aFlags [in, optional] flags, see constants above
350 */
351 function testAccessibleTree(aAccOrElmOrID, aAccTree, aFlags)
352 {
353 var acc = getAccessible(aAccOrElmOrID);
354 if (!acc)
355 return;
357 var accTree = aAccTree;
359 // Support of simplified accessible tree object.
360 var key = Object.keys(accTree)[0];
361 var roleName = "ROLE_" + key;
362 if (roleName in nsIAccessibleRole) {
363 accTree = {
364 role: nsIAccessibleRole[roleName],
365 children: accTree[key]
366 };
367 }
369 // Test accessible properties.
370 for (var prop in accTree) {
371 var msg = "Wrong value of property '" + prop + "' for " + prettyName(acc) + ".";
373 switch (prop) {
374 case "actions": {
375 testActionNames(acc, accTree.actions);
376 break;
377 }
379 case "attributes":
380 testAttrs(acc, accTree[prop], true);
381 break;
383 case "absentAttributes":
384 testAbsentAttrs(acc, accTree[prop]);
385 break;
387 case "interfaces": {
388 var ifaces = (accTree[prop] instanceof Array) ?
389 accTree[prop] : [ accTree[prop] ];
390 for (var i = 0; i < ifaces.length; i++) {
391 ok((acc instanceof ifaces[i]),
392 "No " + ifaces[i] + " interface on " + prettyName(acc));
393 }
394 break;
395 }
397 case "relations": {
398 for (var rel in accTree[prop])
399 testRelation(acc, window[rel], accTree[prop][rel]);
400 break;
401 }
403 case "role":
404 isRole(acc, accTree[prop], msg);
405 break;
407 case "states":
408 case "extraStates":
409 case "absentStates":
410 case "absentExtraStates": {
411 testStates(acc, accTree["states"], accTree["extraStates"],
412 accTree["absentStates"], accTree["absentExtraStates"]);
413 break;
414 }
416 case "tagName":
417 is(accTree[prop], acc.DOMNode.tagName, msg);
418 break;
420 case "textAttrs": {
421 var prevOffset = -1;
422 for (var offset in accTree[prop]) {
423 if (prevOffset !=- 1) {
424 var attrs = accTree[prop][prevOffset];
425 testTextAttrs(acc, prevOffset, attrs, { }, prevOffset, offset, true);
426 }
427 prevOffset = offset;
428 }
430 if (prevOffset != -1) {
431 var charCount = getAccessible(acc, [nsIAccessibleText]).characterCount;
432 var attrs = accTree[prop][prevOffset];
433 testTextAttrs(acc, prevOffset, attrs, { }, prevOffset, charCount, true);
434 }
436 break;
437 }
439 default:
440 if (prop.indexOf("todo_") == 0)
441 todo(false, msg);
442 else if (prop != "children")
443 is(acc[prop], accTree[prop], msg);
444 }
445 }
447 // Test children.
448 if ("children" in accTree && accTree["children"] instanceof Array) {
449 var children = acc.children;
450 var childCount = children.length;
452 is(childCount, accTree.children.length,
453 "Different amount of expected children of " + prettyName(acc) + ".");
455 if (accTree.children.length == childCount) {
456 if (aFlags & kSkipTreeFullCheck) {
457 for (var i = 0; i < childCount; i++) {
458 var child = children.queryElementAt(i, nsIAccessible);
459 testAccessibleTree(child, accTree.children[i], aFlags);
460 }
461 return;
462 }
464 // nsIAccessible::firstChild
465 var expectedFirstChild = childCount > 0 ?
466 children.queryElementAt(0, nsIAccessible) : null;
467 var firstChild = null;
468 try { firstChild = acc.firstChild; } catch (e) {}
469 is(firstChild, expectedFirstChild,
470 "Wrong first child of " + prettyName(acc));
472 // nsIAccessible::lastChild
473 var expectedLastChild = childCount > 0 ?
474 children.queryElementAt(childCount - 1, nsIAccessible) : null;
475 var lastChild = null;
476 try { lastChild = acc.lastChild; } catch (e) {}
477 is(lastChild, expectedLastChild,
478 "Wrong last child of " + prettyName(acc));
480 for (var i = 0; i < childCount; i++) {
481 var child = children.queryElementAt(i, nsIAccessible);
483 // nsIAccessible::parent
484 var parent = null;
485 try { parent = child.parent; } catch (e) {}
486 is(parent, acc, "Wrong parent of " + prettyName(child));
488 // nsIAccessible::indexInParent
489 var indexInParent = -1;
490 try { indexInParent = child.indexInParent; } catch(e) {}
491 is(indexInParent, i,
492 "Wrong index in parent of " + prettyName(child));
494 // nsIAccessible::nextSibling
495 var expectedNextSibling = (i < childCount - 1) ?
496 children.queryElementAt(i + 1, nsIAccessible) : null;
497 var nextSibling = null;
498 try { nextSibling = child.nextSibling; } catch (e) {}
499 is(nextSibling, expectedNextSibling,
500 "Wrong next sibling of " + prettyName(child));
502 // nsIAccessible::previousSibling
503 var expectedPrevSibling = (i > 0) ?
504 children.queryElementAt(i - 1, nsIAccessible) : null;
505 var prevSibling = null;
506 try { prevSibling = child.previousSibling; } catch (e) {}
507 is(prevSibling, expectedPrevSibling,
508 "Wrong previous sibling of " + prettyName(child));
510 // Go down through subtree
511 testAccessibleTree(child, accTree.children[i], aFlags);
512 }
513 }
514 }
515 }
517 /**
518 * Return true if accessible for the given node is in cache.
519 */
520 function isAccessibleInCache(aNodeOrId)
521 {
522 var node = getNode(aNodeOrId);
523 return gAccRetrieval.getAccessibleFromCache(node) ? true : false;
524 }
526 /**
527 * Test accessible tree for defunct accessible.
528 *
529 * @param aAcc [in] the defunct accessible
530 * @param aNodeOrId [in] the DOM node identifier for the defunct accessible
531 */
532 function testDefunctAccessible(aAcc, aNodeOrId)
533 {
534 if (aNodeOrId)
535 ok(!isAccessible(aNodeOrId),
536 "Accessible for " + aNodeOrId + " wasn't properly shut down!");
538 var msg = " doesn't fail for shut down accessible " + prettyName(aNodeOrId) + "!";
540 // firstChild
541 var success = false;
542 try {
543 aAcc.firstChild;
544 } catch (e) {
545 success = (e.result == Components.results.NS_ERROR_FAILURE)
546 }
547 ok(success, "firstChild" + msg);
549 // lastChild
550 success = false;
551 try {
552 aAcc.lastChild;
553 } catch (e) {
554 success = (e.result == Components.results.NS_ERROR_FAILURE)
555 }
556 ok(success, "lastChild" + msg);
558 // childCount
559 success = false;
560 try {
561 aAcc.childCount;
562 } catch (e) {
563 success = (e.result == Components.results.NS_ERROR_FAILURE)
564 }
565 ok(success, "childCount" + msg);
567 // children
568 success = false;
569 try {
570 aAcc.children;
571 } catch (e) {
572 success = (e.result == Components.results.NS_ERROR_FAILURE)
573 }
574 ok(success, "children" + msg);
576 // nextSibling
577 success = false;
578 try {
579 aAcc.nextSibling;
580 } catch (e) {
581 success = (e.result == Components.results.NS_ERROR_FAILURE);
582 }
583 ok(success, "nextSibling" + msg);
585 // previousSibling
586 success = false;
587 try {
588 aAcc.previousSibling;
589 } catch (e) {
590 success = (e.result == Components.results.NS_ERROR_FAILURE);
591 }
592 ok(success, "previousSibling" + msg);
594 // parent
595 success = false;
596 try {
597 aAcc.parent;
598 } catch (e) {
599 success = (e.result == Components.results.NS_ERROR_FAILURE);
600 }
601 ok(success, "parent" + msg);
602 }
604 /**
605 * Convert role to human readable string.
606 */
607 function roleToString(aRole)
608 {
609 return gAccRetrieval.getStringRole(aRole);
610 }
612 /**
613 * Convert states to human readable string.
614 */
615 function statesToString(aStates, aExtraStates)
616 {
617 var list = gAccRetrieval.getStringStates(aStates, aExtraStates);
619 var str = "";
620 for (var index = 0; index < list.length - 1; index++)
621 str += list.item(index) + ", ";
623 if (list.length != 0)
624 str += list.item(index)
626 return str;
627 }
629 /**
630 * Convert event type to human readable string.
631 */
632 function eventTypeToString(aEventType)
633 {
634 return gAccRetrieval.getStringEventType(aEventType);
635 }
637 /**
638 * Convert relation type to human readable string.
639 */
640 function relationTypeToString(aRelationType)
641 {
642 return gAccRetrieval.getStringRelationType(aRelationType);
643 }
645 function getLoadContext() {
646 const Ci = Components.interfaces;
647 return window.QueryInterface(Ci.nsIInterfaceRequestor)
648 .getInterface(Ci.nsIWebNavigation)
649 .QueryInterface(Ci.nsILoadContext);
650 }
652 /**
653 * Return text from clipboard.
654 */
655 function getTextFromClipboard()
656 {
657 var clip = Components.classes["@mozilla.org/widget/clipboard;1"].
658 getService(Components.interfaces.nsIClipboard);
659 if (!clip)
660 return "";
662 var trans = Components.classes["@mozilla.org/widget/transferable;1"].
663 createInstance(Components.interfaces.nsITransferable);
664 trans.init(getLoadContext());
665 if (!trans)
666 return "";
668 trans.addDataFlavor("text/unicode");
669 clip.getData(trans, clip.kGlobalClipboard);
671 var str = new Object();
672 var strLength = new Object();
673 trans.getTransferData("text/unicode", str, strLength);
675 if (str)
676 str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
677 if (str)
678 return str.data.substring(0, strLength.value / 2);
680 return "";
681 }
683 /**
684 * Return pretty name for identifier, it may be ID, DOM node or accessible.
685 */
686 function prettyName(aIdentifier)
687 {
688 if (aIdentifier instanceof Array) {
689 var msg = "";
690 for (var idx = 0; idx < aIdentifier.length; idx++) {
691 if (msg != "")
692 msg += ", ";
694 msg += prettyName(aIdentifier[idx]);
695 }
696 return msg;
697 }
699 if (aIdentifier instanceof nsIAccessible) {
700 var acc = getAccessible(aIdentifier);
701 var msg = "[" + getNodePrettyName(acc.DOMNode);
702 try {
703 msg += ", role: " + roleToString(acc.role);
704 if (acc.name)
705 msg += ", name: '" + shortenString(acc.name) + "'";
706 } catch (e) {
707 msg += "defunct";
708 }
710 if (acc)
711 msg += ", address: " + getObjAddress(acc);
712 msg += "]";
714 return msg;
715 }
717 if (aIdentifier instanceof nsIDOMNode)
718 return "[ " + getNodePrettyName(aIdentifier) + " ]";
720 return " '" + aIdentifier + "' ";
721 }
723 /**
724 * Shorten a long string if it exceeds MAX_TRIM_LENGTH.
725 * @param aString the string to shorten.
726 * @returns the shortened string.
727 */
728 function shortenString(aString, aMaxLength)
729 {
730 if (aString.length <= MAX_TRIM_LENGTH)
731 return aString;
733 // Trim the string if its length is > MAX_TRIM_LENGTH characters.
734 var trimOffset = MAX_TRIM_LENGTH / 2;
735 return aString.substring(0, trimOffset - 1) + "..." +
736 aString.substring(aString.length - trimOffset, aString.length);
737 }
739 ////////////////////////////////////////////////////////////////////////////////
740 // General Utils
741 ////////////////////////////////////////////////////////////////////////////////
742 /**
743 * Return main chrome window (crosses chrome boundary)
744 */
745 function getMainChromeWindow(aWindow)
746 {
747 return aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
748 .getInterface(Components.interfaces.nsIWebNavigation)
749 .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
750 .rootTreeItem
751 .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
752 .getInterface(Components.interfaces.nsIDOMWindow);
753 }
755 /** Sets the test plugin(s) initially expected enabled state.
756 * It will automatically be reset to it's previous value after the test
757 * ends.
758 * @param aNewEnabledState [in] the enabled state, e.g. SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED
759 * @param aPluginName [in, optional] The name of the plugin, defaults to "Test Plug-in"
760 */
761 function setTestPluginEnabledState(aNewEnabledState, aPluginName)
762 {
763 var plugin = getTestPluginTag(aPluginName);
764 var oldEnabledState = plugin.enabledState;
765 plugin.enabledState = aNewEnabledState;
766 SimpleTest.registerCleanupFunction(function() {
767 getTestPluginTag(aPluginName).enabledState = oldEnabledState;
768 });
769 }
771 ////////////////////////////////////////////////////////////////////////////////
772 // Private
773 ////////////////////////////////////////////////////////////////////////////////
775 ////////////////////////////////////////////////////////////////////////////////
776 // Accessible general
778 function getNodePrettyName(aNode)
779 {
780 try {
781 var tag = "";
782 if (aNode.nodeType == nsIDOMNode.DOCUMENT_NODE) {
783 tag = "document";
784 } else {
785 tag = aNode.localName;
786 if (aNode.nodeType == nsIDOMNode.ELEMENT_NODE && aNode.hasAttribute("id"))
787 tag += "@id=\"" + aNode.getAttribute("id") + "\"";
788 }
790 return "'" + tag + " node', address: " + getObjAddress(aNode);
791 } catch (e) {
792 return "' no node info '";
793 }
794 }
796 function getObjAddress(aObj)
797 {
798 var exp = /native\s*@\s*(0x[a-f0-9]+)/g;
799 var match = exp.exec(aObj.toString());
800 if (match)
801 return match[1];
803 return aObj.toString();
804 }
806 function getTestPluginTag(aPluginName)
807 {
808 var ph = SpecialPowers.Cc["@mozilla.org/plugin/host;1"]
809 .getService(SpecialPowers.Ci.nsIPluginHost);
810 var tags = ph.getPluginTags();
811 var name = aPluginName || "Test Plug-in";
812 for (var tag of tags) {
813 if (tag.name == name) {
814 return tag;
815 }
816 }
818 ok(false, "Could not find plugin tag with plugin name '" + name + "'");
819 return null;
820 }