Bug 1437638, move frame, browser and editor to be based on XULFrameElement, a new subclass of XULElement, r=paolo,bz
authorNeil Deakin <neil@mozilla.com>
Thu, 05 Jul 2018 20:14:18 -0400
changeset 425232 d8319d08895ce411a2beaec42ef59e3adf07278e
parent 425231 178261758dc9ea7bd8ee0d91923003455e07a4ab
child 425233 9b3654594194c65655a27f093fc2ee6b575a79a7
push id105002
push userneil@mozilla.com
push dateFri, 06 Jul 2018 00:17:23 +0000
treeherdermozilla-inbound@5a285b578fe1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspaolo, bz
bugs1437638
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1437638, move frame, browser and editor to be based on XULFrameElement, a new subclass of XULElement, r=paolo,bz
browser/components/extensions/parent/ext-browser.js
dom/base/test/chrome/file_bug549682.xul
dom/bindings/BindingUtils.cpp
dom/bindings/Bindings.conf
dom/chrome-webidl/XULFrameElement.webidl
dom/chrome-webidl/moz.build
dom/tests/mochitest/general/test_interfaces.js
dom/xul/XULFrameElement.cpp
dom/xul/XULFrameElement.h
dom/xul/moz.build
dom/xul/nsXULElement.cpp
mobile/android/components/extensions/ext-android.js
toolkit/content/tests/chrome/chrome.ini
toolkit/content/tests/chrome/test_frames.xul
toolkit/content/widgets/browser.xml
toolkit/content/widgets/editor.xml
toolkit/content/widgets/general.xml
toolkit/content/xul.css
toolkit/modules/addons/WebRequest.jsm
toolkit/modules/addons/WebRequestContent.js
--- a/browser/components/extensions/parent/ext-browser.js
+++ b/browser/components/extensions/parent/ext-browser.js
@@ -29,17 +29,17 @@ let windowTracker;
 const getSender = (extension, target, sender) => {
   let tabId;
   if ("tabId" in sender) {
     // The message came from a privileged extension page running in a tab. In
     // that case, it should include a tabId property (which is filled in by the
     // page-open listener below).
     tabId = sender.tabId;
     delete sender.tabId;
-  } else if (ExtensionCommon.instanceOf(target, "XULElement") ||
+  } else if (ExtensionCommon.instanceOf(target, "XULFrameElement") ||
              ExtensionCommon.instanceOf(target, "HTMLIFrameElement")) {
     tabId = tabTracker.getBrowserData(target).tabId;
   }
 
   if (tabId) {
     let tab = extension.tabManager.get(tabId, null);
     if (tab) {
       sender.tab = tab.convert();
--- a/dom/base/test/chrome/file_bug549682.xul
+++ b/dom/base/test/chrome/file_bug549682.xul
@@ -138,17 +138,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   }
 
   function run() {
     var localmm = document.getElementById('ifr').messageManager;
 
     var wn = document.getElementById('ifr').contentWindow
       .getInterface(Ci.nsIWebNavigation);
     ok(wn, "Should have webnavigation");
-    var cfmm = wn.getInterface(Ci.nsIContentFrameMessageManager);
+    var cfmm = wn.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIContentFrameMessageManager);
     ok(cfmm, "Should have content messageManager");
 
     var didGetSyncMessage = false;
     function syncContinueTestFn() {
       didGetSyncMessage = true;
     }
     localmm.addMessageListener("syncContinueTest", syncContinueTestFn);
     cfmm.sendSyncMessage("syncContinueTest", {});
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -43,16 +43,17 @@
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/ElementBinding.h"
 #include "mozilla/dom/HTMLObjectElement.h"
 #include "mozilla/dom/HTMLObjectElementBinding.h"
 #include "mozilla/dom/HTMLEmbedElement.h"
 #include "mozilla/dom/HTMLElementBinding.h"
 #include "mozilla/dom/HTMLEmbedElementBinding.h"
 #include "mozilla/dom/XULElementBinding.h"
+#include "mozilla/dom/XULFrameElementBinding.h"
 #include "mozilla/dom/XULPopupElementBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ResolveSystemBinding.h"
 #include "mozilla/dom/WebIDLGlobalNameHash.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerScope.h"
 #include "mozilla/dom/XrayExpandoClass.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
@@ -3863,16 +3864,20 @@ HTMLConstructor(JSContext* aCx, unsigned
       // function should be the localname's element interface.
       cb = sConstructorGetterCallback[tag];
     } else { // kNameSpaceID_XUL
       if (definition->mLocalName == nsGkAtoms::menupopup ||
           definition->mLocalName == nsGkAtoms::popup ||
           definition->mLocalName == nsGkAtoms::panel ||
           definition->mLocalName == nsGkAtoms::tooltip) {
         cb = XULPopupElement_Binding::GetConstructorObject;
+      } else if (definition->mLocalName == nsGkAtoms::iframe ||
+                 definition->mLocalName == nsGkAtoms::browser ||
+                 definition->mLocalName == nsGkAtoms::editor) {
+        cb = XULFrameElement_Binding::GetConstructorObject;
       } else {
         cb = XULElement_Binding::GetConstructorObject;
       }
     }
 
     if (!cb) {
       return ThrowErrorMessage(aCx, MSG_ILLEGAL_CONSTRUCTOR);
     }
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1829,16 +1829,17 @@ addExternalIface('nsIPrintSettings', nat
                  notflattened=True)
 addExternalIface('nsISelectionListener', nativeType='nsISelectionListener')
 addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True)
 addExternalIface('nsITransportProvider', nativeType='nsITransportProvider')
 addExternalIface('nsITreeSelection', nativeType='nsITreeSelection',
                  notflattened=True)
 addExternalIface('nsISupports', nativeType='nsISupports')
 addExternalIface('nsIDocShell', nativeType='nsIDocShell', notflattened=True)
+addExternalIface('nsIWebNavigation', nativeType='nsIWebNavigation', notflattened=True)
 addExternalIface('nsIEditor', nativeType='nsIEditor', notflattened=True)
 addExternalIface('nsIVariant', nativeType='nsIVariant', notflattened=True)
 addExternalIface('nsIWebBrowserPersistDocumentReceiver',
                  nativeType='nsIWebBrowserPersistDocumentReceiver',
                  headerFile='nsIWebBrowserPersistDocument.h',
                  notflattened=True)
 addExternalIface('nsIWebProgressListener', nativeType='nsIWebProgressListener',
                  notflattened=True)
new file mode 100644
--- /dev/null
+++ b/dom/chrome-webidl/XULFrameElement.webidl
@@ -0,0 +1,17 @@
+/* -*- 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/. */
+
+interface nsIDocShell;
+interface nsIWebNavigation;
+
+[HTMLConstructor, Func="IsChromeOrXBL"]
+interface XULFrameElement : XULElement
+{
+  readonly attribute nsIDocShell? docShell;
+  readonly attribute nsIWebNavigation? webNavigation;
+
+  readonly attribute WindowProxy? contentWindow;
+  readonly attribute Document? contentDocument; 
+};
--- a/dom/chrome-webidl/moz.build
+++ b/dom/chrome-webidl/moz.build
@@ -40,15 +40,16 @@ WEBIDL_FILES = [
     'MozStorageAsyncStatementParams.webidl',
     'MozStorageStatementParams.webidl',
     'MozStorageStatementRow.webidl',
     'PrecompiledScript.webidl',
     'PromiseDebugging.webidl',
     'StructuredCloneHolder.webidl',
     'WebExtensionContentScript.webidl',
     'WebExtensionPolicy.webidl',
+    'XULFrameElement.webidl'
 ]
 
 if CONFIG['MOZ_PLACES']:
     WEBIDL_FILES += [
         'PlacesEvent.webidl',
         'PlacesObservers.webidl',
     ]
--- a/dom/tests/mochitest/general/test_interfaces.js
+++ b/dom/tests/mochitest/general/test_interfaces.js
@@ -1248,16 +1248,18 @@ var interfaceNamesInGlobalScope =
     {name: "XSLTProcessor", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULCommandEvent", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULDocument", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULElement", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "XULFrameElement", insecureContext: true, xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULPopupElement", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
   ];
 // IMPORTANT: Do not change the list above without review from a DOM peer!
 
 function createInterfaceMap(isXBLScope) {
   var interfaceMap = {};
 
new file mode 100644
--- /dev/null
+++ b/dom/xul/XULFrameElement.cpp
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsCOMPtr.h"
+#include "nsIContent.h"
+#include "nsFrameLoader.h"
+#include "mozilla/dom/XULFrameElement.h"
+#include "mozilla/dom/XULFrameElementBinding.h"
+
+namespace mozilla {
+namespace dom {
+
+JSObject*
+XULFrameElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return XULFrameElement_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+nsIDocShell*
+XULFrameElement::GetDocShell()
+{
+  RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
+  return frameLoader ? frameLoader->GetDocShell(IgnoreErrors()) : nullptr;
+}
+
+already_AddRefed<nsIWebNavigation>
+XULFrameElement::GetWebNavigation()
+{
+  nsCOMPtr<nsIDocShell> docShell = GetDocShell();
+  nsCOMPtr<nsIWebNavigation> webnav = do_QueryInterface(docShell);
+  return webnav.forget();
+}
+
+already_AddRefed<nsPIDOMWindowOuter>
+XULFrameElement::GetContentWindow()
+{
+  nsCOMPtr<nsIDocShell> docShell = GetDocShell();
+  if (docShell) {
+    nsCOMPtr<nsPIDOMWindowOuter> win = docShell->GetWindow();
+    return win.forget();
+  }
+
+  return nullptr;
+}
+
+nsIDocument*
+XULFrameElement::GetContentDocument()
+{
+  nsCOMPtr<nsPIDOMWindowOuter> win = GetContentWindow();
+  return win ? win->GetDoc() : nullptr;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/xul/XULFrameElement.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef XULFrameElement_h__
+#define XULFrameElement_h__
+
+#include "mozilla/Attributes.h"
+#include "mozilla/ErrorResult.h"
+#include "js/TypeDecls.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsWrapperCache.h"
+#include "nsString.h"
+#include "nsXULElement.h"
+
+class nsIWebNavigation;
+
+namespace mozilla {
+namespace dom {
+
+class XULFrameElement final : public nsXULElement
+{
+public:
+  explicit XULFrameElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
+    : nsXULElement(aNodeInfo)
+  {
+  }
+
+  nsIDocShell* GetDocShell();
+  already_AddRefed<nsIWebNavigation> GetWebNavigation();
+  already_AddRefed<nsPIDOMWindowOuter> GetContentWindow();
+  nsIDocument* GetContentDocument();
+
+protected:
+  virtual ~XULFrameElement()
+  {
+  }
+
+  JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // XULFrameElement_h
--- a/dom/xul/moz.build
+++ b/dom/xul/moz.build
@@ -19,29 +19,31 @@ if CONFIG['MOZ_XUL']:
         'nsIXULOverlayProvider.idl',
     ]
 
     EXPORTS += [
         'nsXULElement.h',
     ]
 
     EXPORTS.mozilla.dom += [
+        'XULFrameElement.h',
         'XULPopupElement.h',
     ]
 
     UNIFIED_SOURCES += [
         'nsXULCommandDispatcher.cpp',
         'nsXULContentSink.cpp',
         'nsXULContentUtils.cpp',
         'nsXULElement.cpp',
         'nsXULPopupListener.cpp',
         'nsXULPrototypeCache.cpp',
         'nsXULPrototypeDocument.cpp',
         'nsXULSortService.cpp',
         'XULDocument.cpp',
+        'XULFrameElement.cpp',
         'XULPopupElement.cpp',
     ]
 
 XPIDL_SOURCES += [
     'nsIController.idl',
     'nsIControllers.idl',
     'nsIXULSortService.idl',
 ]
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -69,16 +69,17 @@
 #include "nsNodeInfoManager.h"
 #include "nsXBLBinding.h"
 #include "nsXULTooltipListener.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozAutoDocUpdate.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsICSSDeclaration.h"
 #include "nsLayoutUtils.h"
+#include "XULFrameElement.h"
 #include "XULPopupElement.h"
 
 #include "mozilla/dom/XULElementBinding.h"
 #include "mozilla/dom/BoxObject.h"
 #include "mozilla/dom/HTMLIFrameElement.h"
 #include "mozilla/dom/MouseEventBinding.h"
 #include "mozilla/dom/MutationEventBinding.h"
 #include "mozilla/dom/XULCommandEvent.h"
@@ -173,16 +174,23 @@ nsXULElement* nsXULElement::Construct(al
   RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo;
   if (nodeInfo->Equals(nsGkAtoms::menupopup) ||
       nodeInfo->Equals(nsGkAtoms::popup) ||
       nodeInfo->Equals(nsGkAtoms::panel) ||
       nodeInfo->Equals(nsGkAtoms::tooltip)) {
     return NS_NewXULPopupElement(nodeInfo.forget());
   }
 
+  if (nodeInfo->Equals(nsGkAtoms::iframe) ||
+      nodeInfo->Equals(nsGkAtoms::browser) ||
+      nodeInfo->Equals(nsGkAtoms::editor)) {
+    already_AddRefed<mozilla::dom::NodeInfo> frameni = nodeInfo.forget();
+    return new XULFrameElement(frameni);
+  }
+
   return NS_NewBasicXULElement(nodeInfo.forget());
 }
 
 /* static */
 already_AddRefed<nsXULElement>
 nsXULElement::CreateFromPrototype(nsXULPrototypeElement* aPrototype,
                                   mozilla::dom::NodeInfo *aNodeInfo,
                                   bool aIsScriptable,
--- a/mobile/android/components/extensions/ext-android.js
+++ b/mobile/android/components/extensions/ext-android.js
@@ -5,17 +5,17 @@
 const getSender = (extension, target, sender) => {
   let tabId = -1;
   if ("tabId" in sender) {
     // The message came from a privileged extension page running in a tab. In
     // that case, it should include a tabId property (which is filled in by the
     // page-open listener below).
     tabId = sender.tabId;
     delete sender.tabId;
-  } else if (ChromeUtils.getClassName(target) == "XULElement") {
+  } else if (ChromeUtils.getClassName(target) == "XULFrameElement") {
     tabId = tabTracker.getBrowserData(target).tabId;
   }
 
   if (tabId != null && tabId >= 0) {
     let tab = extension.tabManager.get(tabId, null);
     if (tab) {
       sender.tab = tab.convert();
     }
--- a/toolkit/content/tests/chrome/chrome.ini
+++ b/toolkit/content/tests/chrome/chrome.ini
@@ -106,16 +106,17 @@ skip-if = toolkit == "cocoa"
 [test_custom_element_base.xul]
 [test_deck.xul]
 [test_dialogfocus.xul]
 [test_findbar.xul]
 subsuite = clipboard
 [test_findbar_entireword.xul]
 [test_findbar_events.xul]
 [test_focus_anons.xul]
+[test_frames.xul]
 [test_hiddenitems.xul]
 [test_hiddenpaging.xul]
 [test_keys.xul]
 [test_labelcontrol.xul]
 [test_largemenu.xul]
 skip-if = os == 'linux' && !debug # Bug 1207174
 [test_maximized_persist.xul]
 support-files = window_maximized_persist.xul
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/chrome/test_frames.xul
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+
+<window onload="setTimeout(runTest, 0);"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+        <script><![CDATA[
+SimpleTest.waitForExplicitFinish();
+
+function runTest() {
+  for (let i = 1; i <= 3; i++) {
+    let frame = document.getElementById("frame" + i);
+    ok(frame instanceof XULFrameElement, "XULFrameElement " + i);
+
+    // Check the various fields to ensure that they have the correct type.
+    ok(frame.docShell instanceof Ci.nsIDocShell, "docShell " + i);
+    ok(frame.webNavigation instanceof Ci.nsIWebNavigation, "webNavigation " + i);
+
+    let contentWindow = frame.contentWindow;
+    let contentDocument = frame.contentDocument;
+    ok(contentWindow instanceof Window, "contentWindow " + i);
+    ok(contentDocument instanceof Document, "contentDocument " + i);
+    is(contentDocument.body.id, "thechildbody" + i, "right document body " + i);
+
+    // These fields should all be read-only.
+    frame.docShell = null;
+    ok(frame.docShell instanceof Ci.nsIDocShell, "docShell after set " + i);
+    frame.webNavigation = null;
+    ok(frame.webNavigation instanceof Ci.nsIWebNavigation, "webNavigation after set " + i);
+    frame.contentWindow = window;
+    is(frame.contentWindow, contentWindow, "contentWindow after set " + i);
+    frame.contentDocument = document;
+    is(frame.contentDocument, contentDocument, "contentDocument after set " + i);
+  }
+
+  // A non-frame element should not have these fields.
+  let button = document.getElementById("nonframe");
+  ok(!(button instanceof XULFrameElement), "XULFrameElement non frame");
+  is(button.docShell, undefined, "docShell non frame");
+  is(button.webNavigation, undefined, "webNavigation non frame");
+  is(button.contentWindow, undefined, "contentWindow non frame");
+  is(button.contentDocument, undefined, "contentDocument non frame");
+
+  SimpleTest.finish();
+}
+]]>
+</script>
+
+<iframe id="frame1" src="data:text/html,&lt;body id='thechildbody1'&gt;"/>
+<browser id="frame2" src="data:text/html,&lt;body id='thechildbody2'&gt;"/>
+<editor id="frame3" src="data:text/html,&lt;body id='thechildbody3'&gt;"/>
+<button id="nonframe"/>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<div id="content" style="display: none"></div>
+</body>
+
+</window>
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -176,31 +176,16 @@
         <getter><![CDATA[
           return this._sameProcessAsFrameLoader && this._sameProcessAsFrameLoader.get();
         ]]></getter>
         <setter><![CDATA[
           this._sameProcessAsFrameLoader = Cu.getWeakReference(val);
         ]]></setter>
       </property>
 
-      <field name="_docShell">null</field>
-
-      <property name="docShell" readonly="true">
-        <getter><![CDATA[
-          if (this._docShell)
-            return this._docShell;
-
-          let {frameLoader} = this;
-          if (!frameLoader)
-            return null;
-          this._docShell = frameLoader.docShell;
-          return this._docShell;
-        ]]></getter>
-      </property>
-
       <field name="_loadContext">null</field>
 
       <property name="loadContext" readonly="true">
         <getter><![CDATA[
           if (this._loadContext)
             return this._loadContext;
 
           let {frameLoader} = this;
@@ -309,33 +294,16 @@
               return this.frameLoader.messageManager;
             }
             return null;
           ]]>
         </getter>
 
       </property>
 
-      <field name="_webNavigation">null</field>
-
-      <property name="webNavigation"
-                readonly="true">
-        <getter>
-        <![CDATA[
-          if (!this._webNavigation) {
-            if (!this.docShell) {
-              return null;
-            }
-            this._webNavigation = this.docShell.QueryInterface(Ci.nsIWebNavigation);
-          }
-          return this._webNavigation;
-        ]]>
-        </getter>
-      </property>
-
       <field name="_webBrowserFind">null</field>
 
       <property name="webBrowserFind"
                 readonly="true">
         <getter>
         <![CDATA[
           if (!this._webBrowserFind)
             this._webBrowserFind = this.docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebBrowserFind);
@@ -420,38 +388,28 @@
       </property>
 
       <field name="_lastSearchString">null</field>
 
       <property name="webProgress"
                 readonly="true"
                 onget="return this.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebProgress);"/>
 
-      <field name="_contentWindow">null</field>
-
-      <property name="contentWindow"
-                readonly="true"
-                onget="return this._contentWindow || (this._contentWindow = this.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindow));"/>
-
       <property name="contentWindowAsCPOW"
                 readonly="true"
                 onget="return this.contentWindow;"/>
 
       <property name="sessionHistory"
                 onget="return this.webNavigation.sessionHistory;"
                 readonly="true"/>
 
       <property name="markupDocumentViewer"
                 onget="return this.docShell.contentViewer;"
                 readonly="true"/>
 
-      <property name="contentDocument"
-                onget="return this.webNavigation.document;"
-                readonly="true"/>
-
       <property name="contentDocumentAsCPOW"
                 onget="return this.contentDocument;"
                 readonly="true"/>
 
       <property name="contentTitle"
                 onget="return this.contentDocument.title;"
                 readonly="true"/>
 
@@ -1368,20 +1326,17 @@
 
           // We need to swap fields that are tied to our docshell or related to
           // the loaded page
           // Fields which are built as a result of notifactions (pageshow/hide,
           // DOMLinkAdded/Removed, onStateChange) should not be swapped here,
           // because these notifications are dispatched again once the docshells
           // are swapped.
           var fieldsToSwap = [
-            "_docShell",
             "_webBrowserFind",
-            "_contentWindow",
-            "_webNavigation"
           ];
 
           if (this.isRemoteBrowser) {
             fieldsToSwap.push(...[
               "_remoteWebNavigation",
               "_remoteWebNavigationImpl",
               "_remoteWebProgressManager",
               "_remoteWebProgress",
--- a/toolkit/content/widgets/editor.xml
+++ b/toolkit/content/widgets/editor.xml
@@ -112,33 +112,19 @@
         </getter>
       </property>
 
       <field name="_lastSearchString">null</field>
 
       <property name="editortype"
                 onget="return this.getAttribute('editortype');"
                 onset="this.setAttribute('editortype', val); return val;"/>
-      <property name="webNavigation"
-                onget="return this.docShell.QueryInterface(Components.interfaces.nsIWebNavigation);"
-                readonly="true"/>
-      <property name="contentDocument" readonly="true"
-                onget="return this.webNavigation.document;"/>
-      <property name="docShell" readonly="true">
-        <getter><![CDATA[
-          let {frameLoader} = this;
-          return frameLoader ? frameLoader.docShell : null;
-        ]]></getter>
-      </property>
       <property name="currentURI"
                 readonly="true"
                 onget="return this.webNavigation.currentURI;"/>
-      <property name="contentWindow"
-                readonly="true"
-                onget="return this.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindow);"/>
       <property name="contentWindowAsCPOW"
                 readonly="true"
                 onget="return this.contentWindow;"/>
       <property name="webBrowserFind"
                 readonly="true"
                 onget="return this.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebBrowserFind);"/>
       <property name="markupDocumentViewer"
                 readonly="true"
--- a/toolkit/content/widgets/general.xml
+++ b/toolkit/content/widgets/general.xml
@@ -52,28 +52,9 @@
           ]]>
         </setter>
       </property>
 
       <field name="labelElement"/>
     </implementation>
   </binding>
 
-  <binding id="iframe">
-    <implementation>
-      <property name="docShell" readonly="true">
-        <getter><![CDATA[
-          let {frameLoader} = this;
-          return frameLoader ? frameLoader.docShell : null;
-        ]]></getter>
-      </property>
-      <property name="contentWindow"
-                readonly="true"
-                onget="return this.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindow);"/>
-      <property name="webNavigation"
-                onget="return this.docShell.QueryInterface(Components.interfaces.nsIWebNavigation);"
-                readonly="true"/>
-      <property name="contentDocument" readonly="true"
-                onget="return this.webNavigation.document;"/>
-    </implementation>
-  </binding>
-
 </bindings>
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -171,20 +171,16 @@ browser {
 browser[remote=true]:not(.lightweight) {
   -moz-binding: url("chrome://global/content/bindings/remote-browser.xml#remote-browser");
 }
 
 editor {
   -moz-binding: url("chrome://global/content/bindings/editor.xml#editor");
 }
 
-iframe {
-  -moz-binding: url("chrome://global/content/bindings/general.xml#iframe");
-}
-
 /********** notifications **********/
 
 notificationbox {
   -moz-binding: url("chrome://global/content/bindings/notification.xml#notificationbox");
   -moz-box-orient: vertical;
 }
 
 .notificationbox-stack {
--- a/toolkit/modules/addons/WebRequest.jsm
+++ b/toolkit/modules/addons/WebRequest.jsm
@@ -219,17 +219,17 @@ var ContentPolicyManager = {
   init() {
     Services.ppmm.initialProcessData.webRequestContentPolicies = this.policyData;
 
     Services.ppmm.addMessageListener("WebRequest:ShouldLoad", this);
     Services.mm.addMessageListener("WebRequest:ShouldLoad", this);
   },
 
   receiveMessage(msg) {
-    let browser = ChromeUtils.getClassName(msg.target) == "XULElement" ? msg.target : null;
+    let browser = ChromeUtils.getClassName(msg.target) == "XULFrameElement" ? msg.target : null;
 
     let requestId = `fakeRequest-${++nextFakeRequestId}`;
     for (let id of msg.data.ids) {
       let callback = this.policies.get(id);
       if (!callback) {
         // It's possible that this listener has been removed and the
         // child hasn't learned yet.
         continue;
--- a/toolkit/modules/addons/WebRequestContent.js
+++ b/toolkit/modules/addons/WebRequestContent.js
@@ -123,17 +123,17 @@ var ContentPolicy = {
       return window.QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(Ci.nsIDOMWindowUtils)
         .outerWindowID;
     }
 
     let node = loadInfo.loadingContext;
     if (node &&
         (policyType == Ci.nsIContentPolicy.TYPE_SUBDOCUMENT ||
-         (ChromeUtils.getClassName(node) == "XULElement" &&
+        (ChromeUtils.getClassName(node) == "XULFrameElement" &&
           node.localName == "browser"))) {
       // Chrome sets frameId to the ID of the sub-window. But when
       // Firefox loads an iframe, it sets |node| to the <iframe>
       // element, whose window is the parent window. We adopt the
       // Chrome behavior here.
       node = node.contentWindow;
     }