Bug 1455676 part 2. Remove nsIDOMNode usage from accessible/. r=surkov
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 29 May 2018 22:58:47 -0400
changeset 420384 1ccf1348f689b06996d1cbdb1f47eee2b85cd208
parent 420383 c38176356708244983dc39cf96d4597f5889bbc6
child 420385 7161cb18122e3f51c30a014d688a4c5fbcacaa74
push id34071
push userncsoregi@mozilla.com
push dateWed, 30 May 2018 09:25:30 +0000
treeherdermozilla-central@5866d6685849 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssurkov
bugs1455676
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1455676 part 2. Remove nsIDOMNode usage from accessible/. r=surkov
accessible/base/AccEvent.cpp
accessible/base/nsAccessibilityService.cpp
accessible/base/nsAccessibilityService.h
accessible/interfaces/nsIAccessibilityService.idl
accessible/interfaces/nsIAccessible.idl
accessible/interfaces/nsIAccessibleEvent.idl
accessible/ipc/DocAccessibleParent.cpp
accessible/tests/mochitest/.eslintrc.js
accessible/tests/mochitest/common.js
accessible/tests/mochitest/events.js
accessible/tests/mochitest/events/test_focus_name.html
accessible/xpcom/xpcAccessibilityService.cpp
accessible/xpcom/xpcAccessible.cpp
accessible/xpcom/xpcAccessible.h
accessible/xul/XULListboxAccessible.cpp
accessible/xul/XULTabAccessible.cpp
accessible/xul/XULTreeAccessible.cpp
dom/base/nsFocusManager.cpp
dom/interfaces/xul/nsIDOMXULMenuListElement.idl
dom/interfaces/xul/nsIDOMXULRelatedElement.idl
--- a/accessible/base/AccEvent.cpp
+++ b/accessible/base/AccEvent.cpp
@@ -194,80 +194,79 @@ AccVCChangeEvent::
 }
 
 already_AddRefed<nsIAccessibleEvent>
 a11y::MakeXPCEvent(AccEvent* aEvent)
 {
   DocAccessible* doc = aEvent->Document();
   Accessible* acc = aEvent->GetAccessible();
   nsINode* node = acc->GetNode();
-  nsIDOMNode* domNode = node ? node->AsDOMNode() : nullptr;
   bool fromUser = aEvent->IsFromUserInput();
   uint32_t type = aEvent->GetEventType();
   uint32_t eventGroup = aEvent->GetEventGroups();
   nsCOMPtr<nsIAccessibleEvent> xpEvent;
 
   if (eventGroup & (1 << AccEvent::eStateChangeEvent)) {
     AccStateChangeEvent* sc = downcast_accEvent(aEvent);
     bool extra = false;
     uint32_t state = nsAccUtils::To32States(sc->GetState(), &extra);
     xpEvent = new xpcAccStateChangeEvent(type, ToXPC(acc), ToXPCDocument(doc),
-                                         domNode, fromUser,
+                                         node, fromUser,
                                          state, extra, sc->IsStateEnabled());
     return xpEvent.forget();
   }
 
   if (eventGroup & (1 << AccEvent::eTextChangeEvent)) {
     AccTextChangeEvent* tc = downcast_accEvent(aEvent);
     nsString text;
     tc->GetModifiedText(text);
     xpEvent = new xpcAccTextChangeEvent(type, ToXPC(acc), ToXPCDocument(doc),
-                                        domNode, fromUser,
+                                        node, fromUser,
                                         tc->GetStartOffset(), tc->GetLength(),
                                         tc->IsTextInserted(), text);
     return xpEvent.forget();
   }
 
   if (eventGroup & (1 << AccEvent::eHideEvent)) {
     AccHideEvent* hideEvent = downcast_accEvent(aEvent);
     xpEvent = new xpcAccHideEvent(type, ToXPC(acc), ToXPCDocument(doc),
-                                  domNode, fromUser,
+                                  node, fromUser,
                                   ToXPC(hideEvent->TargetParent()),
                                   ToXPC(hideEvent->TargetNextSibling()),
                                   ToXPC(hideEvent->TargetPrevSibling()));
     return xpEvent.forget();
   }
 
   if (eventGroup & (1 << AccEvent::eCaretMoveEvent)) {
     AccCaretMoveEvent* cm = downcast_accEvent(aEvent);
     xpEvent = new xpcAccCaretMoveEvent(type, ToXPC(acc), ToXPCDocument(doc),
-                                       domNode, fromUser,
+                                       node, fromUser,
                                        cm->GetCaretOffset());
     return xpEvent.forget();
   }
 
   if (eventGroup & (1 << AccEvent::eVirtualCursorChangeEvent)) {
     AccVCChangeEvent* vcc = downcast_accEvent(aEvent);
     xpEvent = new xpcAccVirtualCursorChangeEvent(type,
                                                  ToXPC(acc), ToXPCDocument(doc),
-                                                 domNode, fromUser,
+                                                 node, fromUser,
                                                  ToXPC(vcc->OldAccessible()),
                                                  vcc->OldStartOffset(),
                                                  vcc->OldEndOffset(),
                                                  vcc->Reason());
     return xpEvent.forget();
   }
 
   if (eventGroup & (1 << AccEvent::eObjectAttrChangedEvent)) {
     AccObjectAttrChangedEvent* oac = downcast_accEvent(aEvent);
     nsString attribute;
     oac->GetAttribute()->ToString(attribute);
     xpEvent = new xpcAccObjectAttributeChangedEvent(type,
                                                     ToXPC(acc),
-                                                    ToXPCDocument(doc), domNode,
+                                                    ToXPCDocument(doc), node,
                                                     fromUser,
                                                     attribute);
     return xpEvent.forget();
   }
 
-  xpEvent = new xpcAccEvent(type, ToXPC(acc), ToXPCDocument(doc), domNode, fromUser);
+  xpEvent = new xpcAccEvent(type, ToXPC(acc), ToXPCDocument(doc), node, fromUser);
   return xpEvent.forget();
   }
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -1656,27 +1656,26 @@ nsAccessibilityService::RemoveNativeRoot
   ApplicationAccessible* applicationAcc = ApplicationAcc();
 
   if (applicationAcc)
     applicationAcc->RemoveChild(aAccessible);
 #endif
 }
 
 bool
-nsAccessibilityService::HasAccessible(nsIDOMNode* aDOMNode)
+nsAccessibilityService::HasAccessible(nsINode* aDOMNode)
 {
-  nsCOMPtr<nsINode> node(do_QueryInterface(aDOMNode));
-  if (!node)
+  if (!aDOMNode)
     return false;
 
-  DocAccessible* document = GetDocAccessible(node->OwnerDoc());
+  DocAccessible* document = GetDocAccessible(aDOMNode->OwnerDoc());
   if (!document)
     return false;
 
-  return document->HasAccessible(node);
+  return document->HasAccessible(aDOMNode);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessibilityService private (DON'T put methods here)
 
 void
 nsAccessibilityService::SetConsumers(uint32_t aConsumers, bool aNotify) {
   if (gConsumers & aConsumers) {
--- a/accessible/base/nsAccessibilityService.h
+++ b/accessible/base/nsAccessibilityService.h
@@ -116,17 +116,17 @@ public:
 
   /**
    * Adds/remove ATK root accessible for gtk+ native window to/from children
    * of the application accessible.
    */
   Accessible* AddNativeRootAccessible(void* aAtkAccessible);
   void RemoveNativeRootAccessible(Accessible* aRootAccessible);
 
-  bool HasAccessible(nsIDOMNode* aDOMNode);
+  bool HasAccessible(nsINode* aDOMNode);
 
   /**
    * Get a string equivalent for an accessible role value.
    */
   void GetStringRole(uint32_t aRole, nsAString& aString);
 
   /**
    * Get a string equivalent for an accessible state/extra state.
--- a/accessible/interfaces/nsIAccessibilityService.idl
+++ b/accessible/interfaces/nsIAccessibilityService.idl
@@ -1,21 +1,22 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-interface nsIDOMNode;
 interface nsIAccessible;
 interface nsIWeakReference;
 interface nsIPresShell;
 interface nsIAccessiblePivot;
 
+webidl Node;
+
 /**
  * An interface for in-process accessibility clients wishing to get an
  * nsIAccessible for a given DOM node.  More documentation at:
  *   http://www.mozilla.org/projects/ui/accessibility
  */
 [scriptable, builtinclass, uuid(2188e3a0-c88e-11e7-8f1a-0800200c9a66)]
 interface nsIAccessibilityService : nsISupports
 {
@@ -26,17 +27,17 @@ interface nsIAccessibilityService : nsIS
 
   /**
    * Return an nsIAccessible for a DOM node in pres shell 0.
    * Create a new accessible of the appropriate type if necessary,
    * or use one from the accessibility cache if it already exists.
    * @param aNode The DOM node to get an accessible for.
    * @return The nsIAccessible for the given DOM node.
    */
-  nsIAccessible getAccessibleFor(in nsIDOMNode aNode);
+  nsIAccessible getAccessibleFor(in Node aNode);
 
    /**
     * Returns accessible role as a string.
     *
     * @param aRole - the accessible role constants.
     */
   AString getStringRole(in unsigned long aRole);
 
@@ -68,17 +69,17 @@ interface nsIAccessibilityService : nsIS
   /**
    * Return an accessible for the given DOM node from the cache.
    * @note  the method is intended for testing purposes
    *
    * @param aNode  [in] the DOM node to get an accessible for
    *
    * @return       cached accessible for the given DOM node if any
    */
-  nsIAccessible getAccessibleFromCache(in nsIDOMNode aNode);
+  nsIAccessible getAccessibleFromCache(in Node aNode);
 
   /**
    * Create a new pivot for tracking a position and traversing a subtree.
    *
    * @param aRoot [in] the accessible root for the pivot
    * @return a new pivot
    */
   nsIAccessiblePivot createAccessiblePivot(in nsIAccessible aRoot);
--- a/accessible/interfaces/nsIAccessible.idl
+++ b/accessible/interfaces/nsIAccessible.idl
@@ -2,20 +2,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "nsIArray.idl"
 
 interface nsIPersistentProperties;
-interface nsIDOMNode;
 interface nsIAccessibleDocument;
 interface nsIAccessibleRelation;
 
+webidl Node;
+
 %{C++
 namespace mozilla {
 namespace a11y {
 class Accessible;
 }
 }
 %}
 
@@ -71,17 +72,17 @@ interface nsIAccessible : nsISupports
    * The 0-based index of this accessible in its parent's list of children,
    * or -1 if this accessible does not have a parent.
    */
   readonly attribute long indexInParent;
 
   /**
    * The DOM node this nsIAccessible is associated with.
    */
-  readonly attribute nsIDOMNode DOMNode;
+  readonly attribute Node DOMNode;
 
   /**
     * For remote accessibles the id of the related DOM node.
     */
   readonly attribute DOMString id;
 
   /**
    * The document accessible that this access node resides in.
--- a/accessible/interfaces/nsIAccessibleEvent.idl
+++ b/accessible/interfaces/nsIAccessibleEvent.idl
@@ -2,17 +2,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIAccessible;
 interface nsIAccessibleDocument;
-interface nsIDOMNode;
+
+webidl Node;
 
 %{C++
 #define NS_ACCESSIBLE_EVENT_TOPIC "accessible-event"
 %}
 
 /**
  * An interface for accessibility events listened to
  * by in-process accessibility clients, which can be used
@@ -437,19 +438,19 @@ interface nsIAccessibleEvent : nsISuppor
   /**
    * The nsIAccessibleDocument that the event target nsIAccessible
    * resides in. This can be used to get the DOM window,
    * the DOM document and the window handler, among other things.
    */
   readonly attribute nsIAccessibleDocument accessibleDocument;
 
   /**
-   * The nsIDOMNode associated with the event
+   * The Node associated with the event
    * May return null if accessible for event has been shut down
    */
-  readonly attribute nsIDOMNode DOMNode;
+  readonly attribute Node DOMNode;
 
   /**
    * Returns true if the event was caused by explicit user input,
    * as opposed to purely originating from a timer or mouse movement
    */
   readonly attribute boolean isFromUserInput;
 };
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -89,17 +89,17 @@ DocAccessibleParent::RecvShowEvent(const
 
   if (!nsCoreUtils::AccEventObserversExist()) {
     return IPC_OK();
   }
 
   uint32_t type = nsIAccessibleEvent::EVENT_SHOW;
   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target);
   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
-  nsIDOMNode* node = nullptr;
+  nsINode* node = nullptr;
   RefPtr<xpcAccEvent> event = new xpcAccEvent(type, xpcAcc, doc, node,
                                               aFromUser);
   nsCoreUtils::DispatchAccEvent(Move(event));
 
   return IPC_OK();
 }
 
 uint32_t
@@ -180,17 +180,17 @@ DocAccessibleParent::RecvHideEvent(const
     uint32_t type = nsIAccessibleEvent::EVENT_HIDE;
     xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(root);
     xpcAccessibleGeneric* xpcParent = GetXPCAccessible(parent);
     ProxyAccessible* next = root->NextSibling();
     xpcAccessibleGeneric* xpcNext = next ? GetXPCAccessible(next) : nullptr;
     ProxyAccessible* prev = root->PrevSibling();
     xpcAccessibleGeneric* xpcPrev = prev ? GetXPCAccessible(prev) : nullptr;
     xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
-    nsIDOMNode* node = nullptr;
+    nsINode* node = nullptr;
     event = new xpcAccHideEvent(type, xpcAcc, doc, node, aFromUser, xpcParent,
                                 xpcNext, xpcPrev);
   }
 
   parent->RemoveChild(root);
   root->Shutdown();
 
   MOZ_ASSERT(CheckDocTree());
@@ -218,17 +218,17 @@ DocAccessibleParent::RecvEvent(const uin
   ProxyEvent(proxy, aEventType);
 
   if (!nsCoreUtils::AccEventObserversExist()) {
     return IPC_OK();
   }
 
   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(proxy);
   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
-  nsIDOMNode* node = nullptr;
+  nsINode* node = nullptr;
   bool fromUser = true; // XXX fix me
   RefPtr<xpcAccEvent> event = new xpcAccEvent(aEventType, xpcAcc, doc, node,
                                               fromUser);
   nsCoreUtils::DispatchAccEvent(Move(event));
 
   return IPC_OK();
 }
 
@@ -254,17 +254,17 @@ DocAccessibleParent::RecvStateChangeEven
   }
 
   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target);
   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
   uint32_t type = nsIAccessibleEvent::EVENT_STATE_CHANGE;
   bool extra;
   uint32_t state = nsAccUtils::To32States(aState, &extra);
   bool fromUser = true; // XXX fix this
-  nsIDOMNode* node = nullptr; // XXX can we do better?
+  nsINode* node = nullptr; // XXX can we do better?
   RefPtr<xpcAccStateChangeEvent> event =
     new xpcAccStateChangeEvent(type, xpcAcc, doc, node, fromUser, state, extra,
                                aEnabled);
   nsCoreUtils::DispatchAccEvent(Move(event));
 
   return IPC_OK();
 }
 
@@ -292,17 +292,17 @@ DocAccessibleParent::RecvCaretMoveEvent(
 #endif
 
   if (!nsCoreUtils::AccEventObserversExist()) {
     return IPC_OK();
   }
 
   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(proxy);
   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
-  nsIDOMNode* node = nullptr;
+  nsINode* node = nullptr;
   bool fromUser = true; // XXX fix me
   uint32_t type = nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED;
   RefPtr<xpcAccCaretMoveEvent> event =
     new xpcAccCaretMoveEvent(type, xpcAcc, doc, node, fromUser, aOffset);
   nsCoreUtils::DispatchAccEvent(Move(event));
 
   return IPC_OK();
 }
@@ -330,17 +330,17 @@ DocAccessibleParent::RecvTextChangeEvent
   if (!nsCoreUtils::AccEventObserversExist()) {
     return IPC_OK();
   }
 
   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target);
   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
   uint32_t type = aIsInsert ? nsIAccessibleEvent::EVENT_TEXT_INSERTED :
                               nsIAccessibleEvent::EVENT_TEXT_REMOVED;
-  nsIDOMNode* node = nullptr;
+  nsINode* node = nullptr;
   RefPtr<xpcAccTextChangeEvent> event =
     new xpcAccTextChangeEvent(type, xpcAcc, doc, node, aFromUser, aStart, aLen,
                               aIsInsert, aStr);
   nsCoreUtils::DispatchAccEvent(Move(event));
 
   return IPC_OK();
 }
 
@@ -740,17 +740,17 @@ DocAccessibleParent::RecvFocusEvent(cons
   ProxyFocusEvent(proxy, aCaretRect);
 
   if (!nsCoreUtils::AccEventObserversExist()) {
     return IPC_OK();
   }
 
   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(proxy);
   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
-  nsIDOMNode* node = nullptr;
+  nsINode* node = nullptr;
   bool fromUser = true; // XXX fix me
   RefPtr<xpcAccEvent> event = new xpcAccEvent(nsIAccessibleEvent::EVENT_FOCUS,
                                               xpcAcc, doc, node, fromUser);
   nsCoreUtils::DispatchAccEvent(Move(event));
 
   return IPC_OK();
 }
 
--- a/accessible/tests/mochitest/.eslintrc.js
+++ b/accessible/tests/mochitest/.eslintrc.js
@@ -1,16 +1,14 @@
 "use strict";
 
 module.exports = {
   "extends": [
     "plugin:mozilla/mochitest-test"
   ],
   "rules": {
-    "mozilla/reject-importGlobalProperties": "error",
-
     // XXX These are rules that are enabled in the recommended configuration, but
     // disabled here due to failures when initially implemented. They should be
     // removed (and hence enabled) at some stage.
     "no-nested-ternary": "off",
     "no-undef": "off",
   }
 };
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -39,21 +39,38 @@ const nsIAccessiblePivot = Ci.nsIAccessi
 const nsIAccessibleSelectable = Ci.nsIAccessibleSelectable;
 const nsIAccessibleTable = Ci.nsIAccessibleTable;
 const nsIAccessibleTableCell = Ci.nsIAccessibleTableCell;
 const nsIAccessibleTraversalRule = Ci.nsIAccessibleTraversalRule;
 const nsIAccessibleValue = Ci.nsIAccessibleValue;
 
 const nsIObserverService = Ci.nsIObserverService;
 
-const nsIDOMNode = Ci.nsIDOMNode;
 const nsIDOMWindow = Ci.nsIDOMWindow;
 
 const nsIPropertyElement = Ci.nsIPropertyElement;
 
+// Testing "'Node' in this" doesn't do the right thing because there are cases
+// when our "this" is not the global even though we're at toplevel.  In those
+// cases, the import could fail because our global is a Window and we in fact
+// have a Node all along.
+//
+// We could get the global via the (function() { return this; })() trick, but
+// that might break any time if people switch us to strict mode.  So let's just
+// test the thing we care about directly: does bareword Node exist?
+let needToImportNode = false;
+try {
+    Node;
+} catch (e) {
+    needToImportNode = true;
+}
+if (needToImportNode) {
+    Cu.importGlobalProperties(["Node"]);
+}
+
 // //////////////////////////////////////////////////////////////////////////////
 // OS detect
 
 const MAC = (navigator.platform.includes("Mac"));
 const LINUX = (navigator.platform.includes("Linux"));
 const SOLARIS = (navigator.platform.includes("SunOS"));
 const WIN = (navigator.platform.includes("Win"));
 
@@ -203,17 +220,17 @@ function isWithin(aExpected, aGot, aWith
 
 /**
  * Return the DOM node by identifier (may be accessible, DOM node or ID).
  */
 function getNode(aAccOrNodeOrID, aDocument) {
   if (!aAccOrNodeOrID)
     return null;
 
-  if (aAccOrNodeOrID instanceof nsIDOMNode)
+  if (Node.isInstance(aAccOrNodeOrID))
     return aAccOrNodeOrID;
 
   if (aAccOrNodeOrID instanceof nsIAccessible)
     return aAccOrNodeOrID.DOMNode;
 
   var node = (aDocument || document).getElementById(aAccOrNodeOrID);
   if (!node) {
     ok(false, "Can't get DOM element for " + aAccOrNodeOrID);
@@ -251,17 +268,17 @@ function getAccessible(aAccOrElmOrID, aI
   if (!aAccOrElmOrID)
     return null;
 
   var elm = null;
 
   if (aAccOrElmOrID instanceof nsIAccessible) {
     try { elm = aAccOrElmOrID.DOMNode; } catch (e) { }
 
-  } else if (aAccOrElmOrID instanceof nsIDOMNode) {
+  } else if (Node.isInstance(aAccOrElmOrID)) {
     elm = aAccOrElmOrID;
 
   } else {
     elm = document.getElementById(aAccOrElmOrID);
     if (!elm) {
       ok(false, "Can't get DOM element for " + aAccOrElmOrID);
       return null;
     }
@@ -786,17 +803,17 @@ function prettyName(aIdentifier) {
 
     if (acc)
       msg += ", address: " + getObjAddress(acc);
     msg += "]";
 
     return msg;
   }
 
-  if (aIdentifier instanceof nsIDOMNode)
+  if (Node.isInstance(aIdentifier))
     return "[ " + getNodePrettyName(aIdentifier) + " ]";
 
   if (aIdentifier && typeof aIdentifier === "object" ) {
     var treeObj = normalizeAccTreeObj(aIdentifier);
     if ("role" in treeObj) {
       function stringifyTree(aObj) {
         var text = roleToString(aObj.role) + ": [ ";
         if ("children" in aObj) {
@@ -868,21 +885,21 @@ function setTestPluginEnabledState(aNewE
 // //////////////////////////////////////////////////////////////////////////////
 
 // //////////////////////////////////////////////////////////////////////////////
 // Accessible general
 
 function getNodePrettyName(aNode) {
   try {
     var tag = "";
-    if (aNode.nodeType == nsIDOMNode.DOCUMENT_NODE) {
+    if (aNode.nodeType == Node.DOCUMENT_NODE) {
       tag = "document";
     } else {
       tag = aNode.localName;
-      if (aNode.nodeType == nsIDOMNode.ELEMENT_NODE && aNode.hasAttribute("id"))
+      if (aNode.nodeType == Node.ELEMENT_NODE && aNode.hasAttribute("id"))
         tag += "@id=\"" + aNode.getAttribute("id") + "\"";
     }
 
     return "'" + tag + " node', address: " + getObjAddress(aNode);
   } catch (e) {
     return "' no node info '";
   }
 }
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -89,17 +89,17 @@ function waitForEvent(aEventType, aTarge
       if (typeof aTargetOrFunc == "function")
         target = aTargetOrFunc.call();
 
       if (target) {
         if (target instanceof nsIAccessible &&
             target != aEvent.accessible)
           return;
 
-        if (target instanceof nsIDOMNode &&
+        if (Node.isInstance(target) &&
             target != aEvent.DOMNode)
           return;
       }
 
       unregisterA11yEventListener(aEventType, this);
 
       window.setTimeout(
         function() {
--- a/accessible/tests/mochitest/events/test_focus_name.html
+++ b/accessible/tests/mochitest/events/test_focus_name.html
@@ -28,31 +28,31 @@
         is(target.description, aDescription,
            "Wrong description for " + prettyName(target));
       };
     }
 
     var gFocusHandler = {
       handleEvent: function gFocusHandler_handleEvent(aEvent) {
         var elm = aEvent.target;
-        if (elm.nodeType != nsIDOMNode.ELEMENT_NODE)
+        if (elm.nodeType != Node.ELEMENT_NODE)
           return;
 
         gTooltipElm.style.display = "block";
 
         elm.setAttribute("aria-describedby", "tooltip");
       }
     };
 
     var gBlurHandler = {
       handleEvent: function gBlurHandler_handleEvent(aEvent) {
         gTooltipElm.style.display = "none";
 
         var elm = aEvent.target;
-        if (elm.nodeType == nsIDOMNode.ELEMENT_NODE)
+        if (elm.nodeType == Node.ELEMENT_NODE)
           elm.removeAttribute("aria-describedby");
       }
     };
 
     /**
      * Do tests.
      */
 
--- a/accessible/xpcom/xpcAccessibilityService.cpp
+++ b/accessible/xpcom/xpcAccessibilityService.cpp
@@ -103,38 +103,33 @@ xpcAccessibilityService::GetApplicationA
 {
   NS_ENSURE_ARG_POINTER(aAccessibleApplication);
 
   NS_IF_ADDREF(*aAccessibleApplication = XPCApplicationAcc());
   return NS_OK;
 }
 
 NS_IMETHODIMP
-xpcAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
+xpcAccessibilityService::GetAccessibleFor(nsINode *aNode,
                                           nsIAccessible **aAccessible)
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
   *aAccessible = nullptr;
   if (!aNode) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
-  if (!node) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
   nsAccessibilityService* accService = GetAccService();
   if (!accService) {
     return NS_ERROR_SERVICE_NOT_AVAILABLE;
   }
 
-  DocAccessible* document = accService->GetDocAccessible(node->OwnerDoc());
+  DocAccessible* document = accService->GetDocAccessible(aNode->OwnerDoc());
   if (document) {
-    NS_IF_ADDREF(*aAccessible = ToXPC(document->GetAccessible(node)));
+    NS_IF_ADDREF(*aAccessible = ToXPC(document->GetAccessible(aNode)));
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibilityService::GetStringRole(uint32_t aRole, nsAString& aString)
 {
@@ -182,44 +177,39 @@ xpcAccessibilityService::GetStringRelati
     return NS_ERROR_SERVICE_NOT_AVAILABLE;
   }
 
   accService->GetStringRelationType(aRelationType, aString);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-xpcAccessibilityService::GetAccessibleFromCache(nsIDOMNode* aNode,
+xpcAccessibilityService::GetAccessibleFromCache(nsINode* aNode,
                                                 nsIAccessible** aAccessible)
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
   *aAccessible = nullptr;
   if (!aNode) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
-  if (!node) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
   nsAccessibilityService* accService = GetAccService();
   if (!accService) {
     return NS_ERROR_SERVICE_NOT_AVAILABLE;
   }
 
   // Search for an accessible in each of our per document accessible object
   // caches. If we don't find it, and the given node is itself a document, check
   // our cache of document accessibles (document cache). Note usually shutdown
   // document accessibles are not stored in the document cache, however an
   // "unofficially" shutdown document (i.e. not from DocManager) can still
   // exist in the document cache.
-  Accessible* accessible = accService->FindAccessibleInCache(node);
+  Accessible* accessible = accService->FindAccessibleInCache(aNode);
   if (!accessible) {
-    nsCOMPtr<nsIDocument> document(do_QueryInterface(node));
+    nsCOMPtr<nsIDocument> document(do_QueryInterface(aNode));
     if (document) {
       accessible = mozilla::a11y::GetExistingDocAccessible(document);
     }
   }
 
   NS_IF_ADDREF(*aAccessible = ToXPC(accessible));
   return NS_OK;
 }
--- a/accessible/xpcom/xpcAccessible.cpp
+++ b/accessible/xpcom/xpcAccessible.cpp
@@ -172,27 +172,26 @@ xpcAccessible::GetIndexInParent(int32_t*
   } else if (IntlGeneric().IsProxy()) {
     *aIndexInParent = IntlGeneric().AsProxy()->IndexInParent();
   }
 
   return *aIndexInParent != -1 ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-xpcAccessible::GetDOMNode(nsIDOMNode** aDOMNode)
+xpcAccessible::GetDOMNode(nsINode** aDOMNode)
 {
   NS_ENSURE_ARG_POINTER(aDOMNode);
   *aDOMNode = nullptr;
 
   if (!Intl())
     return NS_ERROR_FAILURE;
 
-  nsINode* node = Intl()->GetNode();
-  if (node)
-    CallQueryInterface(node, aDOMNode);
+  nsCOMPtr<nsINode> node = Intl()->GetNode();
+  node.forget(aDOMNode);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessible::GetId(nsAString& aID)
 {
   ProxyAccessible* proxy = IntlGeneric().AsProxy();
--- a/accessible/xpcom/xpcAccessible.h
+++ b/accessible/xpcom/xpcAccessible.h
@@ -32,17 +32,17 @@ public:
   NS_IMETHOD GetFirstChild(nsIAccessible** aFirstChild) final;
   NS_IMETHOD GetLastChild(nsIAccessible** aLastChild) final;
   NS_IMETHOD GetChildCount(int32_t* aChildCount) final;
   NS_IMETHOD GetChildAt(int32_t aChildIndex, nsIAccessible** aChild)
     final;
   NS_IMETHOD GetChildren(nsIArray** aChildren) final;
   NS_IMETHOD GetIndexInParent(int32_t* aIndexInParent) final;
 
-  NS_IMETHOD GetDOMNode(nsIDOMNode** aDOMNode) final;
+  NS_IMETHOD GetDOMNode(nsINode** aDOMNode) final;
   NS_IMETHOD GetId(nsAString& aID) final;
   NS_IMETHOD GetDocument(nsIAccessibleDocument** aDocument) final;
   NS_IMETHOD GetRootDocument(nsIAccessibleDocument** aRootDocument)
     final;
 
   NS_IMETHOD GetRole(uint32_t* aRole) final;
   NS_IMETHOD GetState(uint32_t* aState, uint32_t* aExtraState)
     final;
--- a/accessible/xul/XULListboxAccessible.cpp
+++ b/accessible/xul/XULListboxAccessible.cpp
@@ -496,25 +496,21 @@ XULListboxAccessible::ContainerWidget() 
   if (IsAutoCompletePopup()) {
     // This works for XUL autocompletes. It doesn't work for HTML forms
     // autocomplete because of potential crossprocess calls (when autocomplete
     // lives in content process while popup lives in chrome process). If that's
     // a problem then rethink Widgets interface.
     nsCOMPtr<nsIDOMXULMenuListElement> menuListElm =
       do_QueryInterface(mContent->GetParent());
     if (menuListElm) {
-      nsCOMPtr<nsIDOMNode> inputElm;
+      RefPtr<mozilla::dom::Element> inputElm;
       menuListElm->GetInputField(getter_AddRefs(inputElm));
       if (inputElm) {
-        nsCOMPtr<nsINode> inputNode = do_QueryInterface(inputElm);
-        if (inputNode) {
-          Accessible* input =
-            mDoc->GetAccessible(inputNode);
+          Accessible* input = mDoc->GetAccessible(inputElm);
           return input ? input->ContainerWidget() : nullptr;
-        }
       }
     }
   }
   return nullptr;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULListitemAccessible
--- a/accessible/xul/XULTabAccessible.cpp
+++ b/accessible/xul/XULTabAccessible.cpp
@@ -109,24 +109,22 @@ XULTabAccessible::RelationByType(Relatio
     return rel;
 
   // Expose 'LABEL_FOR' relation on tab accessible for tabpanel accessible.
   nsCOMPtr<nsIDOMXULRelatedElement> tabsElm =
     do_QueryInterface(mContent->GetParent());
   if (!tabsElm)
     return rel;
 
-  nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(GetNode()));
-  nsCOMPtr<nsIDOMNode> tabpanelNode;
-  tabsElm->GetRelatedElement(domNode, getter_AddRefs(tabpanelNode));
-  if (!tabpanelNode)
+  RefPtr<mozilla::dom::Element> tabpanelElement;
+  tabsElm->GetRelatedElement(GetNode(), getter_AddRefs(tabpanelElement));
+  if (!tabpanelElement)
     return rel;
 
-  nsCOMPtr<nsIContent> tabpanelContent(do_QueryInterface(tabpanelNode));
-  rel.AppendTarget(mDoc, tabpanelContent);
+  rel.AppendTarget(mDoc, tabpanelElement);
   return rel;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTabsAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -196,18 +194,16 @@ XULTabpanelAccessible::RelationByType(Re
     return rel;
 
   // Expose 'LABELLED_BY' relation on tabpanel accessible for tab accessible.
   nsCOMPtr<nsIDOMXULRelatedElement> tabpanelsElm =
     do_QueryInterface(mContent->GetParent());
   if (!tabpanelsElm)
     return rel;
 
-  nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(GetNode()));
-  nsCOMPtr<nsIDOMNode> tabNode;
-  tabpanelsElm->GetRelatedElement(domNode, getter_AddRefs(tabNode));
-  if (!tabNode)
+  RefPtr<mozilla::dom::Element> tabElement;
+  tabpanelsElm->GetRelatedElement(GetNode(), getter_AddRefs(tabElement));
+  if (!tabElement)
     return rel;
 
-  nsCOMPtr<nsIContent> tabContent(do_QueryInterface(tabNode));
-  rel.AppendTarget(mDoc, tabContent);
+  rel.AppendTarget(mDoc, tabElement);
   return rel;
 }
--- a/accessible/xul/XULTreeAccessible.cpp
+++ b/accessible/xul/XULTreeAccessible.cpp
@@ -492,25 +492,21 @@ XULTreeAccessible::ContainerWidget() con
   if (IsAutoCompletePopup()) {
     // This works for XUL autocompletes. It doesn't work for HTML forms
     // autocomplete because of potential crossprocess calls (when autocomplete
     // lives in content process while popup lives in chrome process). If that's
     // a problem then rethink Widgets interface.
     nsCOMPtr<nsIDOMXULMenuListElement> menuListElm =
       do_QueryInterface(mContent->GetParent());
     if (menuListElm) {
-      nsCOMPtr<nsIDOMNode> inputElm;
+      RefPtr<mozilla::dom::Element> inputElm;
       menuListElm->GetInputField(getter_AddRefs(inputElm));
       if (inputElm) {
-        nsCOMPtr<nsINode> inputNode = do_QueryInterface(inputElm);
-        if (inputNode) {
-          Accessible* input =
-            mDoc->GetAccessible(inputNode);
-          return input ? input->ContainerWidget() : nullptr;
-        }
+        Accessible* input = mDoc->GetAccessible(inputElm);
+        return input ? input->ContainerWidget() : nullptr;
       }
     }
   }
   return nullptr;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeAccessible: public implementation
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -363,45 +363,40 @@ nsFocusManager::GetRedirectedFocus(nsICo
           numberControlFrame->GetAnonTextControl();
         return textControl;
       }
     }
   }
 
 #ifdef MOZ_XUL
   if (aContent->IsXULElement()) {
-    nsCOMPtr<nsIDOMNode> inputField;
-
     if (aContent->IsXULElement(nsGkAtoms::textbox)) {
       return aContent->OwnerDoc()->
         GetAnonymousElementByAttribute(aContent, nsGkAtoms::anonid, NS_LITERAL_STRING("input"));
     }
     else {
       nsCOMPtr<nsIDOMXULMenuListElement> menulist = do_QueryInterface(aContent);
       if (menulist) {
+        RefPtr<Element> inputField;
         menulist->GetInputField(getter_AddRefs(inputField));
+        return inputField;
       }
       else if (aContent->IsXULElement(nsGkAtoms::scale)) {
         nsCOMPtr<nsIDocument> doc = aContent->GetComposedDoc();
         if (!doc)
           return nullptr;
 
         nsINodeList* children = doc->BindingManager()->GetAnonymousNodesFor(aContent);
         if (children) {
           nsIContent* child = children->Item(0);
           if (child && child->IsXULElement(nsGkAtoms::slider))
             return child->AsElement();
         }
       }
     }
-
-    if (inputField) {
-      nsCOMPtr<Element> retval = do_QueryInterface(inputField);
-      return retval;
-    }
   }
 #endif
 
   return nullptr;
 }
 
 // static
 InputContextAction::Cause
--- a/dom/interfaces/xul/nsIDOMXULMenuListElement.idl
+++ b/dom/interfaces/xul/nsIDOMXULMenuListElement.idl
@@ -1,23 +1,24 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMXULSelectCntrlEl.idl"
-interface nsIDOMNode;
+
+webidl Element;
 
 [scriptable, uuid(36c16a17-c0e9-4b35-951b-81a147314ef1)]
 interface nsIDOMXULMenuListElement : nsIDOMXULSelectControlElement {
   attribute boolean editable;
   attribute boolean open;
   
   // label of selected option or value of textfield for editable menu lists
   readonly attribute DOMString label;
 
   attribute DOMString crop;
   attribute DOMString image;
   
   // For editable menu lists only.
-  readonly attribute nsIDOMNode inputField;
+  readonly attribute Element inputField;
 };
 
--- a/dom/interfaces/xul/nsIDOMXULRelatedElement.idl
+++ b/dom/interfaces/xul/nsIDOMXULRelatedElement.idl
@@ -1,18 +1,21 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "domstubs.idl"
 
+webidl Element;
+webidl Node;
+
 [scriptable, uuid(9fbac05a-fb27-470d-8e5f-028b2dc54ad0)]
 interface nsIDOMXULRelatedElement : nsISupports
 {
   /**
    * Retrun an element associated with the given element. It's implemented
    * by container elements having relation between their items. For example,
    * this interface is implemented by XUL tabs and XUL tabpanels elements
    * and used to get XUL tab element by linked tab panel and vice versa.
    */
-  nsIDOMNode getRelatedElement(in nsIDOMNode aElement);
+  Element getRelatedElement(in Node aElement);
 };