Backed out 19 changesets (bug 1434399) for build bustages on nsXULPopupManager.cpp on a CLOSED TREE
authorCosmin Sabou <csabou@mozilla.com>
Wed, 31 Jan 2018 22:45:26 +0200
changeset 401912 76bf3def2b51dae62623a6815eb4e663abb53797
parent 401911 0b7aaf6d8b4ae04286d89bf39b330239778311c8
child 401913 039178c19726f434acf217b85bdf049f3fe45962
push id33358
push usercsabou@mozilla.com
push dateWed, 31 Jan 2018 23:15:12 +0000
treeherdermozilla-central@17ade9f88b6e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1434399
milestone60.0a1
backs out499f6dffd9cb27f7c5101e200b53396acbdc8289
01829061241509e6409d8aaf51968cc5f887fee5
f4c3179f8e5953fb42b08bfc556db6da6e85ff19
f3ce2826b8579e6829b6c50000357140a971120b
6d2391af01dde230f8f20459c0ac1cbd355f0936
dc98ed8c609a646ed6d4eeb81a264ea8405e6596
8eaa395d62002c85d0689b982a709a99bea69711
19b18f4a53be0bc54c6a7d75cc8868bf98919aaa
8ff378a6e96a8f0db590d790b24fea768566fdc2
60fe73be1a268b1f62cbab36cead243f5b416976
faefb2751fdc9e301080f18a8d29b0c69fb85c67
55cdf8b3a9597d431836713e82290fd67e78433c
b578cc8efb925005b2e34785f0609a42c2cf9110
54cc4cb2fca1c3603e86686926c098b9260fc720
f5343ef34d6cdaf551dc82ea414ee5dbf25b02ec
8fb30e066cbd02e95449578c3566c089c4ea8b36
21341b656b0f185651901d234e8aafee9e820ddb
fab1f8b087a2488dd62f444bd61fc97fd46a3e26
55250a54852a06bdb4c93adae23d7efb685f65e0
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
Backed out 19 changesets (bug 1434399) for build bustages on nsXULPopupManager.cpp on a CLOSED TREE Backed out changeset 499f6dffd9cb (bug 1434399) Backed out changeset 018290612415 (bug 1434399) Backed out changeset f4c3179f8e59 (bug 1434399) Backed out changeset f3ce2826b857 (bug 1434399) Backed out changeset 6d2391af01dd (bug 1434399) Backed out changeset dc98ed8c609a (bug 1434399) Backed out changeset 8eaa395d6200 (bug 1434399) Backed out changeset 19b18f4a53be (bug 1434399) Backed out changeset 8ff378a6e96a (bug 1434399) Backed out changeset 60fe73be1a26 (bug 1434399) Backed out changeset faefb2751fdc (bug 1434399) Backed out changeset 55cdf8b3a959 (bug 1434399) Backed out changeset b578cc8efb92 (bug 1434399) Backed out changeset 54cc4cb2fca1 (bug 1434399) Backed out changeset f5343ef34d6c (bug 1434399) Backed out changeset 8fb30e066cbd (bug 1434399) Backed out changeset 21341b656b0f (bug 1434399) Backed out changeset fab1f8b087a2 (bug 1434399) Backed out changeset 55250a54852a (bug 1434399)
accessible/generic/Accessible.cpp
accessible/generic/DocAccessible.cpp
accessible/generic/RootAccessible.cpp
accessible/generic/moz.build
devtools/server/actors/webextension.js
dom/base/Element.cpp
dom/base/FragmentOrElement.cpp
dom/base/nsDocument.cpp
dom/base/nsGlobalWindowInner.cpp
dom/base/nsGlobalWindowOuter.cpp
dom/base/nsIDocument.h
dom/base/nsPIWindowRoot.h
dom/base/nsWindowRoot.cpp
dom/base/nsWindowRoot.h
dom/events/EventStateManager.cpp
dom/interfaces/xul/moz.build
dom/interfaces/xul/nsIDOMXULDocument.idl
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/webidl/XULDocument.webidl
dom/xbl/nsXBLBinding.cpp
dom/xul/XULDocument.cpp
dom/xul/XULDocument.h
dom/xul/moz.build
dom/xul/nsIXULDocument.h
dom/xul/nsXULContentSink.cpp
dom/xul/nsXULContentUtils.cpp
dom/xul/nsXULElement.cpp
dom/xul/nsXULPopupListener.cpp
dom/xul/nsXULPrototypeDocument.h
layout/base/nsDocumentViewer.cpp
layout/build/nsLayoutModule.cpp
layout/xul/nsXULPopupManager.cpp
layout/xul/nsXULPopupManager.h
layout/xul/nsXULTooltipListener.cpp
toolkit/content/widgets/textbox.xml
xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
xpfe/appshell/moz.build
xpfe/appshell/nsWebShellWindow.cpp
xpfe/appshell/nsXULWindow.cpp
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -23,28 +23,27 @@
 #include "Relation.h"
 #include "Role.h"
 #include "RootAccessible.h"
 #include "States.h"
 #include "StyleInfo.h"
 #include "TableAccessible.h"
 #include "TableCellAccessible.h"
 #include "TreeWalker.h"
-#include "XULDocument.h"
 
 #include "nsIDOMElement.h"
 #include "nsIDOMNodeFilter.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIDOMTreeWalker.h"
 #include "nsIDOMXULButtonElement.h"
+#include "nsIDOMXULDocument.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULLabelElement.h"
 #include "nsIDOMXULSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
-#include "nsINodeList.h"
 #include "nsPIDOMWindow.h"
 
 #include "nsIDocument.h"
 #include "nsIContent.h"
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 
 #include "nsDeckFrame.h"
@@ -1747,27 +1746,32 @@ Accessible::RelationByType(RelationType 
           if (form) {
             nsCOMPtr<nsIContent> formContent =
               do_QueryInterface(form->GetDefaultSubmitElement());
             return Relation(mDoc, formContent);
           }
         }
       } else {
         // In XUL, use first <button default="true" .../> in the document
-        dom::XULDocument* xulDoc = mContent->OwnerDoc()->AsXULDocument();
+        nsCOMPtr<nsIDOMXULDocument> xulDoc =
+          do_QueryInterface(mContent->OwnerDoc());
         nsCOMPtr<nsIDOMXULButtonElement> buttonEl;
         if (xulDoc) {
-          nsCOMPtr<nsINodeList> possibleDefaultButtons =
-            xulDoc->GetElementsByAttribute(NS_LITERAL_STRING("default"),
-                                           NS_LITERAL_STRING("true"));
+          nsCOMPtr<nsIDOMNodeList> possibleDefaultButtons;
+          xulDoc->GetElementsByAttribute(NS_LITERAL_STRING("default"),
+                                         NS_LITERAL_STRING("true"),
+                                         getter_AddRefs(possibleDefaultButtons));
           if (possibleDefaultButtons) {
-            uint32_t length = possibleDefaultButtons->Length();
+            uint32_t length;
+            possibleDefaultButtons->GetLength(&length);
+            nsCOMPtr<nsIDOMNode> possibleButton;
             // Check for button in list of default="true" elements
             for (uint32_t count = 0; count < length && !buttonEl; count ++) {
-              buttonEl = do_QueryInterface(possibleDefaultButtons->Item(count));
+              possibleDefaultButtons->Item(count, getter_AddRefs(possibleButton));
+              buttonEl = do_QueryInterface(possibleButton);
             }
           }
           if (!buttonEl) { // Check for anonymous accept button in <dialog>
             dom::Element* rootElm = mContent->OwnerDoc()->GetRootElement();
             if (rootElm) {
               nsIContent* possibleButtonEl = rootElm->OwnerDoc()->
                 GetAnonymousElementByAttribute(rootElm, nsGkAtoms::_default,
                                                NS_LITERAL_STRING("true"));
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -20,16 +20,17 @@
 #include "xpcAccessibleDocument.h"
 
 #include "nsIMutableArray.h"
 #include "nsICommandManager.h"
 #include "nsIDocShell.h"
 #include "nsIDocument.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIDOMDocument.h"
+#include "nsIDOMXULDocument.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsPIDOMWindow.h"
 #include "nsIEditingSession.h"
 #include "nsIFrame.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsImageFrame.h"
 #include "nsIPersistentProperties2.h"
 #include "nsIPresShell.h"
@@ -44,16 +45,20 @@
 #include "mozilla/Assertions.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/TextEditor.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/DocumentType.h"
 #include "mozilla/dom/Element.h"
 
+#ifdef MOZ_XUL
+#include "nsIXULDocument.h"
+#endif
+
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Static member initialization
 
 static nsStaticAtom** kRelationAttrs[] =
 {
@@ -203,17 +208,18 @@ DocAccessible::NativeRole()
     int32_t itemType = docShell->ItemType();
     if (sameTypeRoot == docShell) {
       // Root of content or chrome tree
       if (itemType == nsIDocShellTreeItem::typeChrome)
         return roles::CHROME_WINDOW;
 
       if (itemType == nsIDocShellTreeItem::typeContent) {
 #ifdef MOZ_XUL
-        if (mDocumentNode && mDocumentNode->IsXULDocument())
+        nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocumentNode));
+        if (xulDoc)
           return roles::APPLICATION;
 #endif
         return roles::DOCUMENT;
       }
     }
     else if (itemType == nsIDocShellTreeItem::typeContent) {
       return roles::DOCUMENT;
     }
@@ -381,17 +387,18 @@ DocAccessible::URL(nsAString& aURL) cons
   }
   CopyUTF8toUTF16(theURL, aURL);
 }
 
 void
 DocAccessible::DocType(nsAString& aType) const
 {
 #ifdef MOZ_XUL
-  if (mDocumentNode->IsXULDocument()) {
+  nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocumentNode));
+  if (xulDoc) {
     aType.AssignLiteral("window"); // doctype not implemented for XUL at time of writing - causes assertion
     return;
   }
 #endif
   dom::DocumentType* docType = mDocumentNode->GetDoctype();
   if (docType)
     docType->GetPublicId(aType);
 }
--- a/accessible/generic/RootAccessible.cpp
+++ b/accessible/generic/RootAccessible.cpp
@@ -37,16 +37,17 @@
 #include "nsIServiceManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsReadableUtils.h"
 #include "nsFocusManager.h"
 #include "nsGlobalWindow.h"
 
 #ifdef MOZ_XUL
+#include "nsIXULDocument.h"
 #include "nsIXULWindow.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 using namespace mozilla::dom;
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/accessible/generic/moz.build
+++ b/accessible/generic/moz.build
@@ -26,17 +26,16 @@ UNIFIED_SOURCES += [
 ]
 
 LOCAL_INCLUDES += [
     '/accessible/base',
     '/accessible/html',
     '/accessible/xpcom',
     '/accessible/xul',
     '/dom/base',
-    '/dom/xul',
     '/layout/generic',
     '/layout/xul',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     LOCAL_INCLUDES += [
         '/accessible/ipc/win',
     ]
--- a/devtools/server/actors/webextension.js
+++ b/devtools/server/actors/webextension.js
@@ -7,17 +7,16 @@
 const { Ci, Cu, Cc } = require("chrome");
 const Services = require("Services");
 
 const { ChromeActor } = require("./chrome");
 const makeDebugger = require("./utils/make-debugger");
 
 loader.lazyRequireGetter(this, "mapURIToAddonID", "devtools/server/actors/utils/map-uri-to-addon-id");
 loader.lazyRequireGetter(this, "unwrapDebuggerObjectGlobal", "devtools/server/actors/script", true);
-loader.lazyRequireGetter(this, "ChromeUtils");
 
 const FALLBACK_DOC_MESSAGE = "Your addon does not have any document opened yet.";
 
 /**
  * Creates a TabActor for debugging all the contexts associated to a target WebExtensions
  * add-on running in a child extension process.
  * Most of the implementation is inherited from ChromeActor (which inherits most of its
  * implementation from TabActor).
@@ -343,17 +342,17 @@ WebExtensionChildActor.prototype._should
       // The global might be a sandbox with a window object in its proto chain. If the
       // window navigated away since the sandbox was created, it can throw a security
       // exception during this property check as the sandbox no longer has access to
       // its own proto.
       return false;
     }
 
     // Filter out any global which contains a XUL document.
-    if (ChromeUtils.getClassName(global.document) == "XULDocument") {
+    if (global.document instanceof Ci.nsIDOMXULDocument) {
       return false;
     }
 
     // Change top level document as a simulated frame switching.
     if (global.document.ownerGlobal && this.isExtensionWindow(global)) {
       this._onNewExtensionWindow(global.document.ownerGlobal);
     }
 
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -112,16 +112,20 @@
 #include "nsView.h"
 #include "nsViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
 #include "nsCSSRuleProcessor.h"
 #include "nsRuleProcessorData.h"
 #include "nsTextNode.h"
 
+#ifdef MOZ_XUL
+#include "nsIXULDocument.h"
+#endif /* MOZ_XUL */
+
 #include "nsCycleCollectionParticipant.h"
 #include "nsCCUncollectableMarker.h"
 
 #include "mozAutoDocUpdate.h"
 
 #include "nsCSSParser.h"
 #include "nsDOMMutationObserver.h"
 #include "nsWrapperCacheInlines.h"
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -98,16 +98,20 @@
 #include "nsViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "ChildIterator.h"
 #include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
 #include "nsRuleProcessorData.h"
 #include "nsTextNode.h"
 #include "mozilla/dom/NodeListBinding.h"
 
+#ifdef MOZ_XUL
+#include "nsIXULDocument.h"
+#endif /* MOZ_XUL */
+
 #include "nsCCUncollectableMarker.h"
 
 #include "mozAutoDocUpdate.h"
 
 #include "mozilla/Sprintf.h"
 #include "nsDOMMutationObserver.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsCycleCollector.h"
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -148,16 +148,17 @@
 #include "nsCCUncollectableMarker.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsICategoryManager.h"
 #include "nsIDocumentLoaderFactory.h"
 #include "nsIDocumentLoader.h"
 #include "nsIContentViewer.h"
 #include "nsIXMLContentSink.h"
+#include "nsIXULDocument.h"
 #include "nsIPrompt.h"
 #include "nsIPropertyBag2.h"
 #include "mozilla/dom/PageTransitionEvent.h"
 #include "mozilla/dom/StyleRuleChangeEvent.h"
 #include "mozilla/dom/StyleSheetChangeEvent.h"
 #include "mozilla/dom/StyleSheetApplicableStateChangeEvent.h"
 #include "nsJSUtils.h"
 #include "nsFrameLoader.h"
@@ -981,17 +982,18 @@ nsExternalResourceMap::AddExternalResour
 
   nsresult rv = NS_OK;
 
   nsCOMPtr<nsIDocument> doc;
   if (aViewer) {
     doc = aViewer->GetDocument();
     NS_ASSERTION(doc, "Must have a document");
 
-    if (doc->IsXULDocument()) {
+    nsCOMPtr<nsIXULDocument> xulDoc = do_QueryInterface(doc);
+    if (xulDoc) {
       // We don't handle XUL stuff here yet.
       rv = NS_ERROR_NOT_AVAILABLE;
     } else {
       doc->SetDisplayDocument(aDisplayDocument);
 
       // Make sure that hiding our viewer will tear down its presentation.
       aViewer->SetSticky(false);
 
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -177,16 +177,20 @@
 #include "nsIPrintSettingsService.h"
 #include "nsIWebBrowserPrint.h"
 #endif
 
 #include "nsWindowRoot.h"
 #include "nsNetCID.h"
 #include "nsIArray.h"
 
+// XXX An unfortunate dependency exists here (two XUL files).
+#include "nsIDOMXULDocument.h"
+#include "nsIDOMXULCommandDispatcher.h"
+
 #include "nsBindingManager.h"
 #include "nsXBLService.h"
 
 // used for popup blocking, needs to be converted to something
 // belonging to the back-end like nsIContentPolicy
 #include "nsIPopupWindowManager.h"
 
 #include "nsIDragService.h"
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -175,17 +175,18 @@
 #include "nsIPrintSettingsService.h"
 #include "nsIWebBrowserPrint.h"
 #endif
 
 #include "nsWindowRoot.h"
 #include "nsNetCID.h"
 #include "nsIArray.h"
 
-#include "XULDocument.h"
+// XXX An unfortunate dependency exists here (two XUL files).
+#include "nsIDOMXULDocument.h"
 #include "nsIDOMXULCommandDispatcher.h"
 
 #include "nsBindingManager.h"
 #include "nsXBLService.h"
 
 // used for popup blocking, needs to be converted to something
 // belonging to the back-end like nsIContentPolicy
 #include "nsIPopupWindowManager.h"
@@ -6379,25 +6380,25 @@ nsGlobalWindowOuter::UpdateCommands(cons
     }
   }
 
   nsPIDOMWindowOuter *rootWindow = GetPrivateRoot();
   if (!rootWindow) {
     return;
   }
 
-  nsIDocument* doc = rootWindow->GetExtantDoc();
-  XULDocument* xulDoc = doc ? doc->AsXULDocument() : nullptr;
+  nsCOMPtr<nsIDOMXULDocument> xulDoc =
+    do_QueryInterface(rootWindow->GetExtantDoc());
   // See if we contain a XUL document.
   // selectionchange action is only used for mozbrowser, not for XUL. So we bypass
   // XUL command dispatch if anAction is "selectionchange".
   if (xulDoc && !anAction.EqualsLiteral("selectionchange")) {
     // Retrieve the command dispatcher and call updateCommands on it.
-    nsIDOMXULCommandDispatcher* xulCommandDispatcher =
-      xulDoc->GetCommandDispatcher();
+    nsCOMPtr<nsIDOMXULCommandDispatcher> xulCommandDispatcher;
+    xulDoc->GetCommandDispatcher(getter_AddRefs(xulCommandDispatcher));
     if (xulCommandDispatcher) {
       nsContentUtils::AddScriptRunner(new CommandDispatcher(xulCommandDispatcher,
                                                             anAction));
     }
   }
 }
 
 Selection*
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -173,17 +173,16 @@ class SVGDocument;
 class SVGSVGElement;
 class Touch;
 class TouchList;
 class TreeWalker;
 class XPathEvaluator;
 class XPathExpression;
 class XPathNSResolver;
 class XPathResult;
-class XULDocument;
 template<typename> class Sequence;
 
 template<typename, typename> class CallbackObjectHolder;
 typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
 
 enum class CallerType : uint32_t;
 
 } // namespace dom
@@ -3038,17 +3037,16 @@ public:
   already_AddRefed<nsIURI> GetMozDocumentURIIfNotForErrorPages();
 
   // ParentNode
   nsIHTMLCollection* Children();
   uint32_t ChildElementCount();
 
   virtual nsHTMLDocument* AsHTMLDocument() { return nullptr; }
   virtual mozilla::dom::SVGDocument* AsSVGDocument() { return nullptr; }
-  virtual mozilla::dom::XULDocument* AsXULDocument() { return nullptr; }
 
   /*
    * Given a node, get a weak reference to it and append that reference to
    * mBlockedTrackingNodes. Can be used later on to look up a node in it.
    * (e.g., by the UI)
    */
   void AddBlockedTrackingNode(nsINode *node)
   {
--- a/dom/base/nsPIWindowRoot.h
+++ b/dom/base/nsPIWindowRoot.h
@@ -9,17 +9,16 @@
 
 #include "nsISupports.h"
 #include "mozilla/dom/EventTarget.h"
 #include "nsWeakReference.h"
 
 class nsPIDOMWindowOuter;
 class nsIControllers;
 class nsIController;
-class nsINode;
 
 namespace mozilla {
 namespace dom {
 class TabParent;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IWINDOWROOT_IID \
@@ -29,18 +28,18 @@ class TabParent;
 class nsPIWindowRoot : public mozilla::dom::EventTarget
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IWINDOWROOT_IID)
 
   virtual nsPIDOMWindowOuter* GetWindow()=0;
 
   // get and set the node that is the context of a popup menu
-  virtual already_AddRefed<nsINode> GetPopupNode() = 0;
-  virtual void SetPopupNode(nsINode* aNode) = 0;
+  virtual nsIDOMNode* GetPopupNode() = 0;
+  virtual void SetPopupNode(nsIDOMNode* aNode) = 0;
 
   /**
    * @param aForVisibleWindow   true if caller needs controller which is
    *                            associated with visible window.
    */
   virtual nsresult GetControllerForCommand(const char *aCommand,
                                            bool aForVisibleWindow,
                                            nsIController** aResult) = 0;
--- a/dom/base/nsWindowRoot.cpp
+++ b/dom/base/nsWindowRoot.cpp
@@ -366,25 +366,25 @@ nsWindowRoot::GetEnabledDisabledCommands
                                                aEnabledCommands, aDisabledCommands);
     }
 
     nsGlobalWindowOuter* win = nsGlobalWindowOuter::Cast(focusedWindow);
     focusedWindow = win->GetPrivateParent();
   }
 }
 
-already_AddRefed<nsINode>
+nsIDOMNode*
 nsWindowRoot::GetPopupNode()
 {
-  nsCOMPtr<nsINode> popupNode = do_QueryReferent(mPopupNode);
-  return popupNode.forget();
+  nsCOMPtr<nsIDOMNode> popupNode = do_QueryReferent(mPopupNode);
+  return popupNode;
 }
 
 void
-nsWindowRoot::SetPopupNode(nsINode* aNode)
+nsWindowRoot::SetPopupNode(nsIDOMNode* aNode)
 {
   mPopupNode = do_GetWeakReference(aNode);
 }
 
 nsIGlobalObject*
 nsWindowRoot::GetParentObject()
 {
   return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
--- a/dom/base/nsWindowRoot.h
+++ b/dom/base/nsWindowRoot.h
@@ -47,18 +47,18 @@ public:
                                   nsIControllers** aResult) override;
   virtual nsresult GetControllerForCommand(const char * aCommand,
                                            bool aForVisibleWindow,
                                            nsIController** _retval) override;
 
   virtual void GetEnabledDisabledCommands(nsTArray<nsCString>& aEnabledCommands,
                                           nsTArray<nsCString>& aDisabledCommands) override;
 
-  virtual already_AddRefed<nsINode> GetPopupNode() override;
-  virtual void SetPopupNode(nsINode* aNode) override;
+  virtual nsIDOMNode* GetPopupNode() override;
+  virtual void SetPopupNode(nsIDOMNode* aNode) override;
 
   virtual void SetParentTarget(mozilla::dom::EventTarget* aTarget) override
   {
     mParent = aTarget;
   }
   virtual mozilla::dom::EventTarget* GetParentTarget() override { return mParent; }
   virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override;
   virtual nsIGlobalObject* GetOwnerGlobal() const override;
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -71,16 +71,17 @@
 
 #include "imgIContainer.h"
 #include "nsIProperties.h"
 #include "nsISupportsPrimitives.h"
 
 #include "nsServiceManagerUtils.h"
 #include "nsITimer.h"
 #include "nsFontMetrics.h"
+#include "nsIDOMXULDocument.h"
 #include "nsIDragService.h"
 #include "nsIDragSession.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "nsContentAreaDragDrop.h"
 #ifdef MOZ_XUL
 #include "nsTreeBodyFrame.h"
 #endif
 #include "nsIController.h"
@@ -985,17 +986,19 @@ IsAccessKeyTarget(nsIContent* aContent, 
   // Use GetAttr because we want Unicode case=insensitive matching
   // XXXbz shouldn't this be case-sensitive, per spec?
   nsString contentKey;
   if (!aContent->IsElement() ||
       !aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, contentKey) ||
       !contentKey.Equals(aKey, nsCaseInsensitiveStringComparator()))
     return false;
 
-  if (!aContent->OwnerDoc()->IsXULDocument() && !aContent->IsXULElement())
+  nsCOMPtr<nsIDOMXULDocument> xulDoc =
+    do_QueryInterface(aContent->OwnerDoc());
+  if (!xulDoc && !aContent->IsXULElement())
     return true;
 
     // For XUL we do visibility checks.
   if (!aFrame)
     return false;
 
   if (aFrame->IsFocusable())
     return true;
--- a/dom/interfaces/xul/moz.build
+++ b/dom/interfaces/xul/moz.build
@@ -10,16 +10,17 @@ with Files("**"):
 XPIDL_SOURCES += [
     'nsIDOMXULButtonElement.idl',
     'nsIDOMXULCheckboxElement.idl',
     'nsIDOMXULCommandDispatcher.idl',
     'nsIDOMXULCommandEvent.idl',
     'nsIDOMXULContainerElement.idl',
     'nsIDOMXULControlElement.idl',
     'nsIDOMXULDescriptionElement.idl',
+    'nsIDOMXULDocument.idl',
     'nsIDOMXULElement.idl',
     'nsIDOMXULLabeledControlEl.idl',
     'nsIDOMXULLabelElement.idl',
     'nsIDOMXULMenuListElement.idl',
     'nsIDOMXULMultSelectCntrlEl.idl',
     'nsIDOMXULRelatedElement.idl',
     'nsIDOMXULSelectCntrlEl.idl',
     'nsIDOMXULSelectCntrlItemEl.idl',
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/xul/nsIDOMXULDocument.idl
@@ -0,0 +1,71 @@
+/* -*- 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"
+#include "nsIDOMDocument.idl"
+
+interface nsIDOMXULCommandDispatcher;
+interface nsIObserver;
+interface nsIBoxObject;
+
+[uuid(7790d4c3-e8f0-4e29-9887-d683ed2b2a44)]
+interface nsIDOMXULDocument : nsIDOMDocument
+{
+  attribute nsIDOMNode                          popupNode;
+
+  /**
+   * These attributes correspond to trustedGetPopupNode().rangeOffset and
+   * rangeParent. They will help you find where in the DOM the popup is
+   * happening. Can be accessed from chrome only, and only during a popup
+   * event. Accessing any other time will be an error.
+   */
+  readonly attribute nsIDOMNode                 popupRangeParent;
+  readonly attribute long                       popupRangeOffset;
+
+  attribute nsIDOMNode                          tooltipNode;
+
+  readonly attribute nsIDOMXULCommandDispatcher commandDispatcher;
+
+  readonly attribute long                       width;
+  readonly attribute long                       height;
+
+  nsIDOMNodeList            getElementsByAttribute(in DOMString name,
+                                                   in DOMString value);
+
+  nsIDOMNodeList            getElementsByAttributeNS(in DOMString namespaceURI,
+                                                     in DOMString name,
+                                                     in DOMString value);
+
+  void                      addBroadcastListenerFor(in nsIDOMElement broadcaster,
+                                                    in nsIDOMElement observer,
+                                                    in DOMString attr);
+
+  void                      removeBroadcastListenerFor(in nsIDOMElement broadcaster,
+                                                       in nsIDOMElement observer,
+                                                       in DOMString attr);
+
+  void                      persist(in DOMString id, in DOMString attr);
+
+  nsIBoxObject getBoxObjectFor(in nsIDOMElement elt);
+
+  /**
+   * Loads a XUL overlay and merges it with the current document, notifying an
+   * observer when the merge is complete. 
+   * @param   url
+   *          The URL of the overlay to load and merge
+   * @param   observer
+   *          An object implementing nsIObserver that will be notified with a
+   *          message of topic "xul-overlay-merged" when the merge is complete. 
+   *          The subject parameter of |observe| will QI to a nsIURI - the URI 
+   *          of the merged overlay. This parameter is optional and may be null.
+   *
+   * NOTICE:  In the 2.0 timeframe this API will change such that the 
+   *          implementation will fire a DOMXULOverlayMerged event upon merge
+   *          completion rather than notifying an observer. Do not rely on this
+   *          API's behavior _not_ to change because it will!
+   *          - Ben Goodger (8/23/2005)
+   */
+  void                      loadOverlay(in DOMString url, in nsIObserver aObserver);
+};
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -70,16 +70,18 @@ static NS_DEFINE_CID(kAppShellCID, NS_AP
 #ifdef XP_WIN
 #include <wtypes.h>
 #include <winuser.h>
 #include "mozilla/widget/WinMessages.h"
 #endif // #ifdef XP_WIN
 
 #ifdef XP_MACOSX
 #include "ComplexTextInputPanel.h"
+#include "nsIDOMXULDocument.h"
+#include "nsIDOMXULCommandDispatcher.h"
 #endif
 
 #ifdef MOZ_WIDGET_GTK
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
 #endif
 
 using namespace mozilla;
--- a/dom/webidl/XULDocument.webidl
+++ b/dom/webidl/XULDocument.webidl
@@ -1,12 +1,15 @@
 /* -*- 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/.
+ *
+ * The origin of this IDL file is:
+ * dom/interfaces/xul/nsIDOMXULDocument.idl
  */
 
 interface XULCommandDispatcher;
 interface MozObserver;
 
 [Func="IsChromeOrXBL"]
 interface XULDocument : Document {
            attribute Node? popupNode;
@@ -44,28 +47,11 @@ interface XULDocument : Document {
                                   DOMString attr);
 
   [Throws]
   void persist([TreatNullAs=EmptyString] DOMString id, DOMString attr);
 
   [Throws]
   BoxObject? getBoxObjectFor(Element? element);
 
-  /**
-   * Loads a XUL overlay and merges it with the current document, notifying an
-   * observer when the merge is complete.
-   * @param   url
-   *          The URL of the overlay to load and merge
-   * @param   observer
-   *          An object implementing nsIObserver that will be notified with a
-   *          message of topic "xul-overlay-merged" when the merge is complete.
-   *          The subject parameter of |observe| will QI to a nsIURI - the URI
-   *          of the merged overlay. This parameter is optional and may be null.
-   *
-   * NOTICE:  In the 2.0 timeframe this API will change such that the
-   *          implementation will fire a DOMXULOverlayMerged event upon merge
-   *          completion rather than notifying an observer. Do not rely on this
-   *          API's behavior _not_ to change because it will!
-   *          - Ben Goodger (8/23/2005)
-   */
   [Throws]
   void loadOverlay(DOMString url, MozObserver? observer);
 };
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -15,17 +15,17 @@
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "plstr.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsContentUtils.h"
 #include "ChildIterator.h"
 #ifdef MOZ_XUL
-#include "XULDocument.h"
+#include "nsIXULDocument.h"
 #endif
 #include "nsIXMLContentSink.h"
 #include "nsContentCID.h"
 #include "mozilla/dom/XMLDocument.h"
 #include "jsapi.h"
 #include "nsXBLService.h"
 #include "nsIXPConnect.h"
 #include "nsIScriptContext.h"
@@ -225,34 +225,34 @@ nsXBLBinding::BindAnonymousContent(nsICo
       child->UnbindFromTree();
       return;
     }
 
 #ifdef MOZ_XUL
     // To make XUL templates work (and other goodies that happen when
     // an element is added to a XUL document), we need to notify the
     // XUL document using its special API.
-    XULDocument* xuldoc = doc ? doc->AsXULDocument() : nullptr;
-    if (xuldoc) {
+    nsCOMPtr<nsIXULDocument> xuldoc(do_QueryInterface(doc));
+    if (xuldoc)
       xuldoc->AddSubtreeToDocument(child);
-    }
 #endif
   }
 }
 
 void
 nsXBLBinding::UnbindAnonymousContent(nsIDocument* aDocument,
                                      nsIContent* aAnonParent,
                                      bool aNullParent)
 {
   nsAutoScriptBlocker scriptBlocker;
   // Hold a strong ref while doing this, just in case.
   nsCOMPtr<nsIContent> anonParent = aAnonParent;
 #ifdef MOZ_XUL
-  XULDocument* xuldoc = aDocument ? aDocument->AsXULDocument() : nullptr;
+  nsCOMPtr<nsIXULDocument> xuldoc =
+    do_QueryInterface(aDocument);
 #endif
   for (nsIContent* child = aAnonParent->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
     child->UnbindFromTree(true, aNullParent);
 #ifdef MOZ_XUL
     if (xuldoc) {
       xuldoc->RemoveSubtreeFromDocument(child);
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -45,17 +45,16 @@
 #include "nsParserCIID.h"
 #include "nsPIBoxObject.h"
 #include "mozilla/dom/BoxObject.h"
 #include "nsString.h"
 #include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
 #include "nsXULCommandDispatcher.h"
 #include "nsXULElement.h"
-#include "nsXULPrototypeCache.h"
 #include "mozilla/Logging.h"
 #include "nsIFrame.h"
 #include "nsXBLService.h"
 #include "nsCExternalHandlerService.h"
 #include "nsMimeTypes.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsContentList.h"
@@ -212,17 +211,17 @@ XULDocument::~XULDocument()
       js_free(mOffThreadCompileStringBuf);
     }
 }
 
 } // namespace dom
 } // namespace mozilla
 
 nsresult
-NS_NewXULDocument(nsIDocument** result)
+NS_NewXULDocument(nsIXULDocument** result)
 {
     NS_PRECONDITION(result != nullptr, "null ptr");
     if (! result)
         return NS_ERROR_NULL_POINTER;
 
     RefPtr<XULDocument> doc = new XULDocument();
 
     nsresult rv;
@@ -278,16 +277,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XULDocument, XMLDocument)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mCommandDispatcher)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStore)
     //XXX We should probably unlink all the objects we traverse.
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(XULDocument,
                                              XMLDocument,
+                                             nsIXULDocument,
+                                             nsIDOMXULDocument,
                                              nsIStreamLoaderObserver,
                                              nsICSSLoaderObserver,
                                              nsIOffThreadScriptReceiver)
 
 
 //----------------------------------------------------------------------
 //
 // nsIDocument interface
@@ -517,17 +518,17 @@ XULDocument::EndLoad()
         rv = uri->GetSpec(urlspec);
         if (NS_SUCCEEDED(rv)) {
             MOZ_LOG(gXULLog, LogLevel::Warning,
                    ("xul: Finished loading document '%s'", urlspec.get()));
         }
     }
 }
 
-nsresult
+NS_IMETHODIMP
 XULDocument::OnPrototypeLoadDone(bool aResumeWalk)
 {
     nsresult rv;
 
     // Add the style overlays from chrome registry, if any.
     rv = AddPrototypeSheets();
     if (NS_FAILED(rv)) return rv;
 
@@ -671,16 +672,29 @@ XULDocument::SynchronizeBroadcastListene
         // hookup: doing so would potentially run the |onbroadcast|
         // handler before the |onload| handler, which could define JS
         // properties that mask XBL properties, etc.
         ExecuteOnBroadcastHandlerFor(aBroadcaster, aListener, name);
 #endif
     }
 }
 
+NS_IMETHODIMP
+XULDocument::AddBroadcastListenerFor(nsIDOMElement* aBroadcaster,
+                                     nsIDOMElement* aListener,
+                                     const nsAString& aAttr)
+{
+    ErrorResult rv;
+    nsCOMPtr<Element> broadcaster = do_QueryInterface(aBroadcaster);
+    nsCOMPtr<Element> listener = do_QueryInterface(aListener);
+    NS_ENSURE_ARG(broadcaster && listener);
+    AddBroadcastListenerFor(*broadcaster, *listener, aAttr, rv);
+    return rv.StealNSResult();
+}
+
 void
 XULDocument::AddBroadcastListenerFor(Element& aBroadcaster, Element& aListener,
                                      const nsAString& aAttr, ErrorResult& aRv)
 {
     nsresult rv =
         nsContentUtils::CheckSameOrigin(this, &aBroadcaster);
 
     if (NS_FAILED(rv)) {
@@ -739,16 +753,28 @@ XULDocument::AddBroadcastListenerFor(Ele
     bl->mListener  = do_GetWeakReference(&aListener);
     bl->mAttribute = attr;
 
     entry->mListeners.AppendElement(bl);
 
     SynchronizeBroadcastListener(&aBroadcaster, &aListener, aAttr);
 }
 
+NS_IMETHODIMP
+XULDocument::RemoveBroadcastListenerFor(nsIDOMElement* aBroadcaster,
+                                        nsIDOMElement* aListener,
+                                        const nsAString& aAttr)
+{
+    nsCOMPtr<Element> broadcaster = do_QueryInterface(aBroadcaster);
+    nsCOMPtr<Element> listener = do_QueryInterface(aListener);
+    NS_ENSURE_ARG(broadcaster && listener);
+    RemoveBroadcastListenerFor(*broadcaster, *listener, aAttr);
+    return NS_OK;
+}
+
 void
 XULDocument::RemoveBroadcastListenerFor(Element& aBroadcaster,
                                         Element& aListener,
                                         const nsAString& aAttr)
 {
     // If we haven't added any broadcast listeners, then there sure
     // aren't any to remove.
     if (! mBroadcasterMap)
@@ -984,16 +1010,21 @@ XULDocument::ContentRemoved(nsIDocument*
     NS_ASSERTION(aDocument == this, "unexpected doc");
 
     // Might not need this, but be safe for now.
     nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
 
     RemoveSubtreeFromDocument(aChild);
 }
 
+//----------------------------------------------------------------------
+//
+// nsIXULDocument interface
+//
+
 nsresult
 XULDocument::AddForwardReference(nsForwardReference* aRef)
 {
     if (mResolutionPhase < aRef->GetPhase()) {
         if (!mForwardReferences.AppendElement(aRef)) {
             delete aRef;
             return NS_ERROR_OUT_OF_MEMORY;
         }
@@ -1065,16 +1096,25 @@ XULDocument::ResolveForwardReferences()
     return NS_OK;
 }
 
 //----------------------------------------------------------------------
 //
 // nsIDOMDocument interface
 //
 
+NS_IMETHODIMP
+XULDocument::GetElementsByAttribute(const nsAString& aAttribute,
+                                    const nsAString& aValue,
+                                    nsIDOMNodeList** aReturn)
+{
+    *aReturn = GetElementsByAttribute(aAttribute, aValue).take();
+    return NS_OK;
+}
+
 already_AddRefed<nsINodeList>
 XULDocument::GetElementsByAttribute(const nsAString& aAttribute,
                                     const nsAString& aValue)
 {
     RefPtr<nsAtom> attrAtom(NS_Atomize(aAttribute));
     void* attrValue = new nsString(aValue);
     RefPtr<nsContentList> list = new nsContentList(this,
                                             MatchAttribute,
@@ -1082,16 +1122,28 @@ XULDocument::GetElementsByAttribute(cons
                                             attrValue,
                                             true,
                                             attrAtom,
                                             kNameSpaceID_Unknown);
 
     return list.forget();
 }
 
+NS_IMETHODIMP
+XULDocument::GetElementsByAttributeNS(const nsAString& aNamespaceURI,
+                                      const nsAString& aAttribute,
+                                      const nsAString& aValue,
+                                      nsIDOMNodeList** aReturn)
+{
+    ErrorResult rv;
+    *aReturn = GetElementsByAttributeNS(aNamespaceURI, aAttribute,
+                                        aValue, rv).take();
+    return rv.StealNSResult();
+}
+
 already_AddRefed<nsINodeList>
 XULDocument::GetElementsByAttributeNS(const nsAString& aNamespaceURI,
                                       const nsAString& aAttribute,
                                       const nsAString& aValue,
                                       ErrorResult& aRv)
 {
     RefPtr<nsAtom> attrAtom(NS_Atomize(aAttribute));
     void* attrValue = new nsString(aValue);
@@ -1112,31 +1164,28 @@ XULDocument::GetElementsByAttributeNS(co
                                             nsContentUtils::DestroyMatchString,
                                             attrValue,
                                             true,
                                             attrAtom,
                                             nameSpaceId);
     return list.forget();
 }
 
-void
+NS_IMETHODIMP
 XULDocument::Persist(const nsAString& aID,
-                     const nsAString& aAttr,
-                     ErrorResult& aRv)
+                     const nsAString& aAttr)
 {
     // If we're currently reading persisted attributes out of the
     // localstore, _don't_ re-enter and try to set them again!
-    if (mApplyingPersistedAttrs) {
-        return;
-    }
+    if (mApplyingPersistedAttrs)
+        return NS_OK;
 
     Element* element = nsDocument::GetElementById(aID);
-    if (!element) {
-        return;
-    }
+    if (!element)
+        return NS_OK;
 
     RefPtr<nsAtom> tag;
     int32_t nameSpaceID;
 
     RefPtr<mozilla::dom::NodeInfo> ni = element->GetExistingAttrNameFromQName(aAttr);
     nsresult rv;
     if (ni) {
         tag = ni->NameAtom();
@@ -1144,36 +1193,31 @@ XULDocument::Persist(const nsAString& aI
     }
     else {
         // Make sure that this QName is going to be valid.
         const char16_t *colon;
         rv = nsContentUtils::CheckQName(PromiseFlatString(aAttr), true, &colon);
 
         if (NS_FAILED(rv)) {
             // There was an invalid character or it was malformed.
-            aRv.Throw(NS_ERROR_INVALID_ARG);
-            return;
+            return NS_ERROR_INVALID_ARG;
         }
 
         if (colon) {
             // We don't really handle namespace qualifiers in attribute names.
-            aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
-            return;
+            return NS_ERROR_NOT_IMPLEMENTED;
         }
 
         tag = NS_Atomize(aAttr);
-        if (NS_WARN_IF(!tag)) {
-            aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-            return;
-        }
+        NS_ENSURE_TRUE(tag, NS_ERROR_OUT_OF_MEMORY);
 
         nameSpaceID = kNameSpaceID_None;
     }
 
-    aRv = Persist(element, nameSpaceID, tag);
+    return Persist(element, nameSpaceID, tag);
 }
 
 nsresult
 XULDocument::Persist(Element* aElement, int32_t aNameSpaceID,
                      nsAtom* aAttribute)
 {
     // For non-chrome documents, persistance is simply broken
     if (!nsContentUtils::IsSystemPrincipal(NodePrincipal()))
@@ -1232,139 +1276,239 @@ XULDocument::GetViewportSize(int32_t* aW
     nsSize size = frame->GetSize();
 
     *aWidth = nsPresContext::AppUnitsToIntCSSPixels(size.width);
     *aHeight = nsPresContext::AppUnitsToIntCSSPixels(size.height);
 
     return NS_OK;
 }
 
+NS_IMETHODIMP
+XULDocument::GetWidth(int32_t* aWidth)
+{
+    NS_ENSURE_ARG_POINTER(aWidth);
+
+    int32_t height;
+    return GetViewportSize(aWidth, &height);
+}
+
 int32_t
 XULDocument::GetWidth(ErrorResult& aRv)
 {
-    int32_t width = 0;
-    int32_t height = 0;
-    aRv = GetViewportSize(&width, &height);
+    int32_t width;
+    aRv = GetWidth(&width);
     return width;
 }
 
+NS_IMETHODIMP
+XULDocument::GetHeight(int32_t* aHeight)
+{
+    NS_ENSURE_ARG_POINTER(aHeight);
+
+    int32_t width;
+    return GetViewportSize(&width, aHeight);
+}
+
 int32_t
 XULDocument::GetHeight(ErrorResult& aRv)
 {
-    int32_t width = 0;
-    int32_t height = 0;
-    aRv = GetViewportSize(&width, &height);
+    int32_t height;
+    aRv = GetHeight(&height);
     return height;
 }
 
-static JSObject*
-GetScopeObjectOfNode(nsINode* node)
+JSObject*
+GetScopeObjectOfNode(nsIDOMNode* node)
 {
     MOZ_ASSERT(node, "Must not be called with null.");
 
     // Window root occasionally keeps alive a node of a document whose
     // window is already dead. If in this brief period someone calls
     // GetPopupNode and we return that node, nsNodeSH::PreCreate will throw,
     // because it will not know which scope this node belongs to. Returning
     // an orphan node like that to JS would be a bug anyway, so to avoid
     // this, let's do the same check as nsNodeSH::PreCreate does to
     // determine the scope and if it fails let's just return null in
     // XULDocument::GetPopupNode.
-    nsIDocument* doc = node->OwnerDoc();
-    MOZ_ASSERT(doc, "This should never happen.");
+    nsCOMPtr<nsINode> inode = do_QueryInterface(node);
+    MOZ_ASSERT(inode, "How can this happen?");
+
+    nsIDocument* doc = inode->OwnerDoc();
+    MOZ_ASSERT(inode, "This should never happen.");
 
     nsIGlobalObject* global = doc->GetScopeObject();
     return global ? global->GetGlobalJSObject() : nullptr;
 }
 
-already_AddRefed<nsINode>
-XULDocument::GetPopupNode()
+//----------------------------------------------------------------------
+//
+// nsIDOMXULDocument interface
+//
+
+NS_IMETHODIMP
+XULDocument::GetPopupNode(nsIDOMNode** aNode)
 {
-    nsCOMPtr<nsINode> node;
+    *aNode = nullptr;
+
+    nsCOMPtr<nsIDOMNode> node;
     nsCOMPtr<nsPIWindowRoot> rootWin = GetWindowRoot();
-    if (rootWin) {
+    if (rootWin)
         node = rootWin->GetPopupNode(); // addref happens here
-    }
 
     if (!node) {
         nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
         if (pm) {
             node = pm->GetLastTriggerPopupNode(this);
         }
     }
 
     if (node && nsContentUtils::CanCallerAccess(node)
         && GetScopeObjectOfNode(node)) {
-        return node.forget();
+        node.forget(aNode);
     }
 
-    return nullptr;
+    return NS_OK;
+}
+
+already_AddRefed<nsINode>
+XULDocument::GetPopupNode()
+{
+    nsCOMPtr<nsIDOMNode> node;
+    DebugOnly<nsresult> rv = GetPopupNode(getter_AddRefs(node));
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
+    nsCOMPtr<nsINode> retval(do_QueryInterface(node));
+    return retval.forget();
+}
+
+NS_IMETHODIMP
+XULDocument::SetPopupNode(nsIDOMNode* aNode)
+{
+    if (aNode) {
+        // only allow real node objects
+        nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
+        NS_ENSURE_ARG(node);
+    }
+
+    nsCOMPtr<nsPIWindowRoot> rootWin = GetWindowRoot();
+    if (rootWin)
+        rootWin->SetPopupNode(aNode); // addref happens here
+
+    return NS_OK;
 }
 
 void
 XULDocument::SetPopupNode(nsINode* aNode)
 {
-    nsCOMPtr<nsPIWindowRoot> rootWin = GetWindowRoot();
-    if (rootWin) {
-        rootWin->SetPopupNode(aNode);
-    }
+    nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aNode));
+    DebugOnly<nsresult> rv = SetPopupNode(node);
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
 }
 
 // Returns the rangeOffset element from the XUL Popup Manager. This is for
 // chrome callers only.
-nsINode*
+NS_IMETHODIMP
+XULDocument::GetPopupRangeParent(nsIDOMNode** aRangeParent)
+{
+    NS_ENSURE_ARG_POINTER(aRangeParent);
+    *aRangeParent = nullptr;
+
+    nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+    if (!pm)
+        return NS_ERROR_FAILURE;
+
+    int32_t offset;
+    pm->GetMouseLocation(aRangeParent, &offset);
+
+    if (*aRangeParent && !nsContentUtils::CanCallerAccess(*aRangeParent)) {
+        NS_RELEASE(*aRangeParent);
+        return NS_ERROR_DOM_SECURITY_ERR;
+    }
+
+    return NS_OK;
+}
+
+already_AddRefed<nsINode>
 XULDocument::GetPopupRangeParent(ErrorResult& aRv)
 {
-    nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
-    if (!pm) {
-        aRv.Throw(NS_ERROR_FAILURE);
-        return nullptr;
-    }
-
-    nsINode* rangeParent = pm->GetMouseLocationParent();
-    if (rangeParent && !nsContentUtils::CanCallerAccess(rangeParent)) {
-        aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-        return nullptr;
-    }
-
-    return rangeParent;
+    nsCOMPtr<nsIDOMNode> node;
+    aRv = GetPopupRangeParent(getter_AddRefs(node));
+    nsCOMPtr<nsINode> retval(do_QueryInterface(node));
+    return retval.forget();
 }
 
+
 // Returns the rangeOffset element from the XUL Popup Manager. We check the
 // rangeParent to determine if the caller has rights to access to the data.
+NS_IMETHODIMP
+XULDocument::GetPopupRangeOffset(int32_t* aRangeOffset)
+{
+    ErrorResult rv;
+    *aRangeOffset = GetPopupRangeOffset(rv);
+    return rv.StealNSResult();
+}
+
 int32_t
 XULDocument::GetPopupRangeOffset(ErrorResult& aRv)
 {
     nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
     if (!pm) {
         aRv.Throw(NS_ERROR_FAILURE);
         return 0;
     }
 
-    nsINode* rangeParent = pm->GetMouseLocationParent();
-    if (rangeParent && !nsContentUtils::CanCallerAccess(rangeParent)) {
+    int32_t offset;
+    nsCOMPtr<nsIDOMNode> parent;
+    pm->GetMouseLocation(getter_AddRefs(parent), &offset);
+
+    if (parent && !nsContentUtils::CanCallerAccess(parent)) {
         aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
         return 0;
     }
-
-    return pm->MouseLocationOffset();
+    return offset;
+}
+
+NS_IMETHODIMP
+XULDocument::GetTooltipNode(nsIDOMNode** aNode)
+{
+    *aNode = nullptr;
+
+    nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+    if (pm) {
+        nsCOMPtr<nsIDOMNode> node = pm->GetLastTriggerTooltipNode(this);
+        if (node && nsContentUtils::CanCallerAccess(node))
+            node.forget(aNode);
+    }
+
+    return NS_OK;
 }
 
 already_AddRefed<nsINode>
 XULDocument::GetTooltipNode()
 {
-    nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
-    if (pm) {
-        nsCOMPtr<nsINode> node = pm->GetLastTriggerTooltipNode(this);
-        if (node && nsContentUtils::CanCallerAccess(node)) {
-            return node.forget();
-        }
-    }
-
-    return nullptr;
+    nsCOMPtr<nsIDOMNode> node;
+    DebugOnly<nsresult> rv = GetTooltipNode(getter_AddRefs(node));
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
+    nsCOMPtr<nsINode> retval(do_QueryInterface(node));
+    return retval.forget();
+}
+
+NS_IMETHODIMP
+XULDocument::SetTooltipNode(nsIDOMNode* aNode)
+{
+    // do nothing
+    return NS_OK;
+}
+
+
+NS_IMETHODIMP
+XULDocument::GetCommandDispatcher(nsIDOMXULCommandDispatcher** aTracker)
+{
+    *aTracker = mCommandDispatcher;
+    NS_IF_ADDREF(*aTracker);
+    return NS_OK;
 }
 
 nsresult
 XULDocument::AddElementToDocumentPre(Element* aElement)
 {
     // Do a bunch of work that's necessary when an element gets added
     // to the XUL Document.
     nsresult rv;
@@ -1415,17 +1559,17 @@ XULDocument::AddElementToDocumentPost(El
     if (aElement->NodeInfo()->Equals(nsGkAtoms::keyset, kNameSpaceID_XUL)) {
         // Create our XUL key listener and hook it up.
         nsXBLService::AttachGlobalKeyHandler(aElement);
     }
 
     return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 XULDocument::AddSubtreeToDocument(nsIContent* aContent)
 {
     NS_ASSERTION(aContent->GetUncomposedDoc() == this, "Element not in doc!");
     // From here on we only care about elements.
     if (!aContent->IsElement()) {
         return NS_OK;
     }
 
@@ -1444,17 +1588,17 @@ XULDocument::AddSubtreeToDocument(nsICon
         if (NS_FAILED(rv))
             return rv;
     }
 
     // Do post-order addition magic
     return AddElementToDocumentPost(aElement);
 }
 
-nsresult
+NS_IMETHODIMP
 XULDocument::RemoveSubtreeFromDocument(nsIContent* aContent)
 {
     // From here on we only care about elements.
     if (!aContent->IsElement()) {
         return NS_OK;
     }
 
     Element* aElement = aContent->AsElement();
@@ -2158,54 +2302,44 @@ XULDocument::AddChromeOverlays()
 
         // Same comment as in XULDocument::InsertXULOverlayPI
         mUnloadedOverlays.InsertElementAt(0, uri);
     }
 
     return rv;
 }
 
-void
-XULDocument::LoadOverlay(const nsAString& aURL, nsIObserver* aObserver,
-                         ErrorResult& aRv)
+NS_IMETHODIMP
+XULDocument::LoadOverlay(const nsAString& aURL, nsIObserver* aObserver)
 {
     nsresult rv;
 
     nsCOMPtr<nsIURI> uri;
     rv = NS_NewURI(getter_AddRefs(uri), aURL, nullptr);
-    if (NS_FAILED(rv)) {
-        aRv.Throw(rv);
-        return;
-    }
+    if (NS_FAILED(rv)) return rv;
 
     if (aObserver) {
         nsIObserver* obs = nullptr;
         if (!mOverlayLoadObservers) {
           mOverlayLoadObservers = new nsInterfaceHashtable<nsURIHashKey,nsIObserver>;
         }
         obs = mOverlayLoadObservers->GetWeak(uri);
 
         if (obs) {
             // We don't support loading the same overlay twice into the same
             // document - that doesn't make sense anyway.
-            aRv.Throw(NS_ERROR_FAILURE);
-            return;
+            return NS_ERROR_FAILURE;
         }
         mOverlayLoadObservers->Put(uri, aObserver);
     }
     bool shouldReturn, failureFromContent;
     rv = LoadOverlayInternal(uri, true, &shouldReturn, &failureFromContent);
-    if (NS_FAILED(rv)) {
-        // remove the observer if LoadOverlayInternal generated an error
-        if (mOverlayLoadObservers) {
-            mOverlayLoadObservers->Remove(uri);
-        }
-        aRv.Throw(rv);
-        return;
-    }
+    if (NS_FAILED(rv) && mOverlayLoadObservers)
+        mOverlayLoadObservers->Remove(uri); // remove the observer if LoadOverlayInternal generated an error
+    return rv;
 }
 
 nsresult
 XULDocument::LoadOverlayInternal(nsIURI* aURI, bool aIsDynamic,
                                  bool* aShouldReturn,
                                  bool* aFailureFromContent)
 {
     nsresult rv;
@@ -4140,16 +4274,25 @@ XULDocument::ThreadSafeGetDocumentLWThem
                 theme = Doc_Theme_Dark;
             else if (lwTheme.EqualsLiteral("bright"))
                 theme = Doc_Theme_Bright;
         }
     }
     return theme;
 }
 
+NS_IMETHODIMP
+XULDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult)
+{
+    ErrorResult rv;
+    nsCOMPtr<Element> el = do_QueryInterface(aElement);
+    *aResult = GetBoxObjectFor(el, rv).take();
+    return rv.StealNSResult();
+}
+
 JSObject*
 XULDocument::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return XULDocumentBinding::Wrap(aCx, this, aGivenProto);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/xul/XULDocument.h
+++ b/dom/xul/XULDocument.h
@@ -4,62 +4,63 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_XULDocument_h
 #define mozilla_dom_XULDocument_h
 
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsXULPrototypeDocument.h"
+#include "nsXULPrototypeCache.h"
 #include "nsTArray.h"
 
 #include "mozilla/dom/XMLDocument.h"
 #include "mozilla/StyleSheet.h"
 #include "nsForwardReference.h"
 #include "nsIContent.h"
 #include "nsIDOMXULCommandDispatcher.h"
+#include "nsIDOMXULDocument.h"
 #include "nsCOMArray.h"
 #include "nsIURI.h"
+#include "nsIXULDocument.h"
 #include "nsIStreamListener.h"
 #include "nsIStreamLoader.h"
 #include "nsICSSLoaderObserver.h"
 #include "nsIXULStore.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/ScriptLoader.h"
 
 #include "js/TracingAPI.h"
 #include "js/TypeDecls.h"
 
 class nsIRDFResource;
 class nsIRDFService;
 class nsPIWindowRoot;
-class nsXULPrototypeElement;
 #if 0 // XXXbe save me, scc (need NSCAP_FORWARD_DECL(nsXULPrototypeScript))
 class nsIObjectInputStream;
 class nsIObjectOutputStream;
 #else
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsXULElement.h"
 #endif
 #include "nsURIHashKey.h"
 #include "nsInterfaceHashtable.h"
 
 /**
  * The XUL document class
  */
 
-// Factory function.
-nsresult NS_NewXULDocument(nsIDocument** result);
-
 namespace mozilla {
 namespace dom {
 
 class XULDocument final : public XMLDocument,
+                          public nsIXULDocument,
+                          public nsIDOMXULDocument,
                           public nsIStreamLoaderObserver,
                           public nsICSSLoaderObserver,
                           public nsIOffThreadScriptReceiver
 {
 public:
     XULDocument();
 
     // nsISupports interface
@@ -78,49 +79,27 @@ public:
                                        nsIStreamListener **aDocListener,
                                        bool aReset = true,
                                        nsIContentSink* aSink = nullptr) override;
 
     virtual void SetContentType(const nsAString& aContentType) override;
 
     virtual void EndLoad() override;
 
-    virtual XULDocument* AsXULDocument() override {
-        return this;
-    }
-
     // nsIMutationObserver interface
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
     NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
 
-    /**
-     * Notify the XUL document that a subtree has been added
-     */
-    nsresult AddSubtreeToDocument(nsIContent* aContent);
-    /**
-     * Notify the XUL document that a subtree has been removed
-     */
-    nsresult RemoveSubtreeFromDocument(nsIContent* aContent);
-    /**
-     * This is invoked whenever the prototype for this document is loaded
-     * and should be walked, regardless of whether the XUL cache is
-     * disabled, whether the protototype was loaded, whether the
-     * prototype was loaded from the cache or created by parsing the
-     * actual XUL source, etc.
-     *
-     * @param aResumeWalk whether this should also call ResumeWalk().
-     * Sometimes the caller of OnPrototypeLoadDone resumes the walk itself
-     */
-    nsresult OnPrototypeLoadDone(bool aResumeWalk);
-    /**
-     * Callback notifying when a document could not be parsed properly.
-     */
-    bool OnDocumentParserError();
+    // nsIXULDocument interface
+    NS_IMETHOD AddSubtreeToDocument(nsIContent* aContent) override;
+    NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aContent) override;
+    NS_IMETHOD OnPrototypeLoadDone(bool aResumeWalk) override;
+    bool OnDocumentParserError() override;
 
     // nsINode interface overrides
     virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                            bool aPreallocateChildren) const override;
 
     // nsIDOMDocument interface
     using nsDocument::CreateElement;
     using nsDocument::CreateElementNS;
@@ -129,51 +108,51 @@ public:
     using mozilla::dom::DocumentOrShadowRoot::GetElementById;
     using nsDocument::GetImplementation;
     using nsDocument::GetTitle;
     using nsDocument::SetTitle;
     using nsDocument::GetLastStyleSheetSet;
     using nsDocument::MozSetImageElement;
     using nsIDocument::GetLocation;
 
+    // nsIDOMXULDocument interface
+    NS_DECL_NSIDOMXULDOCUMENT
+
     // nsICSSLoaderObserver
     NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheet* aSheet,
                                 bool aWasAlternate,
                                 nsresult aStatus) override;
 
     virtual void EndUpdate(nsUpdateType aUpdateType) override;
 
     virtual bool IsDocumentRightToLeft() override;
 
-    /**
-     * Reset the document direction so that it is recomputed.
-     */
-    void ResetDocumentDirection();
+    virtual void ResetDocumentDirection() override;
 
     virtual nsIDocument::DocumentTheme GetDocumentLWTheme() override;
     virtual nsIDocument::DocumentTheme ThreadSafeGetDocumentLWTheme() const override;
 
-    void ResetDocumentLWTheme() { mDocLWTheme = Doc_Theme_Uninitialized; }
+    virtual void ResetDocumentLWTheme() override { mDocLWTheme = Doc_Theme_Uninitialized; }
 
     NS_IMETHOD OnScriptCompileComplete(JSScript* aScript, nsresult aStatus) override;
 
     static bool
     MatchAttribute(Element* aContent,
                    int32_t aNameSpaceID,
                    nsAtom* aAttrName,
                    void* aData);
 
     NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XULDocument, XMLDocument)
 
     void TraceProtos(JSTracer* aTrc);
 
     // WebIDL API
     already_AddRefed<nsINode> GetPopupNode();
     void SetPopupNode(nsINode* aNode);
-    nsINode* GetPopupRangeParent(ErrorResult& aRv);
+    already_AddRefed<nsINode> GetPopupRangeParent(ErrorResult& aRv);
     int32_t GetPopupRangeOffset(ErrorResult& aRv);
     already_AddRefed<nsINode> GetTooltipNode();
     void SetTooltipNode(nsINode* aNode) { /* do nothing */ }
     nsIDOMXULCommandDispatcher* GetCommandDispatcher() const
     {
         return mCommandDispatcher;
     }
     int32_t GetWidth(ErrorResult& aRv);
@@ -185,28 +164,33 @@ public:
       GetElementsByAttributeNS(const nsAString& aNamespaceURI,
                                const nsAString& aAttribute,
                                const nsAString& aValue,
                                ErrorResult& aRv);
     void AddBroadcastListenerFor(Element& aBroadcaster, Element& aListener,
                                  const nsAString& aAttr, ErrorResult& aRv);
     void RemoveBroadcastListenerFor(Element& aBroadcaster, Element& aListener,
                                     const nsAString& aAttr);
-    void Persist(const nsAString& aId, const nsAString& aAttr,
-                 ErrorResult& aRv);
+    void Persist(const nsAString& aId, const nsAString& aAttr, ErrorResult& aRv)
+    {
+        aRv = Persist(aId, aAttr);
+    }
     using nsDocument::GetBoxObjectFor;
     void LoadOverlay(const nsAString& aURL, nsIObserver* aObserver,
-                     ErrorResult& aRv);
+                     ErrorResult& aRv)
+    {
+        aRv = LoadOverlay(aURL, aObserver);
+    }
 
 protected:
     virtual ~XULDocument();
 
     // Implementation methods
     friend nsresult
-    (::NS_NewXULDocument(nsIDocument** aResult));
+    (::NS_NewXULDocument(nsIXULDocument** aResult));
 
     nsresult Init(void) override;
     nsresult StartLayout(void);
 
     nsresult GetViewportSize(int32_t* aWidth, int32_t* aHeight);
 
     nsresult PrepareToLoad(nsISupports* aContainer,
                            const char* aCommand,
--- a/dom/xul/moz.build
+++ b/dom/xul/moz.build
@@ -12,16 +12,17 @@ MOCHITEST_MANIFESTS += ['test/mochitest.
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
 if CONFIG['MOZ_XUL']:
     XPIDL_SOURCES += [
         'nsIXULOverlayProvider.idl',
     ]
 
     EXPORTS += [
+        'nsIXULDocument.h',
         'nsXULElement.h',
     ]
 
     UNIFIED_SOURCES += [
         'nsXULCommandDispatcher.cpp',
         'nsXULContentSink.cpp',
         'nsXULContentUtils.cpp',
         'nsXULElement.cpp',
new file mode 100644
--- /dev/null
+++ b/dom/xul/nsIXULDocument.h
@@ -0,0 +1,78 @@
+/* -*- 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/. */
+
+#ifndef nsIXULDocument_h___
+#define nsIXULDocument_h___
+
+#include "nsISupports.h"
+#include "nsString.h"
+#include "nsCOMArray.h"
+
+class nsIXULTemplateBuilder;
+class nsIContent;
+
+namespace mozilla {
+namespace dom {
+class Element;
+}
+}
+
+
+// 81ba4be5-6cc5-478a-9b08-b3e7ed524455
+#define NS_IXULDOCUMENT_IID \
+  {0x81ba4be5, 0x6cc5, 0x478a, {0x9b, 0x08, 0xb3, 0xe7, 0xed, 0x52, 0x44, 0x55}}
+
+
+/*
+ * An XUL-specific extension to nsIDocument. Includes methods for
+ * setting the root resource of the document content model, a factory
+ * method for constructing the children of a node, etc.
+ */
+class nsIXULDocument : public nsISupports
+{
+public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXULDOCUMENT_IID)
+
+  /**
+   * Notify the XUL document that a subtree has been added
+   */
+  NS_IMETHOD AddSubtreeToDocument(nsIContent* aElement) = 0;
+
+  /**
+   * Notify the XUL document that a subtree has been removed
+   */
+  NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aElement) = 0;
+
+  /**
+   * This is invoked whenever the prototype for this document is loaded
+   * and should be walked, regardless of whether the XUL cache is
+   * disabled, whether the protototype was loaded, whether the
+   * prototype was loaded from the cache or created by parsing the
+   * actual XUL source, etc.
+   *
+   * @param aResumeWalk whether this should also call ResumeWalk().
+   * Sometimes the caller of OnPrototypeLoadDone resumes the walk itself
+   */
+  NS_IMETHOD OnPrototypeLoadDone(bool aResumeWalk) = 0;
+
+  /**
+   * Callback notifying when a document could not be parsed properly.
+   */
+  virtual bool OnDocumentParserError() = 0;
+
+  /**
+   * Reset the document direction so that it is recomputed.
+   */
+  virtual void ResetDocumentDirection() = 0;
+
+  virtual void ResetDocumentLWTheme() = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIXULDocument, NS_IXULDOCUMENT_IID)
+
+// factory functions
+nsresult NS_NewXULDocument(nsIXULDocument** result);
+
+#endif // nsIXULDocument_h___
--- a/dom/xul/nsXULContentSink.cpp
+++ b/dom/xul/nsXULContentSink.cpp
@@ -18,25 +18,27 @@
 
 #include "nsCOMPtr.h"
 #include "nsForwardReference.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsIContentSink.h"
 #include "nsIDocument.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMHTMLFormElement.h"
+#include "nsIDOMXULDocument.h"
 #include "nsIFormControl.h"
 #include "mozilla/dom/NodeInfo.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIServiceManager.h"
 #include "nsIURL.h"
 #include "nsNameSpaceManager.h"
 #include "nsParserBase.h"
 #include "nsViewManager.h"
+#include "nsIXULDocument.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsLayoutCID.h"
 #include "nsNetUtil.h"
 #include "nsRDFCID.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsXULElement.h"
 #include "mozilla/Logging.h"
@@ -48,17 +50,16 @@
 #include "nsUnicharUtils.h"
 #include "nsGkAtoms.h"
 #include "nsContentUtils.h"
 #include "nsAttrName.h"
 #include "nsXMLContentSink.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 #include "nsContentTypeParser.h"
-#include "XULDocument.h"
 
 static mozilla::LazyLogModule gContentSinkLog("nsXULContentSink");;
 
 //----------------------------------------------------------------------
 
 XULContentSinkImpl::ContextStack::ContextStack()
     : mTop(nullptr), mDepth(0)
 {
@@ -669,17 +670,17 @@ XULContentSinkImpl::ReportError(const ch
   mTextLength = 0;
 
   // return leaving the document empty if we're asked to not add a <parsererror> root node
   nsCOMPtr<nsIDocument> idoc = do_QueryReferent(mDocument);
   if (idoc && idoc->SuppressParserErrorElement()) {
     return NS_OK;
   };
 
-  XULDocument* doc = idoc ? idoc->AsXULDocument() : nullptr;
+  nsCOMPtr<nsIXULDocument> doc = do_QueryReferent(mDocument);
   if (doc && !doc->OnDocumentParserError()) {
     // The overlay was broken.  Don't add a messy element to the master doc.
     return NS_OK;
   }
 
   const char16_t* noAtts[] = { 0, 0 };
 
   NS_NAMED_LITERAL_STRING(errorNs,
--- a/dom/xul/nsXULContentUtils.cpp
+++ b/dom/xul/nsXULContentUtils.cpp
@@ -15,27 +15,26 @@
 
 #include "nsCollationCID.h"
 #include "nsCOMPtr.h"
 #include "nsIContent.h"
 #include "nsICollation.h"
 #include "nsIDocument.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMXULCommandDispatcher.h"
+#include "nsIDOMXULDocument.h"
 #include "nsIRDFService.h"
 #include "nsIServiceManager.h"
 #include "nsXULContentUtils.h"
 #include "nsLayoutCID.h"
 #include "nsRDFCID.h"
 #include "nsString.h"
 #include "nsGkAtoms.h"
-#include "XULDocument.h"
 
 using namespace mozilla;
-using dom::XULDocument;
 
 //------------------------------------------------------------------------
 
 nsIRDFService* nsXULContentUtils::gRDF;
 nsICollation *nsXULContentUtils::gCollation;
 
 //------------------------------------------------------------------------
 // Constructors n' stuff
@@ -116,23 +115,26 @@ nsXULContentUtils::SetCommandUpdater(nsI
         return NS_ERROR_NULL_POINTER;
 
     NS_PRECONDITION(aElement != nullptr, "null ptr");
     if (! aElement)
         return NS_ERROR_NULL_POINTER;
 
     nsresult rv;
 
-    XULDocument* xuldoc = aDocument->AsXULDocument();
+    nsCOMPtr<nsIDOMXULDocument> xuldoc = do_QueryInterface(aDocument);
     NS_ASSERTION(xuldoc != nullptr, "not a xul document");
     if (! xuldoc)
         return NS_ERROR_UNEXPECTED;
 
-    nsCOMPtr<nsIDOMXULCommandDispatcher> dispatcher =
-        xuldoc->GetCommandDispatcher();
+    nsCOMPtr<nsIDOMXULCommandDispatcher> dispatcher;
+    rv = xuldoc->GetCommandDispatcher(getter_AddRefs(dispatcher));
+    NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get dispatcher");
+    if (NS_FAILED(rv)) return rv;
+
     NS_ASSERTION(dispatcher != nullptr, "no dispatcher");
     if (! dispatcher)
         return NS_ERROR_UNEXPECTED;
 
     nsAutoString events;
     aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::events, events);
     if (events.IsEmpty())
         events.Assign('*');
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -35,16 +35,17 @@
 #include "nsIScriptContext.h"
 #include "nsIScriptError.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIServiceManager.h"
 #include "mozilla/css/StyleRule.h"
 #include "nsIURL.h"
 #include "nsViewManager.h"
 #include "nsIWidget.h"
+#include "nsIXULDocument.h"
 #include "nsLayoutCID.h"
 #include "nsContentCID.h"
 #include "mozilla/dom/Event.h"
 #include "nsStyleConsts.h"
 #include "nsString.h"
 #include "nsXULControllers.h"
 #include "nsIBoxObject.h"
 #include "nsPIBoxObject.h"
@@ -69,16 +70,19 @@
 #include "nsAttrValueOrString.h"
 #include "nsAttrValueInlines.h"
 #include "mozilla/Attributes.h"
 #include "nsIController.h"
 #include "nsQueryObject.h"
 #include <algorithm>
 #include "nsIDOMChromeWindow.h"
 
+// The XUL doc interface
+#include "nsIDOMXULDocument.h"
+
 #include "nsReadableUtils.h"
 #include "nsIFrame.h"
 #include "nsNodeInfoManager.h"
 #include "nsXBLBinding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozAutoDocUpdate.h"
 #include "nsIDOMXULCommandEvent.h"
 #include "nsCCUncollectableMarker.h"
@@ -1146,24 +1150,24 @@ nsXULElement::AfterSetAttr(int32_t aName
                 } else if (aName == nsGkAtoms::drawintitlebar) {
                     SetDrawsInTitlebar(
                         aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
                 } else if (aName == nsGkAtoms::drawtitle) {
                     SetDrawsTitle(
                         aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
                 } else if (aName == nsGkAtoms::localedir) {
                     // if the localedir changed on the root element, reset the document direction
-                    XULDocument* xuldoc = document->AsXULDocument();
+                    nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(document);
                     if (xuldoc) {
                         xuldoc->ResetDocumentDirection();
                     }
                 } else if (aName == nsGkAtoms::lwtheme ||
                          aName == nsGkAtoms::lwthemetextcolor) {
                     // if the lwtheme changed, make sure to reset the document lwtheme cache
-                    XULDocument* xuldoc = document->AsXULDocument();
+                    nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(document);
                     if (xuldoc) {
                         xuldoc->ResetDocumentLWTheme();
                         UpdateBrightTitlebarForeground(document);
                     }
                 } else if (aName == nsGkAtoms::brighttitlebarforeground) {
                     UpdateBrightTitlebarForeground(document);
                 }
             }
@@ -1183,24 +1187,24 @@ nsXULElement::AfterSetAttr(int32_t aName
             nsIDocument* doc = GetUncomposedDoc();
             if (doc && doc->GetRootElement() == this) {
                 if ((aName == nsGkAtoms::activetitlebarcolor ||
                      aName == nsGkAtoms::inactivetitlebarcolor)) {
                     // Use 0, 0, 0, 0 as the "none" color.
                     SetTitlebarColor(NS_RGBA(0, 0, 0, 0), aName == nsGkAtoms::activetitlebarcolor);
                 } else if (aName == nsGkAtoms::localedir) {
                     // if the localedir changed on the root element, reset the document direction
-                    XULDocument* xuldoc = doc->AsXULDocument();
+                    nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(doc);
                     if (xuldoc) {
                         xuldoc->ResetDocumentDirection();
                     }
                 } else if ((aName == nsGkAtoms::lwtheme ||
                             aName == nsGkAtoms::lwthemetextcolor)) {
                     // if the lwtheme changed, make sure to restyle appropriately
-                    XULDocument* xuldoc = doc->AsXULDocument();
+                    nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(doc);
                     if (xuldoc) {
                         xuldoc->ResetDocumentLWTheme();
                         UpdateBrightTitlebarForeground(doc);
                     }
                 } else if (aName == nsGkAtoms::brighttitlebarforeground) {
                     UpdateBrightTitlebarForeground(doc);
                 } else if (aName == nsGkAtoms::drawintitlebar) {
                     SetDrawsInTitlebar(false);
@@ -1233,22 +1237,24 @@ nsXULElement::ParseAttribute(int32_t aNa
     }
 
     return true;
 }
 
 void
 nsXULElement::RemoveBroadcaster(const nsAString & broadcasterId)
 {
-    XULDocument* xuldoc = OwnerDoc()->AsXULDocument();
+    nsCOMPtr<nsIDOMXULDocument> xuldoc = do_QueryInterface(OwnerDoc());
     if (xuldoc) {
-        Element* broadcaster = xuldoc->GetElementById(broadcasterId);
+        nsCOMPtr<nsIDOMElement> broadcaster;
+        nsCOMPtr<nsIDOMDocument> domDoc (do_QueryInterface(xuldoc));
+        domDoc->GetElementById(broadcasterId, getter_AddRefs(broadcaster));
         if (broadcaster) {
-            xuldoc->RemoveBroadcastListenerFor(*broadcaster, *this,
-                                               NS_LITERAL_STRING("*"));
+            xuldoc->RemoveBroadcastListenerFor(broadcaster, this,
+              NS_LITERAL_STRING("*"));
         }
     }
 }
 
 void
 nsXULElement::DestroyContent()
 {
     nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
--- a/dom/xul/nsXULPopupListener.cpp
+++ b/dom/xul/nsXULPopupListener.cpp
@@ -16,16 +16,17 @@
 #include "nsIDOMNodeList.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentXBL.h"
 #include "nsContentCID.h"
 #include "nsContentUtils.h"
 #include "nsXULPopupManager.h"
 #include "nsIScriptContext.h"
 #include "nsIDOMWindow.h"
+#include "nsIDOMXULDocument.h"
 #include "nsIDocument.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsLayoutUtils.h"
 #include "mozilla/ReflowInput.h"
 #include "nsIObjectLoadingContent.h"
 #include "mozilla/EventStateManager.h"
--- a/dom/xul/nsXULPrototypeDocument.h
+++ b/dom/xul/nsXULPrototypeDocument.h
@@ -99,17 +99,17 @@ public:
      * Otherwise sets aLoaded to true.
      */
     nsresult AwaitLoadDone(mozilla::dom::XULDocument* aDocument, bool* aResult);
 
     /**
      * Notifies each document registered via AwaitLoadDone on this
      * prototype document that the prototype has finished loading.
      * The notification is performed by calling
-     * XULDocument::OnPrototypeLoadDone on the registered documents.
+     * nsIXULDocument::OnPrototypeLoadDone on the registered documents.
      */
     nsresult NotifyLoadDone();
 
     nsNodeInfoManager *GetNodeInfoManager();
 
     void MarkInCCGeneration(uint32_t aCCGeneration);
 
     NS_DECL_CYCLE_COLLECTION_CLASS(nsXULPrototypeDocument)
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -59,16 +59,17 @@
 #include "nsDocShell.h"
 #include "nsIBaseWindow.h"
 #include "nsILayoutHistoryState.h"
 #include "nsCharsetSource.h"
 #include "mozilla/ReflowInput.h"
 #include "nsIImageLoadingContent.h"
 #include "nsCopySupport.h"
 #ifdef MOZ_XUL
+#include "nsIXULDocument.h"
 #include "nsXULPopupManager.h"
 #endif
 
 #include "nsIClipboardHelper.h"
 
 #include "nsPIDOMWindow.h"
 #include "nsGlobalWindow.h"
 #include "nsDOMNavigationTiming.h"
@@ -275,19 +276,19 @@ private:
                         bool aNeedMakeCX = true,
                         bool aForceSetNewDocument = true);
   /**
    * @param aDoInitialReflow set to true if you want to kick off the initial
    * reflow
    */
   nsresult InitPresentationStuff(bool aDoInitialReflow);
 
-  already_AddRefed<nsINode> GetPopupNode();
-  already_AddRefed<nsINode> GetPopupLinkNode();
-  already_AddRefed<nsIImageLoadingContent> GetPopupImageNode();
+  nsresult GetPopupNode(nsIDOMNode** aNode);
+  nsresult GetPopupLinkNode(nsIDOMNode** aNode);
+  nsresult GetPopupImageNode(nsIImageLoadingContent** aNode);
 
   nsresult GetContentSizeInternal(int32_t* aWidth, int32_t* aHeight,
                                   nscoord aMaxWidth, nscoord aMaxHeight);
 
   void PrepareToStartLoad(void);
 
   nsresult SyncParentSubDocMap();
 
@@ -2755,17 +2756,18 @@ NS_IMETHODIMP nsDocumentViewer::CopySele
   nsCopySupport::FireClipboardEvent(eCopy, nsIClipboard::kGlobalClipboard,
                                     mPresShell, nullptr);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDocumentViewer::CopyLinkLocation()
 {
   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
-  nsCOMPtr<nsINode> node = GetPopupLinkNode();
+  nsCOMPtr<nsIDOMNode> node;
+  GetPopupLinkNode(getter_AddRefs(node));
   // make noise if we're not in a link
   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
 
   nsCOMPtr<dom::Element> elm(do_QueryInterface(node));
   NS_ENSURE_TRUE(elm, NS_ERROR_FAILURE);
 
   nsAutoString locationText;
   nsContentUtils::GetLinkLocation(elm, locationText);
@@ -2778,17 +2780,18 @@ NS_IMETHODIMP nsDocumentViewer::CopyLink
 
   // copy the href onto the clipboard
   return clipboard->CopyString(locationText);
 }
 
 NS_IMETHODIMP nsDocumentViewer::CopyImage(int32_t aCopyFlags)
 {
   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
-  nsCOMPtr<nsIImageLoadingContent> node = GetPopupImageNode();
+  nsCOMPtr<nsIImageLoadingContent> node;
+  GetPopupImageNode(getter_AddRefs(node));
   // make noise if we're not in an image
   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsILoadContext> loadContext(mContainer);
   return nsCopySupport::ImageCopy(node, loadContext, aCopyFlags);
 }
 
 
@@ -2838,18 +2841,17 @@ NS_IMETHODIMP nsDocumentViewer::SetComma
   NS_ENSURE_STATE(document);
 
   nsCOMPtr<nsPIDOMWindowOuter> window(document->GetWindow());
   NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE);
 
   nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
   NS_ENSURE_STATE(root);
 
-  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-  root->SetPopupNode(node);
+  root->SetPopupNode(aNode);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDocumentViewer::ScrollToNode(nsIDOMNode* aNode)
 {
   NS_ENSURE_ARG(aNode);
   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
   nsCOMPtr<nsIPresShell> presShell;
@@ -3605,85 +3607,110 @@ nsresult nsDocViewerSelectionListener::I
  * GetPopupNode, GetPopupLinkNode and GetPopupImageNode are helpers
  * for the cmd_copyLink / cmd_copyImageLocation / cmd_copyImageContents family
  * of commands. The focus controller stores the popup node, these retrieve
  * them and munge appropriately. Note that we have to store the popup node
  * rather than retrieving it from EventStateManager::GetFocusedContent because
  * not all content (images included) can receive focus.
  */
 
-already_AddRefed<nsINode>
-nsDocumentViewer::GetPopupNode()
+nsresult
+nsDocumentViewer::GetPopupNode(nsIDOMNode** aNode)
 {
+  NS_ENSURE_ARG_POINTER(aNode);
+
+  *aNode = nullptr;
+
   // get the document
   nsIDocument* document = GetDocument();
-  NS_ENSURE_TRUE(document, nullptr);
+  NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
 
   // get the private dom window
   nsCOMPtr<nsPIDOMWindowOuter> window(document->GetWindow());
-  NS_ENSURE_TRUE(window, nullptr);
+  NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE);
   if (window) {
     nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
-    NS_ENSURE_TRUE(root, nullptr);
+    NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
 
     // get the popup node
-    nsCOMPtr<nsINode> node = root->GetPopupNode();
+    nsCOMPtr<nsIDOMNode> node = root->GetPopupNode();
 #ifdef MOZ_XUL
     if (!node) {
       nsPIDOMWindowOuter* rootWindow = root->GetWindow();
       if (rootWindow) {
         nsCOMPtr<nsIDocument> rootDoc = rootWindow->GetExtantDoc();
         if (rootDoc) {
           nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
           if (pm) {
             node = pm->GetLastTriggerPopupNode(rootDoc);
           }
         }
       }
     }
 #endif
-    return node.forget();
+    node.swap(*aNode);
   }
 
-  return nullptr;
+  return NS_OK;
 }
 
 // GetPopupLinkNode: return popup link node or fail
-already_AddRefed<nsINode>
-nsDocumentViewer::GetPopupLinkNode()
+nsresult
+nsDocumentViewer::GetPopupLinkNode(nsIDOMNode** aNode)
 {
+  NS_ENSURE_ARG_POINTER(aNode);
+
+  // you get null unless i say so
+  *aNode = nullptr;
+
   // find popup node
-  nsCOMPtr<nsINode> node = GetPopupNode();
+  nsCOMPtr<nsIDOMNode> domNode;
+  nsresult rv = GetPopupNode(getter_AddRefs(domNode));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsINode> node = do_QueryInterface(domNode);
 
   // find out if we have a link in our ancestry
   while (node) {
     nsCOMPtr<nsIContent> content(do_QueryInterface(node));
     if (content) {
       nsCOMPtr<nsIURI> hrefURI = content->GetHrefURI();
       if (hrefURI) {
-        return node.forget();
+        *aNode = node->AsDOMNode();
+        NS_IF_ADDREF(*aNode); // addref
+        return NS_OK;
       }
     }
 
     // get our parent and keep trying...
     node = node->GetParentNode();
   }
 
   // if we have no node, fail
-  return nullptr;
+  return NS_ERROR_FAILURE;
 }
 
 // GetPopupLinkNode: return popup image node or fail
-already_AddRefed<nsIImageLoadingContent>
-nsDocumentViewer::GetPopupImageNode()
+nsresult
+nsDocumentViewer::GetPopupImageNode(nsIImageLoadingContent** aNode)
 {
+  NS_ENSURE_ARG_POINTER(aNode);
+
+  // you get null unless i say so
+  *aNode = nullptr;
+
   // find popup node
-  nsCOMPtr<nsINode> node = GetPopupNode();
-  nsCOMPtr<nsIImageLoadingContent> img = do_QueryInterface(node);
-  return img.forget();
+  nsCOMPtr<nsIDOMNode> node;
+  nsresult rv = GetPopupNode(getter_AddRefs(node));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (node)
+    CallQueryInterface(node, aNode);
+
+  return NS_OK;
 }
 
 /*
  * XXX dr
  * ------
  * These two functions -- GetInLink and GetInImage -- are kind of annoying
  * in that they only get called from the controller (in
  * nsDOMWindowController::IsCommandEnabled). The actual construction of the
@@ -3699,17 +3726,19 @@ NS_IMETHODIMP nsDocumentViewer::GetInLin
 #endif
 
   NS_ENSURE_ARG_POINTER(aInLink);
 
   // we're not in a link unless i say so
   *aInLink = false;
 
   // get the popup link
-  nsCOMPtr<nsINode> node = GetPopupLinkNode();
+  nsCOMPtr<nsIDOMNode> node;
+  nsresult rv = GetPopupLinkNode(getter_AddRefs(node));
+  if (NS_FAILED(rv)) return rv;
   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
 
   // if we made it here, we're in a link
   *aInLink = true;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDocumentViewer::GetInImage(bool* aInImage)
@@ -3719,17 +3748,19 @@ NS_IMETHODIMP nsDocumentViewer::GetInIma
 #endif
 
   NS_ENSURE_ARG_POINTER(aInImage);
 
   // we're not in an image unless i say so
   *aInImage = false;
 
   // get the popup image
-  nsCOMPtr<nsIImageLoadingContent> node = GetPopupImageNode();
+  nsCOMPtr<nsIImageLoadingContent> node;
+  nsresult rv = GetPopupImageNode(getter_AddRefs(node));
+  if (NS_FAILED(rv)) return rv;
   if (!node) {
     return NS_ERROR_FAILURE;
   }
 
   // Make sure there is a URI assigned. This allows <input type="image"> to
   // be an image but rejects other <input> types. This matches what
   // nsContextMenu.js does.
   nsCOMPtr<nsIURI> uri;
@@ -3834,17 +3865,18 @@ nsDocViewerFocusListener::Init(nsDocumen
 
 #ifdef NS_PRINTING
 
 NS_IMETHODIMP
 nsDocumentViewer::Print(nsIPrintSettings*       aPrintSettings,
                           nsIWebProgressListener* aWebProgressListener)
 {
   // Printing XUL documents is not supported.
-  if (mDocument && mDocument->IsXULDocument()) {
+  nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
+  if (xulDoc) {
     return NS_ERROR_FAILURE;
   }
 
   if (!mContainer) {
     PR_PL(("Container was destroyed yet we are still trying to use it!"));
     return NS_ERROR_FAILURE;
   }
 
@@ -3949,17 +3981,18 @@ nsDocumentViewer::PrintPreview(nsIPrintS
   nsresult rv = NS_OK;
 
   if (GetIsPrinting()) {
     nsPrintJob::CloseProgressDialog(aWebProgressListener);
     return NS_ERROR_FAILURE;
   }
 
   // Printing XUL documents is not supported.
-  if (mDocument && mDocument->IsXULDocument()) {
+  nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
+  if (xulDoc) {
     nsPrintJob::CloseProgressDialog(aWebProgressListener);
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIDocShell> docShell(mContainer);
   if (!docShell || !mDeviceContext) {
     PR_PL(("Can't Print Preview without device context and docshell"));
     return NS_ERROR_FAILURE;
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -139,17 +139,17 @@ class nsIDocumentLoaderFactory;
 
 #ifdef MOZ_XUL
 #include "inDOMView.h"
 #endif /* MOZ_XUL */
 
 #include "inDeepTreeWalker.h"
 
 #ifdef MOZ_XUL
-#include "XULDocument.h"
+#include "nsIXULDocument.h"
 #include "nsIXULSortService.h"
 #endif
 
 static void Shutdown();
 
 #include "nsGeolocation.h"
 #include "nsDeviceSensors.h"
 #include "mozilla/dom/nsContentSecurityManager.h"
@@ -426,17 +426,17 @@ MAKE_CTOR(CreateTextEncoder,            
 MAKE_CTOR(CreateHTMLCopyTextEncoder,      nsIDocumentEncoder,          NS_NewHTMLCopyTextEncoder)
 MAKE_CTOR(CreateXMLContentSerializer,     nsIContentSerializer,        NS_NewXMLContentSerializer)
 MAKE_CTOR(CreateHTMLContentSerializer,    nsIContentSerializer,        NS_NewHTMLContentSerializer)
 MAKE_CTOR(CreateXHTMLContentSerializer,   nsIContentSerializer,        NS_NewXHTMLContentSerializer)
 MAKE_CTOR(CreatePlainTextSerializer,      nsIContentSerializer,        NS_NewPlainTextSerializer)
 MAKE_CTOR(CreateContentPolicy,            nsIContentPolicy,            NS_NewContentPolicy)
 #ifdef MOZ_XUL
 MAKE_CTOR(CreateXULSortService,           nsIXULSortService,           NS_NewXULSortService)
-MAKE_CTOR(CreateXULDocument,              nsIDocument,                 NS_NewXULDocument)
+MAKE_CTOR(CreateXULDocument,              nsIXULDocument,              NS_NewXULDocument)
 // NS_NewXULControllers
 #endif
 MAKE_CTOR(CreateContentDLF,               nsIDocumentLoaderFactory,    NS_NewContentDocumentLoaderFactory)
 MAKE_CTOR(CreateEventListenerService,     nsIEventListenerService,     NS_NewEventListenerService)
 MAKE_CTOR(CreateGlobalMessageManager,     nsIMessageBroadcaster,       NS_NewGlobalMessageManager)
 MAKE_CTOR(CreateParentMessageManager,     nsIMessageBroadcaster,       NS_NewParentProcessMessageManager)
 MAKE_CTOR(CreateChildMessageManager,      nsISyncMessageSender,        NS_NewChildProcessMessageManager)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDataDocumentContentPolicy)
@@ -955,16 +955,17 @@ static const mozilla::Module::ContractID
   { NS_PARSERUTILS_CONTRACTID, &kNS_PARSERUTILS_CID },
   { NS_SCRIPTABLEUNESCAPEHTML_CONTRACTID, &kNS_SCRIPTABLEUNESCAPEHTML_CID },
   { NS_CONTENTPOLICY_CONTRACTID, &kNS_CONTENTPOLICY_CID },
   { NS_DATADOCUMENTCONTENTPOLICY_CONTRACTID, &kNS_DATADOCUMENTCONTENTPOLICY_CID },
   { NS_NODATAPROTOCOLCONTENTPOLICY_CONTRACTID, &kNS_NODATAPROTOCOLCONTENTPOLICY_CID },
   { "@mozilla.org/xul/xul-controllers;1", &kNS_XULCONTROLLERS_CID },
 #ifdef MOZ_XUL
   { "@mozilla.org/xul/xul-sort-service;1", &kNS_XULSORTSERVICE_CID },
+  { "@mozilla.org/xul/xul-document;1", &kNS_XULDOCUMENT_CID },
 #endif
   { CONTENT_DLF_CONTRACTID, &kNS_CONTENT_DOCUMENT_LOADER_FACTORY_CID },
   { NS_JSPROTOCOLHANDLER_CONTRACTID, &kNS_JSPROTOCOLHANDLER_CID },
   { NS_WINDOWCONTROLLER_CONTRACTID, &kNS_WINDOWCONTROLLER_CID },
   { PLUGIN_DLF_CONTRACTID, &kNS_PLUGINDOCLOADERFACTORY_CID },
   { NS_STYLESHEETSERVICE_CONTRACTID, &kNS_STYLESHEETSERVICE_CID },
   { TRANSFORMIIX_XSLT_PROCESSOR_CONTRACTID, &kTRANSFORMIIX_XSLT_PROCESSOR_CID },
   { NS_XPATH_EVALUATOR_CONTRACTID, &kTRANSFORMIIX_XPATH_EVALUATOR_CID },
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -10,16 +10,18 @@
 #include "nsMenuPopupFrame.h"
 #include "nsMenuBarFrame.h"
 #include "nsMenuBarListener.h"
 #include "nsContentUtils.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMEvent.h"
 #include "nsXULElement.h"
 #include "nsIDOMXULMenuListElement.h"
+#include "nsIXULDocument.h"
+#include "nsIDOMXULDocument.h"
 #include "nsIDOMXULCommandDispatcher.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsGlobalWindow.h"
 #include "nsLayoutUtils.h"
 #include "nsViewManager.h"
 #include "nsIComponentManager.h"
 #include "nsITimer.h"
 #include "nsFocusManager.h"
@@ -29,20 +31,18 @@
 #include "nsIBaseWindow.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsCaret.h"
 #include "nsIDocument.h"
 #include "nsPIWindowRoot.h"
 #include "nsFrameManager.h"
 #include "nsIObserverService.h"
-#include "XULDocument.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
-#include "mozilla/dom/UIEvent.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Services.h"
 #include "mozilla/widget/nsAutoRollup.h"
 
 using namespace mozilla;
@@ -594,26 +594,22 @@ nsXULPopupManager::GetTopVisibleMenu()
       return item;
     }
     item = item->GetParent();
   }
 
   return nullptr;
 }
 
-nsINode*
-nsXULPopupManager::GetMouseLocationParent()
+void
+nsXULPopupManager::GetMouseLocation(nsIDOMNode** aNode, int32_t* aOffset)
 {
-  return mRangeParent;
-}
-
-int32_t
-nsXULPopupManager::MouseLocationOffset()
-{
-  return mRangeOffset;
+  *aNode = mRangeParent;
+  NS_IF_ADDREF(*aNode);
+  *aOffset = mRangeOffset;
 }
 
 void
 nsXULPopupManager::InitTriggerEvent(nsIDOMEvent* aEvent, nsIContent* aPopup,
                                     nsIContent** aTriggerContent)
 {
   mCachedMousePoint = LayoutDeviceIntPoint(0, 0);
 
@@ -624,21 +620,20 @@ nsXULPopupManager::InitTriggerEvent(nsID
       nsCOMPtr<nsIContent> target = do_QueryInterface(
         aEvent->InternalDOMEvent()->GetTarget());
       target.forget(aTriggerContent);
     }
   }
 
   mCachedModifiers = 0;
 
-  nsCOMPtr<nsIDOMUIEvent> domUiEvent = do_QueryInterface(aEvent);
-  if (domUiEvent) {
-    auto uiEvent = static_cast<UIEvent*>(domUiEvent.get())
-    mRangeParent = uiEvent->GetRangeParent();
-    mRangeOffset = uiEvent->RangeOffset();
+  nsCOMPtr<nsIDOMUIEvent> uiEvent = do_QueryInterface(aEvent);
+  if (uiEvent) {
+    uiEvent->GetRangeParent(getter_AddRefs(mRangeParent));
+    uiEvent->GetRangeOffset(&mRangeOffset);
 
     // get the event coordinates relative to the root frame of the document
     // containing the popup.
     NS_ASSERTION(aPopup, "Expected a popup node");
     WidgetEvent* event = aEvent->WidgetEventPtr();
     if (event) {
       WidgetInputEvent* inputEvent = event->AsInputEvent();
       if (inputEvent) {
@@ -1706,38 +1701,38 @@ nsXULPopupManager::GetVisiblePopups(nsTA
     if (item->Frame()->IsVisible() && !item->Frame()->IsMouseTransparent()) {
       aPopups.AppendElement(item->Frame());
     }
 
     item = item->GetParent();
   }
 }
 
-already_AddRefed<nsINode>
+already_AddRefed<nsIDOMNode>
 nsXULPopupManager::GetLastTriggerNode(nsIDocument* aDocument, bool aIsTooltip)
 {
   if (!aDocument)
     return nullptr;
 
-  nsCOMPtr<nsINode> node;
+  nsCOMPtr<nsIDOMNode> node;
 
   // if mOpeningPopup is set, it means that a popupshowing event is being
   // fired. In this case, just use the cached node, as the popup is not yet in
   // the list of open popups.
   if (mOpeningPopup && mOpeningPopup->GetUncomposedDoc() == aDocument &&
       aIsTooltip == mOpeningPopup->IsXULElement(nsGkAtoms::tooltip)) {
-    node = nsMenuPopupFrame::GetTriggerContent(GetPopupFrameForContent(mOpeningPopup, false));
+    node = do_QueryInterface(nsMenuPopupFrame::GetTriggerContent(GetPopupFrameForContent(mOpeningPopup, false)));
   }
   else {
     nsMenuChainItem* item = mPopups;
     while (item) {
       // look for a popup of the same type and document.
       if ((item->PopupType() == ePopupTypeTooltip) == aIsTooltip &&
           item->Content()->GetUncomposedDoc() == aDocument) {
-        node = nsMenuPopupFrame::GetTriggerContent(item->Frame());
+        node = do_QueryInterface(nsMenuPopupFrame::GetTriggerContent(item->Frame()));
         if (node)
           break;
       }
       item = item->GetParent();
     }
   }
 
   return node.forget();
@@ -1972,20 +1967,20 @@ nsXULPopupManager::UpdateMenuItems(nsICo
   // command attribute. If so, then several attributes must potentially be updated.
 
   nsCOMPtr<nsIDocument> document = aPopup->GetUncomposedDoc();
   if (!document) {
     return;
   }
 
   // When a menu is opened, make sure that command updating is unlocked first.
-  XULDocument* xulDoc = document->AsXULDocument();
+  nsCOMPtr<nsIDOMXULDocument> xulDoc = do_QueryInterface(document);
   if (xulDoc) {
-    nsCOMPtr<nsIDOMXULCommandDispatcher> xulCommandDispatcher =
-      xulDoc->GetCommandDispatcher();
+    nsCOMPtr<nsIDOMXULCommandDispatcher> xulCommandDispatcher;
+    xulDoc->GetCommandDispatcher(getter_AddRefs(xulCommandDispatcher));
     if (xulCommandDispatcher) {
       xulCommandDispatcher->Unlock();
     }
   }
 
   for (nsCOMPtr<nsIContent> grandChild = aPopup->GetFirstChild();
        grandChild;
        grandChild = grandChild->GetNextSibling()) {
--- a/layout/xul/nsXULPopupManager.h
+++ b/layout/xul/nsXULPopupManager.h
@@ -417,20 +417,19 @@ public:
   // when the active menu bar should be defocused. In the latter case, if
   // aMenuBar isn't currently active, yet another menu bar is, that menu bar
   // will remain active.
   void SetActiveMenuBar(nsMenuBarFrame* aMenuBar, bool aActivate);
 
   // retrieve the node and offset of the last mouse event used to open a
   // context menu. This information is determined from the rangeParent and
   // the rangeOffset of the event supplied to ShowPopup or ShowPopupAtScreen.
-  // This is used by the implementation of XULDocument::GetPopupRangeParent
-  // and XULDocument::GetPopupRangeOffset.
-  nsINode* GetMouseLocationParent();
-  int32_t MouseLocationOffset();
+  // This is used by the implementation of nsIDOMXULDocument::GetPopupRangeParent
+  // and nsIDOMXULDocument::GetPopupRangeOffset.
+  void GetMouseLocation(nsIDOMNode** aNode, int32_t* aOffset);
 
   /**
    * Open a <menu> given its content node. If aSelectFirstItem is
    * set to true, the first item on the menu will automatically be
    * selected. If aAsynchronous is true, the event will be dispatched
    * asynchronously. This should be true when called from frame code.
    */
   void ShowMenu(nsIContent *aMenu, bool aSelectFirstItem, bool aAsynchronous);
@@ -592,22 +591,22 @@ public:
    */
   void GetVisiblePopups(nsTArray<nsIFrame *>& aPopups);
 
   /**
    * Get the node that last triggered a popup or tooltip in the document
    * aDocument. aDocument must be non-null and be a document contained within
    * the same window hierarchy as the popup to retrieve.
    */
-  already_AddRefed<nsINode> GetLastTriggerPopupNode(nsIDocument* aDocument)
+  already_AddRefed<nsIDOMNode> GetLastTriggerPopupNode(nsIDocument* aDocument)
   {
     return GetLastTriggerNode(aDocument, false);
   }
 
-  already_AddRefed<nsINode> GetLastTriggerTooltipNode(nsIDocument* aDocument)
+  already_AddRefed<nsIDOMNode> GetLastTriggerTooltipNode(nsIDocument* aDocument)
   {
     return GetLastTriggerNode(aDocument, true);
   }
 
   /**
    * Return false if a popup may not be opened. This will return false if the
    * popup is already open, if the popup is in a content shell that is not
    * focused, or if it is a submenu of another menu that isn't open.
@@ -794,17 +793,17 @@ private:
    * handled and other default handling should not occur.
    */
   bool HandleKeyboardNavigationInPopup(nsMenuChainItem* aItem,
                                          nsMenuPopupFrame* aFrame,
                                          nsNavigationDirection aDir);
 
 protected:
 
-  already_AddRefed<nsINode> GetLastTriggerNode(nsIDocument* aDocument, bool aIsTooltip);
+  already_AddRefed<nsIDOMNode> GetLastTriggerNode(nsIDocument* aDocument, bool aIsTooltip);
 
   /**
    * Set mouse capturing for the current popup. This traps mouse clicks that
    * occur outside the popup so that it can be closed up. aOldPopup should be
    * set to the popup that was previously the current popup.
    */
   void SetCaptureState(nsIContent *aOldPopup);
 
@@ -828,17 +827,17 @@ protected:
 
   // the document the key event listener is attached to
   nsCOMPtr<mozilla::dom::EventTarget> mKeyListener;
 
   // widget that is currently listening to rollup events
   nsCOMPtr<nsIWidget> mWidget;
 
   // range parent and offset set in SetTriggerEvent
-  nsCOMPtr<nsINode> mRangeParent;
+  nsCOMPtr<nsIDOMNode> mRangeParent;
   int32_t mRangeOffset;
   // Device pixels relative to the showing popup's presshell's
   // root prescontext's root frame.
   mozilla::LayoutDeviceIntPoint mCachedMousePoint;
 
   // cached modifiers
   mozilla::Modifiers mCachedModifiers;
 
--- a/layout/xul/nsXULTooltipListener.cpp
+++ b/layout/xul/nsXULTooltipListener.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "nsXULTooltipListener.h"
 
 #include "nsIDOMMouseEvent.h"
+#include "nsIDOMXULDocument.h"
 #include "nsXULElement.h"
 #include "nsIDocument.h"
 #include "nsGkAtoms.h"
 #include "nsMenuPopupFrame.h"
 #include "nsIServiceManager.h"
 #include "nsIDragService.h"
 #include "nsIDragSession.h"
 #ifdef MOZ_XUL
@@ -97,22 +98,22 @@ nsXULTooltipListener::MouseOut(nsIDOMEve
     return;
 #endif
 
 #ifdef MOZ_XUL
   // check to see if the mouse left the targetNode, and if so,
   // hide the tooltip
   if (currentTooltip) {
     // which node did the mouse leave?
-    nsCOMPtr<nsINode> targetNode = do_QueryInterface(
+    nsCOMPtr<nsIDOMNode> targetNode = do_QueryInterface(
       aEvent->InternalDOMEvent()->GetTarget());
 
     nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
     if (pm) {
-      nsCOMPtr<nsINode> tooltipNode =
+      nsCOMPtr<nsIDOMNode> tooltipNode =
         pm->GetLastTriggerTooltipNode(currentTooltip->GetUncomposedDoc());
       if (tooltipNode == targetNode) {
         // if the target node is the current tooltip target node, the mouse
         // left the node the tooltip appeared on, so close the tooltip.
         HideTooltip();
         // reset special tree tracking
         if (mIsSourceTree) {
           mLastTreeRow = -1;
@@ -398,18 +399,19 @@ nsXULTooltipListener::ShowTooltip()
 
   // get the tooltip content designated for the target node
   nsCOMPtr<nsIContent> tooltipNode;
   GetTooltipFor(sourceNode, getter_AddRefs(tooltipNode));
   if (!tooltipNode || sourceNode == tooltipNode)
     return NS_ERROR_FAILURE; // the target node doesn't need a tooltip
 
   // set the node in the document that triggered the tooltip and show it
-  if (tooltipNode->GetComposedDoc() &&
-      tooltipNode->GetComposedDoc()->IsXULDocument()) {
+  nsCOMPtr<nsIDOMXULDocument> xulDoc =
+    do_QueryInterface(tooltipNode->GetComposedDoc());
+  if (xulDoc) {
     // Make sure the target node is still attached to some document.
     // It might have been deleted.
     if (sourceNode->IsInComposedDoc()) {
 #ifdef MOZ_XUL
       if (!mIsSourceTree) {
         mLastTreeRow = -1;
         mLastTreeCol = nullptr;
       }
--- a/toolkit/content/widgets/textbox.xml
+++ b/toolkit/content/widgets/textbox.xml
@@ -514,17 +514,17 @@
       </field>
 
       <property name="spellCheckerUI" readonly="true">
         <getter><![CDATA[
           if (!this._spellCheckInitialized) {
             this._spellCheckInitialized = true;
 
             const CI = Components.interfaces;
-            if (ChromeUtils.getClassName(document) != "XULDocument")
+            if (!(document instanceof CI.nsIDOMXULDocument))
               return null;
 
             var textbox = document.getBindingParent(this);
             if (!textbox || !(textbox instanceof CI.nsIDOMXULTextBoxElement))
               return null;
 
             try {
               ChromeUtils.import("resource://gre/modules/InlineSpellChecker.jsm", this);
--- a/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
+++ b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
@@ -68,16 +68,17 @@
 #include "nsIDOMTreeWalker.h"
 #include "nsIDOMUIEvent.h"
 #include "nsIDOMValidityState.h"
 #include "nsIDOMWheelEvent.h"
 #include "nsIDOMXMLDocument.h"
 #include "nsIDOMXPathEvaluator.h"
 #include "nsIDOMXPathResult.h"
 #include "nsIDOMXULCommandEvent.h"
+#include "nsIDOMXULDocument.h"
 #include "nsIDOMXULElement.h"
 #include "nsIFrameLoader.h"
 #include "nsIListBoxObject.h"
 #include "nsIMenuBoxObject.h"
 #include "nsIScrollBoxObject.h"
 #include "nsISelection.h"
 #include "nsITreeBoxObject.h"
 #include "nsIWebBrowserPersistable.h"
@@ -300,16 +301,17 @@ const ComponentsInterfaceShimEntry kComp
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIWebBrowserPersistable, FrameLoader),
   DEFINE_SHIM(WheelEvent),
   DEFINE_SHIM(XMLDocument),
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIXMLHttpRequestEventTarget, XMLHttpRequestEventTarget),
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIXMLHttpRequestUpload, XMLHttpRequestUpload),
   DEFINE_SHIM(XPathEvaluator),
   DEFINE_SHIM(XPathResult),
   DEFINE_SHIM(XULCommandEvent),
+  DEFINE_SHIM(XULDocument),
   DEFINE_SHIM(XULElement),
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsISelection, Selection),
 };
 
 #undef DEFINE_SHIM
 #undef DEFINE_SHIM_WITH_CUSTOM_INTERFACE
 
 NS_IMPL_ISUPPORTS(ShimInterfaceInfo, nsISupports, nsIInterfaceInfo)
--- a/xpfe/appshell/moz.build
+++ b/xpfe/appshell/moz.build
@@ -34,14 +34,13 @@ UNIFIED_SOURCES += [
     'nsContentTreeOwner.cpp',
     'nsWebShellWindow.cpp',
     'nsWindowMediator.cpp',
     'nsXULWindow.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/base',
-    '/dom/xul',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/xpfe/appshell/nsWebShellWindow.cpp
+++ b/xpfe/appshell/nsWebShellWindow.cpp
@@ -33,16 +33,19 @@
 #include "nsIWidgetListener.h"
 
 #include "nsIDOMCharacterData.h"
 #include "nsINodeList.h"
 
 #include "nsITimer.h"
 #include "nsXULPopupManager.h"
 
+
+#include "nsIDOMXULDocument.h"
+
 #include "nsFocusManager.h"
 
 #include "nsIWebProgress.h"
 #include "nsIWebProgressListener.h"
 
 #include "nsIDocument.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMElement.h"
--- a/xpfe/appshell/nsXULWindow.cpp
+++ b/xpfe/appshell/nsXULWindow.cpp
@@ -21,16 +21,17 @@
 
 //Interfaces needed to be included
 #include "nsIAppShell.h"
 #include "nsIAppShellService.h"
 #include "nsIServiceManager.h"
 #include "nsIContentViewer.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
+#include "nsIDOMXULDocument.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMXULElement.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMScreen.h"
 #include "nsIEmbeddingSiteWindow.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIIOService.h"
@@ -45,17 +46,16 @@
 #include "nsIURI.h"
 #include "nsAppShellCID.h"
 #include "nsReadableUtils.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsContentUtils.h"
 #include "nsWebShellWindow.h" // get rid of this one, too...
 #include "nsGlobalWindow.h"
-#include "XULDocument.h"
 
 #include "prenv.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/BarProps.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
@@ -1615,96 +1615,90 @@ NS_IMETHODIMP nsXULWindow::SavePersisten
     if (NS_SUCCEEDED(parent->GetPosition(&parentX, &parentY))) {
       rect.MoveBy(-parentX, -parentY);
     }
   }
 
   char                        sizeBuf[10];
   nsAutoString                sizeString;
   nsAutoString                windowElementId;
-  RefPtr<dom::XULDocument>    ownerXULDoc;
+  nsCOMPtr<nsIDOMXULDocument> ownerXULDoc;
 
   // fetch docShellElement's ID and XUL owner document
-  ownerXULDoc = docShellElement->OwnerDoc()->AsXULDocument();
+  ownerXULDoc = do_QueryInterface(docShellElement->OwnerDoc());
   if (docShellElement->IsXULElement()) {
     docShellElement->GetId(windowElementId);
   }
 
   bool shouldPersist = !isFullscreen && ownerXULDoc;
   ErrorResult rv;
   // (only for size elements which are persisted)
   if ((mPersistentAttributesDirty & PAD_POSITION) && gotRestoredBounds) {
     if (persistString.Find("screenX") >= 0) {
       SprintfLiteral(sizeBuf, "%d", NSToIntRound(rect.X() / posScale.scale));
       CopyASCIItoUTF16(sizeBuf, sizeString);
       docShellElement->SetAttribute(SCREENX_ATTRIBUTE, sizeString, rv);
       if (shouldPersist) {
-        IgnoredErrorResult err;
-        ownerXULDoc->Persist(windowElementId, SCREENX_ATTRIBUTE, err);
+        ownerXULDoc->Persist(windowElementId, SCREENX_ATTRIBUTE);
       }
     }
     if (persistString.Find("screenY") >= 0) {
       SprintfLiteral(sizeBuf, "%d", NSToIntRound(rect.Y() / posScale.scale));
       CopyASCIItoUTF16(sizeBuf, sizeString);
       docShellElement->SetAttribute(SCREENY_ATTRIBUTE, sizeString, rv);
       if (shouldPersist) {
-        IgnoredErrorResult err;
-        ownerXULDoc->Persist(windowElementId, SCREENY_ATTRIBUTE, err);
+        ownerXULDoc->Persist(windowElementId, SCREENY_ATTRIBUTE);
       }
     }
   }
 
   if ((mPersistentAttributesDirty & PAD_SIZE) && gotRestoredBounds) {
     if (persistString.Find("width") >= 0) {
       SprintfLiteral(sizeBuf, "%d", NSToIntRound(rect.Width() / sizeScale.scale));
       CopyASCIItoUTF16(sizeBuf, sizeString);
       docShellElement->SetAttribute(WIDTH_ATTRIBUTE, sizeString, rv);
       if (shouldPersist) {
-        IgnoredErrorResult err;
-        ownerXULDoc->Persist(windowElementId, WIDTH_ATTRIBUTE, err);
+        ownerXULDoc->Persist(windowElementId, WIDTH_ATTRIBUTE);
       }
     }
     if (persistString.Find("height") >= 0) {
       SprintfLiteral(sizeBuf, "%d", NSToIntRound(rect.Height() / sizeScale.scale));
       CopyASCIItoUTF16(sizeBuf, sizeString);
       docShellElement->SetAttribute(HEIGHT_ATTRIBUTE, sizeString, rv);
       if (shouldPersist) {
-        IgnoredErrorResult err;
-        ownerXULDoc->Persist(windowElementId, HEIGHT_ATTRIBUTE, err);
+        ownerXULDoc->Persist(windowElementId, HEIGHT_ATTRIBUTE);
       }
     }
   }
 
   if (mPersistentAttributesDirty & PAD_MISC) {
     nsSizeMode sizeMode = mWindow->SizeMode();
 
     if (sizeMode != nsSizeMode_Minimized) {
       if (sizeMode == nsSizeMode_Maximized)
         sizeString.Assign(SIZEMODE_MAXIMIZED);
       else if (sizeMode == nsSizeMode_Fullscreen)
         sizeString.Assign(SIZEMODE_FULLSCREEN);
       else
         sizeString.Assign(SIZEMODE_NORMAL);
       docShellElement->SetAttribute(MODE_ATTRIBUTE, sizeString, rv);
       if (shouldPersist && persistString.Find("sizemode") >= 0) {
-        IgnoredErrorResult err;
-        ownerXULDoc->Persist(windowElementId, MODE_ATTRIBUTE, err);
+        ownerXULDoc->Persist(windowElementId, MODE_ATTRIBUTE);
       }
     }
     if (persistString.Find("zlevel") >= 0) {
       uint32_t zLevel;
       nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
       if (mediator) {
         mediator->GetZLevel(this, &zLevel);
         SprintfLiteral(sizeBuf, "%" PRIu32, zLevel);
         CopyASCIItoUTF16(sizeBuf, sizeString);
         docShellElement->SetAttribute(ZLEVEL_ATTRIBUTE, sizeString, rv);
         if (shouldPersist) {
-          IgnoredErrorResult err;
-          ownerXULDoc->Persist(windowElementId, ZLEVEL_ATTRIBUTE, err);
+          ownerXULDoc->Persist(windowElementId, ZLEVEL_ATTRIBUTE);
         }
       }
     }
   }
 
   mPersistentAttributesDirty = 0;
   return NS_OK;
 }