Bug 979835: Port BoxObject and its subclasses to WebIDL. r=khuey sr=bz
authorJon Morton <jonanin@gmail.com>
Tue, 14 Oct 2014 13:15:21 -0700
changeset 210449 8d3304b7e0e0b2b8fd607c8320436b415e8d4cae
parent 210448 944cba921a299f6f29c482652f5a0446189de6a3
child 210450 713b9fa30f62b47d811adc4f190b07b22cae2eb4
push id27654
push userryanvm@gmail.com
push dateWed, 15 Oct 2014 18:31:27 +0000
treeherdermozilla-central@a280a03c9f3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey, bz
bugs979835
milestone36.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 979835: Port BoxObject and its subclasses to WebIDL. r=khuey sr=bz
accessible/base/nsCoreUtils.cpp
accessible/base/nsCoreUtils.h
accessible/tests/mochitest/actions/test_treegrid.xul
accessible/tests/mochitest/hittest/test_zoom_tree.xul
accessible/tests/mochitest/name/test_tree.xul
accessible/tests/mochitest/selectable/test_tree.xul
accessible/tests/mochitest/states/test_tree.xul
accessible/tests/mochitest/tree/test_tree.xul
accessible/tests/mochitest/treeview.js
accessible/xul/XULTreeAccessible.cpp
accessible/xul/XULTreeGridAccessible.cpp
browser/base/content/browser-places.js
browser/base/content/pageinfo/pageInfo.js
browser/base/content/sync/quota.js
browser/components/feeds/FeedWriter.js
browser/components/places/content/sidebarUtils.js
browser/components/places/content/tree.xml
browser/components/places/tests/browser/browser_forgetthissite_single.js
browser/components/places/tests/browser/browser_library_infoBox.js
browser/components/places/tests/browser/browser_library_middleclick.js
browser/components/places/tests/browser/head.js
browser/components/preferences/cookies.js
browser/components/preferences/permissions.js
browser/components/preferences/tests/browser_bug705422.js
browser/components/preferences/translation.js
browser/components/search/test/browser_405664.js
browser/components/sessionstore/content/aboutSessionRestore.js
browser/components/sessionstore/test/browser_590563.js
browser/devtools/shared/widgets/FastListWidget.js
browser/devtools/shared/widgets/SideMenuWidget.jsm
browser/devtools/shared/widgets/SimpleListWidget.jsm
browser/devtools/shared/widgets/VariablesView.jsm
browser/metro/base/content/bindings/bindings.xml
browser/metro/base/content/input.js
browser/modules/UITour.jsm
content/base/public/nsIDocument.h
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/xul/content/src/nsXULElement.cpp
content/xul/content/src/nsXULElement.h
content/xul/document/src/XULDocument.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/bindings/Bindings.conf
dom/events/test/test_bug602962.xul
dom/tests/mochitest/general/test_interfaces.html
dom/webidl/BoxObject.webidl
dom/webidl/ContainerBoxObject.webidl
dom/webidl/LegacyQueryInterface.webidl
dom/webidl/ListBoxObject.webidl
dom/webidl/MenuBoxObject.webidl
dom/webidl/PopupBoxObject.webidl
dom/webidl/ScrollBoxObject.webidl
dom/webidl/TreeBoxObject.webidl
dom/webidl/TreeColumns.webidl
dom/webidl/XULDocument.webidl
dom/webidl/XULElement.webidl
dom/webidl/moz.build
dom/xslt/tests/buster/buster-handlers.js
editor/composer/test/test_bug434998.xul
editor/libeditor/tests/test_bug607584.xul
editor/libeditor/tests/test_bug616590.xul
editor/libeditor/tests/test_bug780908.xul
gfx/tests/unit/test_nsIScriptableRegion.js
js/xpconnect/src/dom_quickstubs.qsconf
layout/reftests/invalidation/540247-1-ref.xul
layout/reftests/invalidation/540247-1.xul
layout/xul/BoxObject.cpp
layout/xul/BoxObject.h
layout/xul/ContainerBoxObject.cpp
layout/xul/ContainerBoxObject.h
layout/xul/ListBoxObject.cpp
layout/xul/ListBoxObject.h
layout/xul/MenuBoxObject.cpp
layout/xul/MenuBoxObject.h
layout/xul/PopupBoxObject.cpp
layout/xul/PopupBoxObject.h
layout/xul/ScrollBoxObject.cpp
layout/xul/ScrollBoxObject.h
layout/xul/moz.build
layout/xul/nsBoxObject.cpp
layout/xul/nsBoxObject.h
layout/xul/nsContainerBoxObject.cpp
layout/xul/nsIBoxObject.idl
layout/xul/nsIBrowserBoxObject.idl
layout/xul/nsIContainerBoxObject.idl
layout/xul/nsIEditorBoxObject.idl
layout/xul/nsIIFrameBoxObject.idl
layout/xul/nsIListBoxObject.idl
layout/xul/nsIMenuBoxObject.idl
layout/xul/nsIPopupBoxObject.idl
layout/xul/nsIScrollBoxObject.idl
layout/xul/nsListBoxBodyFrame.cpp
layout/xul/nsListBoxBodyFrame.h
layout/xul/nsListBoxObject.cpp
layout/xul/nsMenuBoxObject.cpp
layout/xul/nsMenuPopupFrame.cpp
layout/xul/nsMenuPopupFrame.h
layout/xul/nsPopupBoxObject.cpp
layout/xul/nsScrollBoxObject.cpp
layout/xul/nsXULPopupManager.cpp
layout/xul/nsXULTooltipListener.cpp
layout/xul/tree/TreeBoxObject.cpp
layout/xul/tree/TreeBoxObject.h
layout/xul/tree/crashtests/585815-iframe.xul
layout/xul/tree/moz.build
layout/xul/tree/nsITreeBoxObject.idl
layout/xul/tree/nsTreeBodyFrame.cpp
layout/xul/tree/nsTreeBodyFrame.h
layout/xul/tree/nsTreeBoxObject.cpp
layout/xul/tree/nsTreeBoxObject.h
layout/xul/tree/nsTreeColFrame.cpp
layout/xul/tree/nsTreeColumns.cpp
layout/xul/tree/nsTreeColumns.h
layout/xul/tree/nsTreeSelection.cpp
security/manager/pki/resources/content/certManager.js
security/manager/pki/resources/content/viewCertDetails.js
services/sync/tps/extensions/mozmill/resource/driver/mozelement.js
testing/mochitest/browser-harness.xul
toolkit/components/filepicker/content/filepicker.js
toolkit/components/passwordmgr/content/passwordManager.js
toolkit/components/passwordmgr/content/passwordManagerExceptions.js
toolkit/components/passwordmgr/test/browser/browser_passwordmgrdlg.js
toolkit/content/tests/chrome/popup_trigger.js
toolkit/content/tests/chrome/test_contextmenu_list.xul
toolkit/content/tests/chrome/test_mousescroll.xul
toolkit/content/tests/chrome/test_popup_tree.xul
toolkit/content/tests/chrome/test_position.xul
toolkit/content/tests/chrome/window_largemenu.xul
toolkit/content/tests/fennec-tile-testapp/chrome/content/FooScript.js
toolkit/content/tests/fennec-tile-testapp/chrome/content/foo.xul
toolkit/content/tests/widgets/popup_shared.js
toolkit/content/tests/widgets/tree_shared.js
toolkit/content/widgets/autocomplete.xml
toolkit/content/widgets/button.xml
toolkit/content/widgets/datetimepicker.xml
toolkit/content/widgets/editor.xml
toolkit/content/widgets/general.xml
toolkit/content/widgets/listbox.xml
toolkit/content/widgets/menu.xml
toolkit/content/widgets/menulist.xml
toolkit/content/widgets/popup.xml
toolkit/content/widgets/richlistbox.xml
toolkit/content/widgets/scrollbox.xml
toolkit/content/widgets/tree.xml
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
toolkit/mozapps/extensions/test/browser/browser_inlinesettings_info.js
toolkit/mozapps/extensions/test/browser/browser_select_selection.js
xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
xpfe/components/autocomplete/resources/content/autocomplete.xml
--- a/accessible/base/nsCoreUtils.cpp
+++ b/accessible/base/nsCoreUtils.cpp
@@ -52,17 +52,17 @@ nsCoreUtils::HasClickListener(nsIContent
     (listenerManager->HasListenersFor(nsGkAtoms::onclick) ||
      listenerManager->HasListenersFor(nsGkAtoms::onmousedown) ||
      listenerManager->HasListenersFor(nsGkAtoms::onmouseup));
 }
 
 void
 nsCoreUtils::DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
                                 int32_t aRowIndex, nsITreeColumn *aColumn,
-                                const nsCString& aPseudoElt)
+                                const nsAString& aPseudoElt)
 {
   nsCOMPtr<nsIDOMElement> tcElm;
   aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
   if (!tcElm)
     return;
 
   nsCOMPtr<nsIContent> tcContent(do_QueryInterface(tcElm));
   nsIDocument *document = tcContent->GetCurrentDoc();
--- a/accessible/base/nsCoreUtils.h
+++ b/accessible/base/nsCoreUtils.h
@@ -39,17 +39,17 @@ public:
    * @param  aTreeBoxObj  [in] tree box object
    * @param  aRowIndex    [in] row index
    * @param  aColumn      [in] column object
    * @param  aPseudoElm   [in] pseudo elemenet inside the cell, see
    *                       nsITreeBoxObject for available values
    */
   static void DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
                                  int32_t aRowIndex, nsITreeColumn *aColumn,
-                                 const nsCString& aPseudoElt = EmptyCString());
+                                 const nsAString& aPseudoElt = EmptyString());
 
   /**
    * Send mouse event to the given element.
    *
    * @param aEventType   [in] an event type (see BasicEvents.h for constants)
    * @param aX           [in] x coordinate in dev pixels
    * @param aY           [in] y coordinate in dev pixels
    * @param aContent     [in] the element
@@ -309,9 +309,8 @@ public:
   static bool IsWhitespace(char16_t aChar)
   {
     return aChar == ' ' || aChar == '\n' ||
       aChar == '\r' || aChar == '\t' || aChar == 0xa0;
   }
 };
 
 #endif
-
--- a/accessible/tests/mochitest/actions/test_treegrid.xul
+++ b/accessible/tests/mochitest/actions/test_treegrid.xul
@@ -150,18 +150,17 @@
     {
       var treeNode = getNode("tabletree");
       waitForEvent(EVENT_REORDER, treeNode, doTestActions);
       treeNode.view = new nsTreeTreeView();
     }
 
     function test1()
     {
-      var boxObj = getNode("tabletree").treeBoxObject;
-      boxObj.view.setCellValue(0, boxObj.columns.firstColumn, "false");
+      getNode("tabletree").view.setCellValue(0, boxObj.columns.firstColumn, "false");
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
   </script>
 
   <hbox flex="1" style="overflow: auto;">
@@ -191,9 +190,8 @@
       </tree>
 
       <vbox id="debug"/>
       <button oncommand="test1();" label="uncheck"/>
     </vbox>
   </hbox>
 
 </window>
-
--- a/accessible/tests/mochitest/hittest/test_zoom_tree.xul
+++ b/accessible/tests/mochitest/hittest/test_zoom_tree.xul
@@ -35,26 +35,24 @@
       var treecol1 = tabDocument.getElementById("treecol1");
 
       // tree columns
       hitTest(tree, treecols, treecol1);
 
       // tree rows and cells
       var treeBoxObject = tree.treeBoxObject;
       var treeBodyBoxObj = tree.treeBoxObject.treeBody.boxObject;
-      var xObj = {}, yObj = {}, widthObj = {}, heightObj = {};
-      treeBoxObject.getCoordsForCellItem(1, tree.columns[0], "cell",
-                                         xObj, yObj, widthObj, heightObj);
+      var rect = treeBoxObject.getCoordsForCellItem(1, tree.columns[0], "cell");
 
       var treeAcc = getAccessible(tree, [nsIAccessibleTable]);
       var cellAcc = treeAcc.getCellAt(1, 0);
       var rowAcc = cellAcc.parent;
 
-      var cssX = xObj.value + treeBodyBoxObj.x;
-      var cssY = yObj.value + treeBodyBoxObj.y;
+      var cssX = rect.x + treeBodyBoxObj.x;
+      var cssY = rect.y + treeBodyBoxObj.y;
       var [x, y] = CSSToDevicePixels(tabWindow, cssX, cssY);
 
       testChildAtPoint(treeAcc, x, y, rowAcc, cellAcc);
       testChildAtPoint(rowAcc, x, y, cellAcc, cellAcc);
 
       // do zoom
       zoomDocument(tabDocument, 1.5);
 
@@ -95,9 +93,8 @@
       <div id="content" style="display: none">
       </div>
       <pre id="test">
       </pre>
     </body>
   </hbox>
 
 </window>
-
--- a/accessible/tests/mochitest/name/test_tree.xul
+++ b/accessible/tests/mochitest/name/test_tree.xul
@@ -27,17 +27,17 @@
   <script type="application/javascript">
   <![CDATA[
     function treeTester(aID)
     {
       this.DOMNode = getNode(aID);
 
       this.invoke = function treeTester_invoke()
       {
-        this.DOMNode.treeBoxObject.view = new nsTreeTreeView();
+        this.DOMNode.view = new nsTreeTreeView();
       }
 
       this.check = function treeTester_check(aEvent)
       {
         var tree = {
           role: ROLE_OUTLINE,
           children: [
             {
@@ -85,17 +85,17 @@
     }
 
     function tableTester(aID, aIsTable, aCol1ID, aCol2ID)
     {
       this.DOMNode = getNode(aID);
 
       this.invoke = function tableTester_invoke()
       {
-        this.DOMNode.treeBoxObject.view = new nsTableTreeView(2);
+        this.DOMNode.view = new nsTableTreeView(2);
       }
 
       this.check = function tableTester_check(aEvent)
       {
         var tree = {
           role: aIsTable ? ROLE_TABLE : ROLE_TREE_TABLE,
           children: [
             {
@@ -204,9 +204,8 @@
       <treecol id="tt_col2" flex="1" label="column 2"/>
     </treecols>
     <treechildren/>
   </tree>
 
   </vbox> <!-- close tests area -->
   </hbox> <!-- close main area -->
 </window>
-
--- a/accessible/tests/mochitest/selectable/test_tree.xul
+++ b/accessible/tests/mochitest/selectable/test_tree.xul
@@ -37,17 +37,17 @@
      * accessible.
      */
     function statesChecker(aTreeID, aView)
     {
       this.DOMNode = getNode(aTreeID);
       
       this.invoke = function invoke()
       {
-        this.DOMNode.treeBoxObject.view = aView;
+        this.DOMNode.view = aView;
       }
       this.check = function check()
       {
         var tree = getAccessible(this.DOMNode);
 
         var isTreeMultiSelectable = false;
         var seltype = this.DOMNode.getAttribute("seltype");
         if (seltype != "single" && seltype != "cell" && seltype != "text")
@@ -181,9 +181,8 @@
         <treechildren/>
       </tree>
 
       <vbox id="debug"/>
     </vbox>
   </hbox>
 
 </window>
-
--- a/accessible/tests/mochitest/states/test_tree.xul
+++ b/accessible/tests/mochitest/states/test_tree.xul
@@ -33,17 +33,17 @@
      * accessible.
      */
     function statesChecker(aTreeID, aView)
     {
       this.DOMNode = getNode(aTreeID);
 
       this.invoke = function statesChecker_invoke()
       {
-        this.DOMNode.treeBoxObject.view = aView;
+        this.DOMNode.view = aView;
       }
 
       this.check = function statesChecker_check()
       {
         var tree = getAccessible(this.DOMNode);
 
         // tree states
         testStates(tree, STATE_READONLY);
@@ -145,9 +145,8 @@
         <treechildren/>
       </tree>
 
       <vbox id="debug"/>
     </vbox>
   </hbox>
 
 </window>
-
--- a/accessible/tests/mochitest/tree/test_tree.xul
+++ b/accessible/tests/mochitest/tree/test_tree.xul
@@ -67,17 +67,17 @@
       var accTreeForTree = {
         role: aRole,
         children: [
           accTreeForColumns
         ]
       };
 
       var treeBoxObject = aTree.treeBoxObject;
-      var view = treeBoxObject.view;
+      var view = aTree.view;
       var columnCount = treeBoxObject.columns.count;
 
       for (var idx = 0; idx < columnCount; idx++)
         accTreeForColumns.children.push({ COLUMNHEADER: [ ] });
       if (!aTree.hasAttribute("hidecolumnpicker"))
         accTreeForColumns.children.push({ PUSHBUTTON: [ { MENUPOPUP: [] } ] });
 
       for (var idx = 0; idx < view.rowCount; idx++)
@@ -90,17 +90,17 @@
      * Event queue invoker object to test accessible tree for XUL tree element.
      */
     function treeChecker(aID, aView, aRole)
     {
       this.DOMNode = getNode(aID);
 
       this.invoke = function invoke()
       {
-        this.DOMNode.treeBoxObject.view = aView;
+        this.DOMNode.view = aView;
       }
       this.check = function check(aEvent)
       {
         testAccessibleTreeFor(this.DOMNode, aRole);
       }
       this.getID = function getID()
       {
         return "Tree testing of " + aID;
@@ -175,9 +175,8 @@
         <treechildren/>
       </tree>
 
       <vbox id="debug"/>
     </vbox>
   </hbox>
 
 </window>
-
--- a/accessible/tests/mochitest/treeview.js
+++ b/accessible/tests/mochitest/treeview.js
@@ -12,17 +12,17 @@ function loadXULTreeAndDoTest(aDoTestFun
     this.treeNode = getNode(aTreeID);
 
     this.eventSeq = [
       new invokerChecker(EVENT_REORDER, this.treeNode)
     ];
 
     this.invoke = function loadXULTree_invoke()
     {
-      this.treeNode.treeBoxObject.view = aTreeView;
+      this.treeNode.view = aTreeView;
     }
 
     this.getID = function loadXULTree_getID()
     {
       return "Load XUL tree " + prettyName(aTreeID);
     }
   }
 
--- a/accessible/xul/XULTreeAccessible.cpp
+++ b/accessible/xul/XULTreeAccessible.cpp
@@ -194,17 +194,17 @@ XULTreeAccessible::ChildAtPoint(int32_t 
 
   nsIntRect rootRect = rootFrame->GetScreenRect();
 
   int32_t clientX = presContext->DevPixelsToIntCSSPixels(aX) - rootRect.x;
   int32_t clientY = presContext->DevPixelsToIntCSSPixels(aY) - rootRect.y;
 
   int32_t row = -1;
   nsCOMPtr<nsITreeColumn> column;
-  nsAutoCString childEltUnused;
+  nsAutoString childEltUnused;
   mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column),
                    childEltUnused);
 
   // If we failed to find tree cell for the given point then it might be
   // tree columns.
   if (row == -1 || !column)
     return AccessibleWrap::ChildAtPoint(aX, aY, aWhichChild);
 
@@ -741,17 +741,17 @@ XULTreeItemAccessibleBase::Bounds() cons
 
   nsCOMPtr<nsIBoxObject> boxObj = nsCoreUtils::GetTreeBodyBoxObject(mTree);
   if (!boxObj)
     return nsIntRect();
 
   nsCOMPtr<nsITreeColumn> column = nsCoreUtils::GetFirstSensibleColumn(mTree);
 
   int32_t x = 0, y = 0, width = 0, height = 0;
-  nsresult rv = mTree->GetCoordsForCellItem(mRow, column, EmptyCString(),
+  nsresult rv = mTree->GetCoordsForCellItem(mRow, column, EmptyString(),
                                             &x, &y, &width, &height);
   if (NS_FAILED(rv))
     return nsIntRect();
 
   boxObj->GetWidth(&width);
 
   int32_t tcX = 0, tcY = 0;
   boxObj->GetScreenX(&tcX);
@@ -991,25 +991,25 @@ XULTreeItemAccessibleBase::DispatchClick
 
   nsCOMPtr<nsITreeColumns> columns;
   mTree->GetColumns(getter_AddRefs(columns));
   if (!columns)
     return;
 
   // Get column and pseudo element.
   nsCOMPtr<nsITreeColumn> column;
-  nsAutoCString pseudoElm;
+  nsAutoString pseudoElm;
 
   if (aActionIndex == eAction_Click) {
     // Key column is visible and clickable.
     columns->GetKeyColumn(getter_AddRefs(column));
   } else {
     // Primary column contains a twisty we should click on.
     columns->GetPrimaryColumn(getter_AddRefs(column));
-    pseudoElm = NS_LITERAL_CSTRING("twisty");
+    pseudoElm = NS_LITERAL_STRING("twisty");
   }
 
   if (column)
     nsCoreUtils::DispatchClickEvent(mTree, mRow, column, pseudoElm);
 }
 
 Accessible*
 XULTreeItemAccessibleBase::GetSiblingAtOffset(int32_t aOffset,
@@ -1191,9 +1191,8 @@ XULTreeColumAccessible::GetSiblingAtOffs
         if (treeAcc)
           return treeAcc->GetTreeItemAccessible(aOffset - 1);
       }
     }
   }
 
   return nullptr;
 }
-
--- a/accessible/xul/XULTreeGridAccessible.cpp
+++ b/accessible/xul/XULTreeGridAccessible.cpp
@@ -336,17 +336,17 @@ XULTreeGridRowAccessible::ChildAtPoint(i
 
   nsIntRect rootRect = rootFrame->GetScreenRect();
 
   int32_t clientX = presContext->DevPixelsToIntCSSPixels(aX) - rootRect.x;
   int32_t clientY = presContext->DevPixelsToIntCSSPixels(aY) - rootRect.y;
 
   int32_t row = -1;
   nsCOMPtr<nsITreeColumn> column;
-  nsAutoCString childEltUnused;
+  nsAutoString childEltUnused;
   mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column),
                    childEltUnused);
 
   // Return if we failed to find tree cell in the row for the given point.
   if (row != mRow || !column)
     return nullptr;
 
   return GetCellAccessible(column);
@@ -517,17 +517,17 @@ XULTreeGridCellAccessible::Bounds() cons
   // Get bounds for tree cell and add x and y of treechildren element to
   // x and y of the cell.
   nsCOMPtr<nsIBoxObject> boxObj = nsCoreUtils::GetTreeBodyBoxObject(mTree);
   if (!boxObj)
     return nsIntRect();
 
   int32_t x = 0, y = 0, width = 0, height = 0;
   nsresult rv = mTree->GetCoordsForCellItem(mRow, mColumn,
-                                            NS_LITERAL_CSTRING("cell"),
+                                            NS_LITERAL_STRING("cell"),
                                             &x, &y, &width, &height);
   if (NS_FAILED(rv))
     return nsIntRect();
 
   int32_t tcX = 0, tcY = 0;
   boxObj->GetScreenX(&tcX);
   boxObj->GetScreenY(&tcY);
   x += tcX;
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -703,23 +703,22 @@ var BookmarksEventHandler = {
 
   fillInBHTooltip: function BEH_fillInBHTooltip(aDocument, aEvent) {
     var node;
     var cropped = false;
     var targetURI;
 
     if (aDocument.tooltipNode.localName == "treechildren") {
       var tree = aDocument.tooltipNode.parentNode;
-      var row = {}, column = {};
       var tbo = tree.treeBoxObject;
-      tbo.getCellAt(aEvent.clientX, aEvent.clientY, row, column, {});
-      if (row.value == -1)
+      var cell = tbo.getCellAt(aEvent.clientX, aEvent.clientY);
+      if (cell.row == -1)
         return false;
-      node = tree.view.nodeForTreeIndex(row.value);
-      cropped = tbo.isCellCropped(row.value, column.value);
+      node = tree.view.nodeForTreeIndex(cell.row);
+      cropped = tbo.isCellCropped(cell.row, cell.col);
     }
     else {
       // Check whether the tooltipNode is a Places node.
       // In such a case use it, otherwise check for targetURI attribute.
       var tooltipNode = aDocument.tooltipNode;
       if (tooltipNode._placesNode)
         node = tooltipNode._placesNode;
       else {
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -503,17 +503,17 @@ function makeGeneralTab()
     metaGroup.collapsed = true;
   else {
     var metaTagsCaption = document.getElementById("metaTagsCaption");
     if (length == 1)
       metaTagsCaption.label = gBundle.getString("generalMetaTag");
     else
       metaTagsCaption.label = gBundle.getFormattedString("generalMetaTags", [length]);
     var metaTree = document.getElementById("metatree");
-    metaTree.treeBoxObject.view = gMetaView;
+    metaTree.view = gMetaView;
 
     for (var i = 0; i < length; i++)
       gMetaView.addRow([metaNodes[i].name || metaNodes[i].httpEquiv, metaNodes[i].content]);
 
     metaGroup.collapsed = false;
   }
 
   // get the date of last modification
--- a/browser/base/content/sync/quota.js
+++ b/browser/base/content/sync/quota.js
@@ -156,20 +156,19 @@ let gUsageTreeView = {
 
   /*
    * Handle click events on the tree.
    */
   onTreeClick: function onTreeClick(event) {
     if (event.button == 2)
       return;
 
-    let row = {}, col = {};
-    this.treeBox.getCellAt(event.clientX, event.clientY, row, col, {});
-    if (col.value && col.value.id == "enabled")
-      this.toggle(row.value);
+    let cell = this.treeBox.getCellAt(event.clientX, event.clientY);
+    if (cell.col && cell.col.id == "enabled")
+      this.toggle(cell.row);
   },
 
   /*
    * Toggle enabled state of an engine.
    */
   toggle: function toggle(row) {
     // Update the tree
     let collection = this._collections[row];
--- a/browser/components/feeds/FeedWriter.js
+++ b/browser/components/feeds/FeedWriter.js
@@ -853,17 +853,16 @@ FeedWriter.prototype = {
            * Application" item is being selected with the keyboard. We do this
            * by ignoring command events while the dropdown is closed (user
            * arrowing through the combobox), but handling them while the
            * combobox dropdown is open (user pressed enter when an item was
            * selected). If we don't show the filepicker here, it will be shown
            * when clicking "Subscribe Now".
            */
           var popupbox = this._handlersMenuList.firstChild.boxObject;
-          popupbox.QueryInterface(Components.interfaces.nsIPopupBoxObject);
           if (popupbox.popupState == "hiding") {
             this._chooseClientApp(function(aResult) {
               if (!aResult) {
                 // Select the (per-prefs) selected handler if no application
                 // was selected
                 this._setSelectedHandler(this._getFeedType());
               }
             }.bind(this));
--- a/browser/components/places/content/sidebarUtils.js
+++ b/browser/components/places/content/sidebarUtils.js
@@ -5,66 +5,63 @@
 
 var SidebarUtils = {
   handleTreeClick: function SU_handleTreeClick(aTree, aEvent, aGutterSelect) {
     // right-clicks are not handled here
     if (aEvent.button == 2)
       return;
 
     var tbo = aTree.treeBoxObject;
-    var row = { }, col = { }, obj = { };
-    tbo.getCellAt(aEvent.clientX, aEvent.clientY, row, col, obj);
+    var cell = tbo.getCellAt(aEvent.clientX, aEvent.clientY);
 
-    if (row.value == -1 || obj.value == "twisty")
+    if (cell.row == -1 || cell.childElt == "twisty")
       return;
 
     var mouseInGutter = false;
     if (aGutterSelect) {
-      var x = { }, y = { }, w = { }, h = { };
-      tbo.getCoordsForCellItem(row.value, col.value, "image",
-                               x, y, w, h);
+      var rect = tbo.getCoordsForCellItem(cell.row, cell.col, "image");
       // getCoordsForCellItem returns the x coordinate in logical coordinates
       // (i.e., starting from the left and right sides in LTR and RTL modes,
       // respectively.)  Therefore, we make sure to exclude the blank area
       // before the tree item icon (that is, to the left or right of it in
       // LTR and RTL modes, respectively) from the click target area.
       var isRTL = window.getComputedStyle(aTree, null).direction == "rtl";
       if (isRTL)
-        mouseInGutter = aEvent.clientX > x.value;
+        mouseInGutter = aEvent.clientX > rect.x;
       else
-        mouseInGutter = aEvent.clientX < x.value;
+        mouseInGutter = aEvent.clientX < rect.y;
     }
 
 #ifdef XP_MACOSX
     var modifKey = aEvent.metaKey || aEvent.shiftKey;
 #else
     var modifKey = aEvent.ctrlKey || aEvent.shiftKey;
 #endif
 
-    var isContainer = tbo.view.isContainer(row.value);
+    var isContainer = tbo.view.isContainer(cell.row);
     var openInTabs = isContainer &&
                      (aEvent.button == 1 ||
                       (aEvent.button == 0 && modifKey)) &&
-                     PlacesUtils.hasChildURIs(tbo.view.nodeForTreeIndex(row.value), true);
+                     PlacesUtils.hasChildURIs(tbo.view.nodeForTreeIndex(cell.row), true);
 
     if (aEvent.button == 0 && isContainer && !openInTabs) {
-      tbo.view.toggleOpenState(row.value);
+      tbo.view.toggleOpenState(cell.row);
       return;
     }
     else if (!mouseInGutter && openInTabs &&
             aEvent.originalTarget.localName == "treechildren") {
-      tbo.view.selection.select(row.value);
+      tbo.view.selection.select(cell.row);
       PlacesUIUtils.openContainerNodeInTabs(aTree.selectedNode, aEvent, aTree);
     }
     else if (!mouseInGutter && !isContainer &&
              aEvent.originalTarget.localName == "treechildren") {
       // Clear all other selection since we're loading a link now. We must
       // do this *before* attempting to load the link since openURL uses
       // selection as an indication of which link to load.
-      tbo.view.selection.select(row.value);
+      tbo.view.selection.select(cell.row);
       PlacesUIUtils.openNodeWithEvent(aTree.selectedNode, aEvent, aTree);
     }
   },
 
   handleTreeKeyPress: function SU_handleTreeKeyPress(aEvent) {
     // XXX Bug 627901: Post Fx4, this method should take a tree parameter.
     let tree = aEvent.target;
     let node = tree.selectedNode;
@@ -79,24 +76,23 @@ var SidebarUtils = {
    * hovered over.
    */
   handleTreeMouseMove: function SU_handleTreeMouseMove(aEvent) {
     if (aEvent.target.localName != "treechildren")
       return;
 
     var tree = aEvent.target.parentNode;
     var tbo = tree.treeBoxObject;
-    var row = { }, col = { }, obj = { };
-    tbo.getCellAt(aEvent.clientX, aEvent.clientY, row, col, obj);
+    var cell = tbo.getCellAt(aEvent.clientX, aEvent.clientY);
 
-    // row.value is -1 when the mouse is hovering an empty area within the tree.
+    // cell.row is -1 when the mouse is hovering an empty area within the tree.
     // To avoid showing a URL from a previously hovered node for a currently
     // hovered non-url node, we must clear the moused-over URL in these cases.
-    if (row.value != -1) {
-      var node = tree.view.nodeForTreeIndex(row.value);
+    if (cell.row != -1) {
+      var node = tree.view.nodeForTreeIndex(cell.row);
       if (PlacesUtils.nodeIsURI(node))
         this.setMouseoverURL(node.uri);
       else
         this.setMouseoverURL("");
     }
     else
       this.setMouseoverURL("");
   },
--- a/browser/components/places/content/tree.xml
+++ b/browser/components/places/content/tree.xml
@@ -742,52 +742,50 @@
         this._controller.setDataTransfer(event);
         event.stopPropagation();
       ]]></handler>
 
       <handler event="dragover"><![CDATA[
         if (event.target.localName != "treechildren")
           return;
 
-        let row = { }, col = { }, child = { };
-        this.treeBoxObject.getCellAt(event.clientX, event.clientY,
-                                     row, col, child);
-        let node = row.value != -1 ?
-                   this.view.nodeForTreeIndex(row.value) :
+        let cell = this.treeBoxObject.getCellAt(event.clientX, event.clientY);
+        let node = cell.row != -1 ?
+                   this.view.nodeForTreeIndex(cell.row) :
                    this.result.root;
         // cache the dropTarget for the view
         PlacesControllerDragHelper.currentDropTarget = node;
 
         // We have to calculate the orientation since view.canDrop will use
         // it and we want to be consistent with the dropfeedback.
         let tbo = this.treeBoxObject;
         let rowHeight = tbo.rowHeight;
         let eventY = event.clientY - tbo.treeBody.boxObject.y -
-                     rowHeight * (row.value - tbo.getFirstVisibleRow());
+                     rowHeight * (cell.row - tbo.getFirstVisibleRow());
 
         let orientation = Ci.nsITreeView.DROP_BEFORE;
 
-        if (row.value == -1) {
+        if (cell.row == -1) {
           // If the row is not valid we try to insert inside the resultNode.
           orientation = Ci.nsITreeView.DROP_ON;
         }
         else if (PlacesUtils.nodeIsContainer(node) &&
                  eventY > rowHeight * 0.75) {
           // If we are below the 75% of a container the treeview we try
           // to drop after the node.
           orientation = Ci.nsITreeView.DROP_AFTER;
         }
         else if (PlacesUtils.nodeIsContainer(node) &&
                  eventY > rowHeight * 0.25) {
           // If we are below the 25% of a container the treeview we try
           // to drop inside the node.
           orientation = Ci.nsITreeView.DROP_ON;
         }
 
-        if (!this.view.canDrop(row.value, orientation, event.dataTransfer))
+        if (!this.view.canDrop(cell.row, orientation, event.dataTransfer))
           return;
 
         event.preventDefault();
         event.stopPropagation();
       ]]></handler>
 
       <handler event="dragend"><![CDATA[
         PlacesControllerDragHelper.currentDropTarget = null;
--- a/browser/components/places/tests/browser/browser_forgetthissite_single.js
+++ b/browser/components/places/tests/browser/browser_forgetthissite_single.js
@@ -57,17 +57,14 @@ function test() {
               organizer.removeEventListener("unload", arguments.callee, false);
               // Proceed
               funcNext();
             }, false);
             // Close Library window.
             organizer.close();
           }, true);
           // Get cell coordinates
-          var x = {}, y = {}, width = {}, height = {};
-          tree.treeBoxObject.getCoordsForCellItem(0, tree.columns[0], "text",
-                                                  x, y, width, height);
+          var rect = tree.treeBoxObject.getCoordsForCellItem(0, tree.columns[0], "text");
           // Initiate a context menu for the selected cell
-          EventUtils.synthesizeMouse(tree.body, x.value + width.value / 2, y.value + height.value / 2, {type: "contextmenu"}, organizer);
+          EventUtils.synthesizeMouse(tree.body, rect.x + rect.width / 2, rect.y + rect.height / 2, {type: "contextmenu"}, organizer);
     });
   }
 }
-
--- a/browser/components/places/tests/browser/browser_library_infoBox.js
+++ b/browser/components/places/tests/browser/browser_library_infoBox.js
@@ -47,17 +47,17 @@ gTests.push({
       isnot(childNode, null, "History node first child is not null.");
       PO._places.selectNode(childNode);
       checkInfoBoxSelected(PO);
       ok(infoBoxExpanderWrapper.hidden,
          "Expander button is hidden for history child node.");
       checkAddInfoFieldsCollapsed(PO);
 
       // open history item
-      var view = ContentTree.view.treeBoxObject.view;
+      var view = ContentTree.view.view;
       ok(view.rowCount > 0, "History item exists.");
       view.selection.select(0);
       ok(infoBoxExpanderWrapper.hidden,
          "Expander button is hidden for history item.");
       checkAddInfoFieldsCollapsed(PO);
 
       historyNode.containerOpen = false;
 
@@ -84,17 +84,17 @@ gTests.push({
          "Correctly selected recently bookmarked node.");
       PO._places.selectNode(childNode);
       checkInfoBoxSelected(PO);
       ok(!infoBoxExpanderWrapper.hidden,
          "Expander button is not hidden for recently bookmarked node.");
       checkAddInfoFieldsNotCollapsed(PO);
 
       // open first bookmark
-      var view = ContentTree.view.treeBoxObject.view;
+      var view = ContentTree.view.view;
       ok(view.rowCount > 0, "Bookmark item exists.");
       view.selection.select(0);
       checkInfoBoxSelected(PO);
       ok(!infoBoxExpanderWrapper.hidden,
          "Expander button is not hidden for bookmark item.");
       checkAddInfoFieldsNotCollapsed(PO);
       checkAddInfoFields(PO, "bookmark item");
 
--- a/browser/components/places/tests/browser/browser_library_middleclick.js
+++ b/browser/components/places/tests/browser/browser_library_middleclick.js
@@ -267,15 +267,13 @@ function runNextTest() {
 
 function mouseEventOnCell(aTree, aRowIndex, aColumnIndex, aEventDetails) {
   var selection = aTree.view.selection;
   selection.select(aRowIndex);
   aTree.treeBoxObject.ensureRowIsVisible(aRowIndex);
   var column = aTree.columns[aColumnIndex];
 
   // get cell coordinates
-  var x = {}, y = {}, width = {}, height = {};
-  aTree.treeBoxObject.getCoordsForCellItem(aRowIndex, column, "text",
-                                           x, y, width, height);
+  var rect = aTree.treeBoxObject.getCoordsForCellItem(aRowIndex, column, "text");
 
-  EventUtils.synthesizeMouse(aTree.body, x.value, y.value,
+  EventUtils.synthesizeMouse(aTree.body, rect.x, rect.y,
                              aEventDetails, gLibrary);
 }
--- a/browser/components/places/tests/browser/head.js
+++ b/browser/components/places/tests/browser/head.js
@@ -191,17 +191,15 @@ function synthesizeClickOnSelectedTreeCe
   if (tbo.view.selection.count != 1)
      throw new Error("The test node should be successfully selected");
   // Get selection rowID.
   let min = {}, max = {};
   tbo.view.selection.getRangeAt(0, min, max);
   let rowID = min.value;
   tbo.ensureRowIsVisible(rowID);
   // Calculate the click coordinates.
-  let x = {}, y = {}, width = {}, height = {};
-  tbo.getCoordsForCellItem(rowID, aTree.columns[0], "text",
-                           x, y, width, height);
-  x = x.value + width.value / 2;
-  y = y.value + height.value / 2;
+  var rect = tbo.getCoordsForCellItem(rowID, aTree.columns[0], "text");
+  var x = rect.x + rect.width / 2;
+  var y = rect.y + rect.height / 2;
   // Simulate the click.
   EventUtils.synthesizeMouse(aTree.body, x, y, aOptions || {},
                              aTree.ownerDocument.defaultView);
 }
--- a/browser/components/preferences/cookies.js
+++ b/browser/components/preferences/cookies.js
@@ -33,17 +33,17 @@ var gCookiesWindow = {
     var os = Components.classes["@mozilla.org/observer-service;1"]
                        .getService(Components.interfaces.nsIObserverService);
     os.removeObserver(this, "cookie-changed");
     os.removeObserver(this, "perm-changed");
   },
 
   _populateList: function (aInitialLoad) {
     this._loadCookies();
-    this._tree.treeBoxObject.view = this._view;
+    this._tree.view = this._view;
     if (aInitialLoad)
       this.sort("rawHost");
     if (this._view.rowCount > 0)
       this._tree.view.selection.select(0);
 
     if (aInitialLoad) {
       if ("arguments" in window &&
           window.arguments[0] &&
@@ -785,17 +785,17 @@ var gCookiesWindow = {
     // Clear the Tree Display
     this._view._filtered = false;
     this._view._rowCount = 0;
     this._tree.treeBoxObject.rowCountChanged(0, -this._view._filterSet.length);
     this._view._filterSet = [];
 
     // Just reload the list to make sure deletions are respected
     this._loadCookies();
-    this._tree.treeBoxObject.view = this._view;
+    this._tree.view = this._view;
 
     // Restore sort order
     var sortby = this._lastSortProperty;
     if (sortby == "") {
       this._lastSortAscending = false;
       this.sort("rawHost");
     }
     else {
--- a/browser/components/preferences/permissions.js
+++ b/browser/components/preferences/permissions.js
@@ -327,17 +327,17 @@ var gPermissionManager = {
     while (enumerator.hasMoreElements()) {
       var nextPermission = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
       this._addPermissionToList(nextPermission);
     }
    
     this._view._rowCount = this._permissions.length;
 
     // sort and display the table
-    this._tree.treeBoxObject.view = this._view;
+    this._tree.view = this._view;
     this.onPermissionSort("rawHost", false);
 
     // disable "remove all" button if there are none
     document.getElementById("removeAllPermissions").disabled = this._permissions.length == 0;
   },
   
   _addPermissionToList: function (aPermission)
   {
@@ -365,9 +365,8 @@ function setHost(aHost)
 {
   gPermissionManager.setHost(aHost);
 }
 
 function initWithParams(aParams)
 {
   gPermissionManager.init(aParams);
 }
-
--- a/browser/components/preferences/tests/browser_bug705422.js
+++ b/browser/components/preferences/tests/browser_bug705422.js
@@ -77,34 +77,33 @@ function runTest(win, searchTerm, cookie
 
     // "delete all cookies" should be enabled
     isDisabled(win, false);
 
 
     // select first cookie and delete
     var tree = win.document.getElementById("cookiesList");
     var deleteButton = win.document.getElementById("removeCookie");
-    var x = {}, y = {}, width = {}, height = {};
-    tree.treeBoxObject.getCoordsForCellItem(0, tree.columns[0], "cell", x, y, width, height);
-    EventUtils.synthesizeMouse(tree.body, x.value + width.value / 2, y.value + height.value / 2, {}, win);
+    var rect = tree.treeBoxObject.getCoordsForCellItem(0, tree.columns[0], "cell");
+    EventUtils.synthesizeMouse(tree.body, rect.x + rect.width / 2, rect.y + rect.height / 2, {}, win);
     EventUtils.synthesizeMouseAtCenter(deleteButton, {}, win);
 
     // count cookies should be matches-1
     is(win.gCookiesWindow._view.rowCount, matches-1, "Deleted selected cookie");
 
     // select two adjacent cells and delete
-    EventUtils.synthesizeMouse(tree.body, x.value + width.value / 2, y.value + height.value / 2, {}, win);
+    EventUtils.synthesizeMouse(tree.body, rect.x + rect.width / 2, rect.y + rect.height / 2, {}, win);
     deleteButton = win.document.getElementById("removeCookies"); 
     var eventObj = {};
     if (navigator.platform.indexOf("Mac") >= 0)
         eventObj.metaKey = true;
     else
         eventObj.ctrlKey = true;
-    tree.treeBoxObject.getCoordsForCellItem(1, tree.columns[0], "cell", x, y, width, height);
-    EventUtils.synthesizeMouse(tree.body, x.value + width.value / 2, y.value + height.value / 2, eventObj, win);
+    rect = tree.treeBoxObject.getCoordsForCellItem(1, tree.columns[0], "cell");
+    EventUtils.synthesizeMouse(tree.body, rect.x + rect.width / 2, rect.y + rect.height / 2, eventObj, win);
     EventUtils.synthesizeMouseAtCenter(deleteButton, {}, win);
 
     // count cookies should be matches-3
     is(win.gCookiesWindow._view.rowCount, matches-3, "Deleted selected two adjacent cookies");
 
     // "delete all cookies" should be enabled
     isDisabled(win, false);
 
--- a/browser/components/preferences/translation.js
+++ b/browser/components/preferences/translation.js
@@ -15,17 +15,17 @@ XPCOMUtils.defineLazyGetter(this, "gLang
 
 const kPermissionType = "translate";
 const kLanguagesPref = "browser.translation.neverForLanguages";
 
 function Tree(aId, aData)
 {
   this._data = aData;
   this._tree = document.getElementById(aId);
-  this._tree.treeBoxObject.view = this;
+  this._tree.view = this;
 }
 
 Tree.prototype = {
   get boxObject() this._tree.treeBoxObject,
   get isEmpty() !this._data.length,
   get hasSelection() this.selection.count > 0,
   getSelectedItems: function() {
     let result = [];
--- a/browser/components/search/test/browser_405664.js
+++ b/browser/components/search/test/browser_405664.js
@@ -1,16 +1,16 @@
 function test() {
   var searchBar = BrowserSearch.searchBar;
   ok(searchBar, "got search bar");
   
   searchBar.focus();
 
   var pbo = searchBar._popup.popupBoxObject;
-  ok(pbo, "popup is nsIPopupBoxObject");
+  ok(pbo, "popup is PopupBoxObject");
 
   EventUtils.synthesizeKey("VK_UP", { altKey: true });
   is(pbo.popupState, "showing", "popup is opening after Alt+Up");
 
   EventUtils.synthesizeKey("VK_ESCAPE", {});
   is(pbo.popupState, "closed", "popup is closed after ESC");
 
   EventUtils.synthesizeKey("VK_DOWN", { altKey: true });
--- a/browser/components/sessionstore/content/aboutSessionRestore.js
+++ b/browser/components/sessionstore/content/aboutSessionRestore.js
@@ -139,34 +139,33 @@ function startNewSession() {
     getBrowserWindow().BrowserHome();
 }
 
 function onListClick(aEvent) {
   // don't react to right-clicks
   if (aEvent.button == 2)
     return;
 
-  var row = {}, col = {};
-  treeView.treeBox.getCellAt(aEvent.clientX, aEvent.clientY, row, col, {});
-  if (col.value) {
+  var cell = treeView.treeBox.getCellAt(aEvent.clientX, aEvent.clientY);
+  if (cell.col) {
     // Restore this specific tab in the same window for middle/double/accel clicking
     // on a tab's title.
 #ifdef XP_MACOSX
     let accelKey = aEvent.metaKey;
 #else
     let accelKey = aEvent.ctrlKey;
 #endif
     if ((aEvent.button == 1 || aEvent.button == 0 && aEvent.detail == 2 || accelKey) &&
-        col.value.id == "title" &&
-        !treeView.isContainer(row.value)) {
-      restoreSingleTab(row.value, aEvent.shiftKey);
+        cell.col.id == "title" &&
+        !treeView.isContainer(cell.row)) {
+      restoreSingleTab(cell.row, aEvent.shiftKey);
       aEvent.stopPropagation();
     }
-    else if (col.value.id == "restore")
-      toggleRowChecked(row.value);
+    else if (cell.col.id == "restore")
+      toggleRowChecked(cell.row);
   }
 }
 
 function onListKeyDown(aEvent) {
   switch (aEvent.keyCode)
   {
   case KeyEvent.DOM_VK_SPACE:
     toggleRowChecked(document.getElementById("tabList").currentIndex);
--- a/browser/components/sessionstore/test/browser_590563.js
+++ b/browser/components/sessionstore/test/browser_590563.js
@@ -33,25 +33,23 @@ function test() {
   });
 }
 
 function middleClickTest(win) {
   let browser = win.gBrowser.selectedBrowser;
   let tree = browser.contentDocument.getElementById("tabList");
   is(tree.view.rowCount, 3, "There should be three items");
 
-  let x = {}, y = {}, width = {}, height = {};
-
   // click on the first tab item
-  tree.treeBoxObject.getCoordsForCellItem(1, tree.columns[1], "text", x, y, width, height);
-  EventUtils.synthesizeMouse(tree.body, x.value, y.value, { button: 1 },
+  var rect = tree.treeBoxObject.getCoordsForCellItem(1, tree.columns[1], "text");
+  EventUtils.synthesizeMouse(tree.body, rect.x, rect.y, { button: 1 },
                              browser.contentWindow);
   // click on the second tab item
-  tree.treeBoxObject.getCoordsForCellItem(2, tree.columns[1], "text", x, y, width, height);
-  EventUtils.synthesizeMouse(tree.body, x.value, y.value, { button: 1 },
+  rect = tree.treeBoxObject.getCoordsForCellItem(2, tree.columns[1], "text");
+  EventUtils.synthesizeMouse(tree.body, rect.x, rect.y, { button: 1 },
                              browser.contentWindow);
 
   is(win.gBrowser.tabs.length, 3,
      "The total number of tabs should be 3 after restoring 2 tabs by middle click.");
   is(win.gBrowser.visibleTabs.length, 3,
      "The total number of visible tabs should be 3 after restoring 2 tabs by middle click");
 }
 
--- a/browser/devtools/shared/widgets/FastListWidget.js
+++ b/browser/devtools/shared/widgets/FastListWidget.js
@@ -190,17 +190,17 @@ FastListWidget.prototype = {
    *        The element to make visible.
    */
   ensureElementIsVisible: function(element) {
     if (!element) {
       return;
     }
 
     // Ensure the element is visible but not scrolled horizontally.
-    let boxObject = this._list.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
+    let boxObject = this._list.boxObject;
     boxObject.ensureElementIsVisible(element);
     boxObject.scrollBy(-this._list.clientWidth, 0);
   },
 
   /**
    * Sets the text displayed in this container when empty.
    * @param string aValue
    */
--- a/browser/devtools/shared/widgets/SideMenuWidget.jsm
+++ b/browser/devtools/shared/widgets/SideMenuWidget.jsm
@@ -209,17 +209,17 @@ SideMenuWidget.prototype = {
    *        The element to make visible.
    */
   ensureElementIsVisible: function(aElement) {
     if (!aElement) {
       return;
     }
 
     // Ensure the element is visible but not scrolled horizontally.
-    let boxObject = this._list.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
+    let boxObject = this._list.boxObject;
     boxObject.ensureElementIsVisible(aElement);
     boxObject.scrollBy(-this._list.clientWidth, 0);
   },
 
   /**
    * Shows all the groups, even the ones with no visible children.
    */
   showEmptyGroups: function() {
--- a/browser/devtools/shared/widgets/SimpleListWidget.jsm
+++ b/browser/devtools/shared/widgets/SimpleListWidget.jsm
@@ -166,17 +166,17 @@ SimpleListWidget.prototype = {
    *        The element to make visible.
    */
   ensureElementIsVisible: function(aElement) {
     if (!aElement) {
       return;
     }
 
     // Ensure the element is visible but not scrolled horizontally.
-    let boxObject = this._list.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
+    let boxObject = this._list.boxObject;
     boxObject.ensureElementIsVisible(aElement);
     boxObject.scrollBy(-this._list.clientWidth, 0);
   },
 
   /**
    * Sets the text displayed permanently in this container as a header.
    * @param string aValue
    */
--- a/browser/devtools/shared/widgets/VariablesView.jsm
+++ b/browser/devtools/shared/widgets/VariablesView.jsm
@@ -982,17 +982,17 @@ VariablesView.prototype = {
       this._parent.removeAttribute("actions-first");
     }
   },
 
   /**
    * Gets the parent node holding this view.
    * @return nsIDOMNode
    */
-  get boxObject() this._list.boxObject.QueryInterface(Ci.nsIScrollBoxObject),
+  get boxObject() this._list.boxObject,
 
   /**
    * Gets the parent node holding this view.
    * @return nsIDOMNode
    */
   get parentNode() this._parent,
 
   /**
--- a/browser/metro/base/content/bindings/bindings.xml
+++ b/browser/metro/base/content/bindings/bindings.xml
@@ -20,24 +20,21 @@
     <handlers>
       <handler event="scroll">
         <![CDATA[
           // if there no more items to insert, just return early
           if (this._items.length == 0)
             return;
 
           if (this._contentScrollHeight == -1) {
-            let scrollheight = {};
-            this.scrollBoxObject.getScrolledSize({}, scrollheight);
-            this._contentScrollHeight = scrollheight.value;
+            this._contentScrollHeight = this.scrollBoxObject.scrolledHeight;
           }
 
-          let y = {};
-          this.scrollBoxObject.getPosition({}, y);
-          let scrollRatio = (y.value + this._childrenHeight) / this._contentScrollHeight;
+          let y = this.scrollBoxObject.positionY;
+          let scrollRatio = (y + this._childrenHeight) / this._contentScrollHeight;
 
           // If we're scrolled 80% to the bottom of the list, append the next
           // set of items
           if (scrollRatio > 0.8)
             this._insertItems();
         ]]>
       </handler>
     </handlers>
--- a/browser/metro/base/content/input.js
+++ b/browser/metro/base/content/input.js
@@ -470,27 +470,27 @@ var ScrollUtils = {
     // if element is content or the startui page, get the browser scroll interface
     if (elem.ownerDocument == Browser.selectedBrowser.contentDocument) {
       elem = Browser.selectedBrowser;
     }
     for (; elem; elem = elem.parentNode) {
       try {
         if (elem.anonScrollBox) {
           scrollbox = elem.anonScrollBox;
-          qinterface = scrollbox.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
+          qinterface = scrollbox.boxObject;
         } else if (elem.scrollBoxObject) {
           scrollbox = elem;
           qinterface = elem.scrollBoxObject;
           break;
         } else if (elem.customDragger) {
           scrollbox = elem;
           break;
         } else if (elem.boxObject) {
           let qi = (elem._cachedSBO) ? elem._cachedSBO
-                                     : elem.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
+                                     : elem.boxObject;
           if (qi) {
             scrollbox = elem;
             scrollbox._cachedSBO = qinterface = qi;
             break;
           }
         }
       } catch (e) { /* we aren't here to deal with your exceptions, we'll just keep
                        traversing until we find something more well-behaved, as we
@@ -507,50 +507,43 @@ var ScrollUtils = {
 
   /**
    * The default dragger object used by TouchModule when dragging a scrollable
    * element that provides no customDragger.  Simply performs the expected
    * regular scrollBy calls on the scroller.
    */
   _defaultDragger: {
     isDraggable: function isDraggable(target, scroller) {
-      let sX = {}, sY = {},
-          pX = {}, pY = {};
-      scroller.getPosition(pX, pY);
-      scroller.getScrolledSize(sX, sY);
       let rect = target.getBoundingClientRect();
-      return { x: (sX.value > rect.width  || pX.value != 0),
-               y: (sY.value > rect.height || pY.value != 0) };
+      return { x: (scroller.scrolledWidth > rect.width   || scroller.positionX != 0),
+               y: (scroller.scrolledHeight > rect.height || scroller.positionY != 0) };
     },
 
     dragStart: function dragStart(cx, cy, target, scroller) {
       scroller.element.addEventListener("PanBegin", this._showScrollbars, false);
     },
 
     dragStop: function dragStop(dx, dy, scroller) {
       scroller.element.removeEventListener("PanBegin", this._showScrollbars, false);
       return this.dragMove(dx, dy, scroller);
     },
 
     dragMove: function dragMove(dx, dy, scroller) {
-      if (scroller.getPosition) {
         try {
-          let oldX = {}, oldY = {};
-          scroller.getPosition(oldX, oldY);
+        let oldX = scroller.positionX,
+            oldY = scroller.positionY;
 
           scroller.scrollBy(dx, dy);
 
-          let newX = {}, newY = {};
-          scroller.getPosition(newX, newY);
+        let newX = scroller.positionX,
+            newY = scroller.positionY;
 
-          return (newX.value != oldX.value) || (newY.value != oldY.value);
+        return (newX != oldX) || (newY != oldY);
 
         } catch (e) { /* we have no time for whiny scrollers! */ }
-      }
-
       return false;
     },
 
     _showScrollbars: function _showScrollbars(aEvent) {
       let scrollbox = aEvent.target;
       scrollbox.setAttribute("panning", "true");
 
       let hideScrollbars = function() {
--- a/browser/modules/UITour.jsm
+++ b/browser/modules/UITour.jsm
@@ -1016,17 +1016,17 @@ this.UITour = {
     function openMenuButton(aID) {
       let menuBtn = aWindow.document.getElementById(aID);
       if (!menuBtn || !menuBtn.boxObject) {
         aOpenCallback();
         return;
       }
       if (aOpenCallback)
         menuBtn.addEventListener("popupshown", onPopupShown);
-      menuBtn.boxObject.QueryInterface(Ci.nsIMenuBoxObject).openMenu(true);
+      menuBtn.boxObject.openMenu(true);
     }
     function onPopupShown(event) {
       this.removeEventListener("popupshown", onPopupShown);
       aOpenCallback(event);
     }
 
     if (aMenuName == "appMenu") {
       aWindow.PanelUI.panel.setAttribute("noautohide", "true");
@@ -1044,17 +1044,17 @@ this.UITour = {
       openMenuButton("bookmarks-menu-button");
     }
   },
 
   hideMenu: function(aWindow, aMenuName) {
     function closeMenuButton(aID) {
       let menuBtn = aWindow.document.getElementById(aID);
       if (menuBtn && menuBtn.boxObject)
-        menuBtn.boxObject.QueryInterface(Ci.nsIMenuBoxObject).openMenu(false);
+        menuBtn.boxObject.openMenu(false);
     }
 
     if (aMenuName == "appMenu") {
       aWindow.PanelUI.panel.removeAttribute("noautohide");
       aWindow.PanelUI.hide();
       this.recreatePopup(aWindow.PanelUI.panel);
     } else if (aMenuName == "bookmarks") {
       closeMenuButton("bookmarks-menu-button");
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -33,17 +33,16 @@ class nsIDocShell;
 class nsDocShell;
 class nsDOMNavigationTiming;
 class nsFrameLoader;
 class nsHTMLCSSStyleSheet;
 class nsHTMLDocument;
 class nsHTMLStyleSheet;
 class nsIAtom;
 class nsIBFCacheEntry;
-class nsIBoxObject;
 class nsIChannel;
 class nsIContent;
 class nsIContentSink;
 class nsIDocShell;
 class nsIDocumentEncoder;
 class nsIDocumentObserver;
 class nsIDOMDocument;
 class nsIDOMDocumentFragment;
@@ -90,16 +89,17 @@ class SVGAttrAnimationRuleProcessor;
 namespace css {
 class Loader;
 class ImageLoader;
 } // namespace css
 
 namespace dom {
 class AnimationTimeline;
 class Attr;
+class BoxObject;
 class CDATASection;
 class Comment;
 struct CustomElementDefinition;
 class DocumentFragment;
 class DocumentType;
 class DOMImplementation;
 class DOMStringList;
 class Element;
@@ -1495,17 +1495,17 @@ public:
    * @param aElement canonical nsIContent pointer of the box object's element
    */
   virtual void ClearBoxObjectFor(nsIContent *aContent) = 0;
 
   /**
    * Get the box object for an element. This is not exposed through a
    * scriptable interface except for XUL documents.
    */
-  virtual already_AddRefed<nsIBoxObject>
+  virtual already_AddRefed<mozilla::dom::BoxObject>
     GetBoxObjectFor(mozilla::dom::Element* aElement,
                     mozilla::ErrorResult& aRv) = 0;
 
   /**
    * Get the compatibility mode for this document
    */
   nsCompatibility GetCompatibilityMode() const {
     return mCompatMode;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -215,16 +215,17 @@
 #include "nsIDocumentActivity.h"
 #include "nsIStructuredCloneContainer.h"
 #include "nsIMutableArray.h"
 #include "nsContentPermissionHelper.h"
 #include "mozilla/dom/DOMStringList.h"
 #include "nsWindowMemoryReporter.h"
 #include "nsLocation.h"
 #include "mozilla/dom/FontFaceSet.h"
+#include "mozilla/dom/BoxObject.h"
 
 #ifdef MOZ_MEDIA_NAVIGATOR
 #include "mozilla/MediaManager.h"
 #endif // MOZ_MEDIA_NAVIGATOR
 #ifdef MOZ_WEBRTC
 #include "IPeerConnection.h"
 #endif // MOZ_WEBRTC
 
@@ -6942,17 +6943,17 @@ nsDocument::DoNotifyPossibleTitleChange(
   }
 
   // Fire a DOM event for the title change.
   nsContentUtils::DispatchChromeEvent(this, static_cast<nsIDocument*>(this),
                                       NS_LITERAL_STRING("DOMTitleChanged"),
                                       true, true);
 }
 
-already_AddRefed<nsIBoxObject>
+already_AddRefed<BoxObject>
 nsDocument::GetBoxObjectFor(Element* aElement, ErrorResult& aRv)
 {
   if (!aElement) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsIDocument* doc = aElement->OwnerDoc();
@@ -6969,17 +6970,17 @@ nsDocument::GetBoxObjectFor(Element* aEl
                                     "UseOfGetBoxObjectForWarning");
   }
 
   if (!mBoxObjectTable) {
     mBoxObjectTable = new nsInterfaceHashtable<nsPtrHashKey<nsIContent>, nsPIBoxObject>(6);
   } else {
     nsCOMPtr<nsPIBoxObject> boxObject = mBoxObjectTable->Get(aElement);
     if (boxObject) {
-      return boxObject.forget();
+      return boxObject.forget().downcast<BoxObject>();
     }
   }
 
   int32_t namespaceID;
   nsCOMPtr<nsIAtom> tag = BindingManager()->ResolveTag(aElement, &namespaceID);
 
   nsAutoCString contractID("@mozilla.org/layout/xul-boxobject");
   if (namespaceID == kNameSpaceID_XUL) {
@@ -7010,17 +7011,17 @@ nsDocument::GetBoxObjectFor(Element* aEl
   }
 
   boxObject->Init(aElement);
 
   if (mBoxObjectTable) {
     mBoxObjectTable->Put(aElement, boxObject.get());
   }
 
-  return boxObject.forget();
+  return boxObject.forget().downcast<BoxObject>();
 }
 
 void
 nsDocument::ClearBoxObjectFor(nsIContent* aContent)
 {
   if (mBoxObjectTable) {
     nsPIBoxObject *boxObject = mBoxObjectTable->GetWeak(aContent);
     if (boxObject) {
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -25,18 +25,16 @@
 #include "nsStubDocumentObserver.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIContent.h"
 #include "nsIPrincipal.h"
 #include "nsIParser.h"
 #include "nsBindingManager.h"
 #include "nsInterfaceHashtable.h"
 #include "nsJSThingHashtable.h"
-#include "nsIBoxObject.h"
-#include "nsPIBoxObject.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIURI.h"
 #include "nsScriptLoader.h"
 #include "nsIRadioGroupContainer.h"
 #include "nsILayoutHistoryState.h"
 #include "nsIRequest.h"
 #include "nsILoadGroup.h"
 #include "nsTObserverArray.h"
@@ -90,20 +88,22 @@ class nsChildContentList;
 class nsHTMLStyleSheet;
 class nsHTMLCSSStyleSheet;
 class nsDOMNavigationTiming;
 class nsWindowSizes;
 class nsHtml5TreeOpExecutor;
 class nsDocumentOnStack;
 class nsPointerLockPermissionRequest;
 class nsISecurityConsoleMessage;
+class nsPIBoxObject;
 
 namespace mozilla {
 class EventChainPreVisitor;
 namespace dom {
+class BoxObject;
 class UndoManager;
 struct LifecycleCallbacks;
 class CallbackFunction;
 }
 }
 
 /**
  * Right now our identifier map entries contain information for 'name'
@@ -997,18 +997,20 @@ public:
 
   virtual void BlockOnload();
   virtual void UnblockOnload(bool aFireSync);
 
   virtual void AddStyleRelevantLink(mozilla::dom::Link* aLink);
   virtual void ForgetLink(mozilla::dom::Link* aLink);
 
   void ClearBoxObjectFor(nsIContent* aContent);
-  already_AddRefed<nsIBoxObject> GetBoxObjectFor(mozilla::dom::Element* aElement,
-                                                 mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
+
+  virtual already_AddRefed<mozilla::dom::BoxObject>
+  GetBoxObjectFor(mozilla::dom::Element* aElement,
+                  mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
 
   virtual Element*
     GetAnonymousElementByAttribute(nsIContent* aElement,
                                    nsIAtom* aAttrName,
                                    const nsAString& aAttrValue) const;
 
   virtual Element* ElementFromPointHelper(float aX, float aY,
                                                       bool aIgnoreRootScrollFrame,
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -68,17 +68,17 @@
 #include "nsXULControllers.h"
 #include "nsIBoxObject.h"
 #include "nsPIBoxObject.h"
 #include "XULDocument.h"
 #include "nsXULPopupListener.h"
 #include "nsRuleWalker.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsCSSParser.h"
-#include "nsIListBoxObject.h"
+#include "ListBoxObject.h"
 #include "nsContentUtils.h"
 #include "nsContentList.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/MouseEvents.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsPIDOMWindow.h"
 #include "nsJSPrincipals.h"
 #include "nsDOMAttributeMap.h"
@@ -104,16 +104,17 @@
 #include "nsXBLBinding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozAutoDocUpdate.h"
 #include "nsIDOMXULCommandEvent.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsICSSDeclaration.h"
 
 #include "mozilla/dom/XULElementBinding.h"
+#include "mozilla/dom/BoxObject.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
 uint32_t             nsXULPrototypeAttribute::gNumElements;
 uint32_t             nsXULPrototypeAttribute::gNumAttributes;
 uint32_t             nsXULPrototypeAttribute::gNumCacheTests;
@@ -1500,17 +1501,17 @@ nsXULElement::GetControllers(ErrorResult
 NS_IMETHODIMP
 nsXULElement::GetBoxObject(nsIBoxObject** aResult)
 {
     ErrorResult rv;
     *aResult = GetBoxObject(rv).take();
     return rv.ErrorCode();
 }
 
-already_AddRefed<nsIBoxObject>
+already_AddRefed<BoxObject>
 nsXULElement::GetBoxObject(ErrorResult& rv)
 {
     // XXX sXBL/XBL2 issue! Owner or current document?
     return OwnerDoc()->GetBoxObjectFor(this, rv);
 }
 
 // Methods for setting/getting attributes from nsIDOMXULElement
 #define NS_IMPL_XUL_STRING_ATTR(_method, _atom)                     \
--- a/content/xul/content/src/nsXULElement.h
+++ b/content/xul/content/src/nsXULElement.h
@@ -21,17 +21,16 @@
 #include "nsIControllers.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsIRDFCompositeDataSource.h"
 #include "nsIRDFResource.h"
 #include "nsIURI.h"
 #include "nsIXULTemplateBuilder.h"
-#include "nsIBoxObject.h"
 #include "nsLayoutCID.h"
 #include "nsAttrAndChildArray.h"
 #include "nsGkAtoms.h"
 #include "nsAutoPtr.h"
 #include "nsStyledElement.h"
 #include "nsIFrameLoader.h"
 #include "nsFrameLoader.h"
 #include "mozilla/dom/DOMRect.h"
@@ -49,16 +48,19 @@ class nsXULPrototypeNode;
 typedef nsTArray<nsRefPtr<nsXULPrototypeNode> > nsPrototypeArray;
 
 namespace mozilla {
 class EventChainPreVisitor;
 class EventListenerManager;
 namespace css {
 class StyleRule;
 }
+namespace dom {
+class BoxObject;
+}
 }
 
 namespace JS {
 class SourceBufferHolder;
 }
 
 ////////////////////////////////////////////////////////////////////////
 
@@ -582,17 +584,17 @@ public:
     bool AllowEvents() const
     {
         return BoolAttrIsTrue(nsGkAtoms::allowevents);
     }
     already_AddRefed<nsIRDFCompositeDataSource> GetDatabase();
     already_AddRefed<nsIXULTemplateBuilder> GetBuilder();
     already_AddRefed<nsIRDFResource> GetResource(mozilla::ErrorResult& rv);
     nsIControllers* GetControllers(mozilla::ErrorResult& rv);
-    already_AddRefed<nsIBoxObject> GetBoxObject(mozilla::ErrorResult& rv);
+    already_AddRefed<mozilla::dom::BoxObject> GetBoxObject(mozilla::ErrorResult& rv);
     void Focus(mozilla::ErrorResult& rv);
     void Blur(mozilla::ErrorResult& rv);
     void Click(mozilla::ErrorResult& rv);
     // The XPCOM DoCommand never fails, so it's OK for us.
     already_AddRefed<nsINodeList>
       GetElementsByAttribute(const nsAString& aAttribute,
                              const nsAString& aValue);
     already_AddRefed<nsINodeList>
--- a/content/xul/document/src/XULDocument.cpp
+++ b/content/xul/document/src/XULDocument.cpp
@@ -39,16 +39,17 @@
 #include "nsXMLContentSink.h"
 #include "nsXULContentSink.h"
 #include "nsXULContentUtils.h"
 #include "nsIXULOverlayProvider.h"
 #include "nsIStringEnumerator.h"
 #include "nsNetUtil.h"
 #include "nsParserCIID.h"
 #include "nsPIBoxObject.h"
+#include "mozilla/dom/BoxObject.h"
 #include "nsXPIDLString.h"
 #include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
 #include "nsXULCommandDispatcher.h"
 #include "nsXULElement.h"
 #include "prlog.h"
 #include "rdf.h"
 #include "nsIFrame.h"
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -81,17 +81,16 @@
 #include "nsIDOMCSSSupportsRule.h"
 #include "nsIDOMMozCSSKeyframeRule.h"
 #include "nsIDOMMozCSSKeyframesRule.h"
 #include "nsIDOMCSSCounterStyleRule.h"
 #include "nsIDOMCSSPageRule.h"
 #include "nsIDOMCSSStyleRule.h"
 #include "nsIDOMXULCommandDispatcher.h"
 #include "nsIControllers.h"
-#include "nsIBoxObject.h"
 #ifdef MOZ_XUL
 #include "nsITreeSelection.h"
 #include "nsITreeContentView.h"
 #include "nsITreeView.h"
 #include "nsIXULTemplateBuilder.h"
 #include "nsITreeColumns.h"
 #endif
 #include "nsIDOMXPathNSResolver.h"
@@ -246,18 +245,16 @@ static nsDOMClassInfoData sClassInfoData
 
   // XUL classes
 #ifdef MOZ_XUL
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULCommandDispatcher, nsDOMGenericSH,
                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULControllers, nsNonDOMObjectSH,
                                       DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(BoxObject, nsDOMGenericSH,
-                                      DEFAULT_SCRIPTABLE_FLAGS)
 #ifdef MOZ_XUL
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(TreeSelection, nsDOMGenericSH,
                                       DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(TreeContentView, nsDOMGenericSH,
                                       DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
 #ifdef MOZ_XUL
@@ -691,20 +688,16 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULCommandDispatcher)
   DOM_CLASSINFO_MAP_END
 #endif
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULControllers, nsIControllers)
     DOM_CLASSINFO_MAP_ENTRY(nsIControllers)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(BoxObject, nsIBoxObject)
-    DOM_CLASSINFO_MAP_ENTRY(nsIBoxObject)
-  DOM_CLASSINFO_MAP_END
-
 #ifdef MOZ_XUL
   DOM_CLASSINFO_MAP_BEGIN(TreeSelection, nsITreeSelection)
     DOM_CLASSINFO_MAP_ENTRY(nsITreeSelection)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(TreeContentView, nsITreeContentView)
     DOM_CLASSINFO_MAP_ENTRY(nsITreeContentView)
     DOM_CLASSINFO_MAP_ENTRY(nsITreeView)
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -14,17 +14,16 @@ DOMCI_CLASS(CSSImportRule)
 DOMCI_CLASS(CSSMediaRule)
 DOMCI_CLASS(CSSNameSpaceRule)
 
 // XUL classes
 #ifdef MOZ_XUL
 DOMCI_CLASS(XULCommandDispatcher)
 #endif
 DOMCI_CLASS(XULControllers)
-DOMCI_CLASS(BoxObject)
 #ifdef MOZ_XUL
 DOMCI_CLASS(TreeSelection)
 DOMCI_CLASS(TreeContentView)
 #endif
 
 #ifdef MOZ_XUL
 DOMCI_CLASS(XULTemplateBuilder)
 DOMCI_CLASS(XULTreeBuilder)
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -170,16 +170,20 @@ DOMInterfaces = {
     'nativeType': 'mozilla::dom::bluetooth::BluetoothPairingHandle',
 },
 
 'BluetoothPairingListener': {
     'nativeType':
       'mozilla::dom::bluetooth::BluetoothPairingListener',
 },
 
+'BoxObject': {
+    'resultNotAddRefed': ['element'],
+},
+
 'CameraCapabilities': {
     'nativeType': 'mozilla::dom::CameraCapabilities',
     'headerFile': 'DOMCameraCapabilities.h'
 },
 
 'CameraControl': {
     'nativeType': 'mozilla::nsDOMCameraControl',
     'headerFile': 'DOMCameraControl.h',
@@ -861,16 +865,20 @@ DOMInterfaces = {
     'headerFile' : 'nsPluginArray.h',
     'nativeType': 'nsPluginElement',
 },
 
 'PluginArray': {
     'nativeType': 'nsPluginArray',
 },
 
+'PopupBoxObject': {
+    'resultNotAddRefed': ['triggerNode', 'anchorNode'],
+},
+
 'Position': {
     'headerFile': 'nsGeoPosition.h'
 },
 
 'PositionError': {
     'headerFile': 'nsGeolocation.h'
 },
 
@@ -1797,31 +1805,30 @@ def addExternalIface(iface, nativeType=N
 addExternalIface('ApplicationCache', nativeType='nsIDOMOfflineResourceList')
 addExternalIface('Counter')
 addExternalIface('CSSRule')
 addExternalIface('RTCDataChannel', nativeType='nsIDOMDataChannel')
 addExternalIface('HitRegionOptions', nativeType='nsISupports')
 addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserver')
 addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True)
 addExternalIface('MenuBuilder', nativeType='nsIMenuBuilder', notflattened=True)
-addExternalIface('MozBoxObject', nativeType='nsIBoxObject')
 addExternalIface('MozControllers', nativeType='nsIControllers')
 addExternalIface('MozFrameLoader', nativeType='nsIFrameLoader', notflattened=True)
 addExternalIface('MozFrameRequestCallback', nativeType='nsIFrameRequestCallback',
                  notflattened=True)
 addExternalIface('MozMmsMessage')
 addExternalIface('MozObserver', nativeType='nsIObserver', notflattened=True)
 addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSource',
                  notflattened=True)
 addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True)
 addExternalIface('MozSmsMessage')
-addExternalIface('MozTreeBoxObject', nativeType='nsITreeBoxObject',
-                 notflattened=True)
 addExternalIface('MozTreeColumn', nativeType='nsITreeColumn',
                  headerFile='nsITreeColumns.h')
+addExternalIface('MozTreeView', nativeType='nsITreeView',
+                  headerFile='nsITreeView.h')
 addExternalIface('MozWakeLockListener', headerFile='nsIDOMWakeLockListener.h')
 addExternalIface('MozXULTemplateBuilder', nativeType='nsIXULTemplateBuilder')
 addExternalIface('nsIBrowserDOMWindow', nativeType='nsIBrowserDOMWindow',
                  notflattened=True)
 addExternalIface('nsIControllers', nativeType='nsIControllers')
 addExternalIface('nsIDOMCrypto', nativeType='nsIDOMCrypto',
                  headerFile='Crypto.h')
 addExternalIface('nsIInputStreamCallback', nativeType='nsIInputStreamCallback',
@@ -1830,16 +1837,17 @@ addExternalIface('nsIFile', nativeType='
 addExternalIface('nsIMessageBroadcaster', nativeType='nsIMessageBroadcaster',
                  headerFile='nsIMessageManager.h', notflattened=True)
 addExternalIface('nsISelectionListener', nativeType='nsISelectionListener')
 addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True)
 addExternalIface('nsISupports', nativeType='nsISupports')
 addExternalIface('nsIDocShell', nativeType='nsIDocShell', notflattened=True)
 addExternalIface('nsIEditor', nativeType='nsIEditor', notflattened=True)
 addExternalIface('nsIVariant', nativeType='nsIVariant', notflattened=True)
+addExternalIface('nsIScriptableRegion', nativeType='nsIScriptableRegion', notflattened=True)
 addExternalIface('OutputStream', nativeType='nsIOutputStream',
                  notflattened=True)
 addExternalIface('Principal', nativeType='nsIPrincipal',
                  headerFile='nsIPrincipal.h', notflattened=True)
 addExternalIface('StackFrame', nativeType='nsIStackFrame',
                  headerFile='nsIException.h', notflattened=True)
 addExternalIface('URI', nativeType='nsIURI', headerFile='nsIURI.h',
                  notflattened=True)
--- a/dom/events/test/test_bug602962.xul
+++ b/dom/events/test/test_bug602962.xul
@@ -25,36 +25,35 @@ var oldWidth = 0, oldHeight = 0;
 var win = null;
 
 function openWindow() {
   win = window.open("chrome://mochitests/content/chrome/dom/events/test/bug602962.xul", "_blank", "width=600,height=600");
 }
 
 function doTest() {
   scrollbox = win.document.getElementById("page-scrollbox");
-  sbo = scrollbox.boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject);
+  sbo = scrollbox.boxObject;
   content = win.document.getElementById("page-box");
   content.style.width = 400 + "px";
   
   win.addEventListener("resize", function() {
     win.removeEventListener("resize", arguments.callee, false);
 
     sbo.scrollBy(200, 0);
     setTimeout(function() { resize(); }, 0);
   }, false);
 
   oldWidth = win.outerWidth;
   oldHeight = win.outerHeight;
   win.resizeTo(200, 400);
 }
 
 function resize() {
-  let x = {}, y = {};
-  sbo.getPosition(x, y);
-  scrollX = x.value, scrollY = y.value;
+  scrollX = sbo.positionX;
+  scrollY = sbo.positionY;
 
   win.addEventListener("resize", function() {
     content.style.width = (oldWidth + 400) + "px";
     win.removeEventListener("resize", arguments.callee, true);
     
     setTimeout(function() {
       finish();
     }, 0);
@@ -67,20 +66,18 @@ function finish() {
   if (win.outerWidth != oldWidth ||
       win.outerHeight != oldHeight) {
     // We should eventually get back to the original size.
     setTimeout(finish, 0);
     return;
   }
   sbo.scrollBy(scrollX, scrollY);
 
-  let x = {}, y = {};
-  sbo.getPosition(x, y);
-  is(x.value, 200, "Scroll X should have been restored to the value before the resize");
-  is(y.value, 0, "Scroll Y should have been restored to the value before the resize");
+  is(sbo.positionX, 200, "Scroll X should have been restored to the value before the resize");
+  is(sbo.positionY, 0, "Scroll Y should have been restored to the value before the resize");
 
   is(win.outerWidth, oldWidth, "Width should be resized");
   is(win.outerHeight, oldHeight, "Height should be resized");
   win.close();
   SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -668,16 +668,18 @@ var interfaceNamesInGlobalScope =
     "MediaStreamAudioSourceNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MediaStreamEvent", pref: "media.peerconnection.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MediaStreamTrackEvent", pref: "media.peerconnection.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MediaStreamTrack",
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "MenuBoxObject", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MessageEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MessagePort",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MimeType",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MimeTypeArray",
 // IMPORTANT: Do not change this list without review from a DOM peer!
@@ -858,16 +860,18 @@ var interfaceNamesInGlobalScope =
     "PluginArray",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PointerEvent", pref: "dom.w3c_pointer_events.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PopStateEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PopupBlockedEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "PopupBoxObject", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ProcessingInstruction",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ProgressEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Promise",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PropertyNodeList",
 // IMPORTANT: Do not change this list without review from a DOM peer!
new file mode 100644
--- /dev/null
+++ b/dom/webidl/BoxObject.webidl
@@ -0,0 +1,33 @@
+/* -*- 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/.
+ */
+
+[Func="IsChromeOrXBL"]
+interface BoxObject {
+  readonly attribute Element? element;
+
+  readonly attribute long x;
+  readonly attribute long y;
+  [Throws]
+  readonly attribute long screenX;
+  [Throws]
+  readonly attribute long screenY;
+  readonly attribute long width;
+  readonly attribute long height;
+
+  nsISupports? getPropertyAsSupports(DOMString propertyName);
+  void setPropertyAsSupports(DOMString propertyName, nsISupports value);
+  [Throws]
+  DOMString? getProperty(DOMString propertyName);
+  void setProperty(DOMString propertyName, DOMString propertyValue);
+  void removeProperty(DOMString propertyName);
+
+  // for stepping through content in the expanded dom with box-ordinal-group order
+  readonly attribute Element? parentBox;
+  readonly attribute Element? firstChild;
+  readonly attribute Element? lastChild;
+  readonly attribute Element? nextSibling;
+  readonly attribute Element? previousSibling;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/ContainerBoxObject.webidl
@@ -0,0 +1,12 @@
+
+/* -*- 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/.
+ */
+
+[NoInterfaceObject]
+interface ContainerBoxObject : BoxObject {
+    [ChromeOnly]
+    readonly attribute nsIDocShell? docShell;
+};
--- a/dom/webidl/LegacyQueryInterface.webidl
+++ b/dom/webidl/LegacyQueryInterface.webidl
@@ -15,16 +15,17 @@ interface LegacyQueryInterface {
   // Legacy QueryInterface, only exposed to chrome or XBL code on the
   // main thread.
   [Exposed=Window]
   nsISupports queryInterface(IID iid);
 };
 
 Attr implements LegacyQueryInterface;
 BarProp implements LegacyQueryInterface;
+BoxObject implements LegacyQueryInterface;
 CaretPosition implements LegacyQueryInterface;
 Comment implements LegacyQueryInterface;
 Crypto implements LegacyQueryInterface;
 CSSPrimitiveValue implements LegacyQueryInterface;
 CSSStyleDeclaration implements LegacyQueryInterface;
 CSSValueList implements LegacyQueryInterface;
 DOMImplementation implements LegacyQueryInterface;
 DOMParser implements LegacyQueryInterface;
new file mode 100644
--- /dev/null
+++ b/dom/webidl/ListBoxObject.webidl
@@ -0,0 +1,21 @@
+
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+[NoInterfaceObject]
+interface ListBoxObject : BoxObject {
+
+  long getRowCount();
+  long getNumberOfVisibleRows();
+  long getIndexOfFirstVisibleRow();
+
+  void ensureIndexIsVisible(long rowIndex);
+  void scrollToIndex(long rowIndex);
+  void scrollByLines(long numLines);
+
+  Element? getItemAtIndex(long index);
+  long getIndexOfItem(Element item);
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/MenuBoxObject.webidl
@@ -0,0 +1,19 @@
+
+/* -*- 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/.
+ */
+
+[Func="IsChromeOrXBL"]
+interface MenuBoxObject : BoxObject {
+
+  void openMenu(boolean openFlag);
+
+  attribute Element? activeChild;
+
+  boolean handleKeyPress(KeyboardEvent keyEvent);
+
+  readonly attribute boolean openedWithKey;
+
+};
rename from layout/xul/nsIPopupBoxObject.idl
rename to dom/webidl/PopupBoxObject.webidl
--- a/layout/xul/nsIPopupBoxObject.idl
+++ b/dom/webidl/PopupBoxObject.webidl
@@ -1,84 +1,77 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsISupports.idl"
-
-interface nsIDOMElement;
-interface nsIDOMNode;
-interface nsIDOMEvent;
-interface nsIDOMClientRect;
-
-[scriptable, uuid(492861e3-d168-410f-b2bb-6eb8ce503d4a)]
-interface nsIPopupBoxObject : nsISupports
+[Func="IsChromeOrXBL"]
+interface PopupBoxObject : BoxObject
 {
   /**
    *  This method is deprecated. Use openPopup or openPopupAtScreen instead.
    */
-  void showPopup(in nsIDOMElement srcContent, in nsIDOMElement popupContent,
-                 in long xpos, in long ypos,
-                 in wstring popupType, in wstring anchorAlignment, 
-                 in wstring popupAlignment);
+  void showPopup(Element? srcContent, Element popupContent,
+                 long xpos, long ypos,
+                 DOMString popupType, DOMString anchorAlignment,
+                 DOMString popupAlignment);
 
   /**
    *  Hide the popup if it is open. The cancel argument is used as a hint that
    *  the popup is being closed because it has been cancelled, rather than
    *  something being selected within the panel.
    *
    * @param cancel if true, then the popup is being cancelled.
    */
-  void hidePopup([optional] in bool cancel);
+  void hidePopup(optional boolean cancel = false);
 
-  /** 
+  /**
    * Allow the popup to automatically position itself.
    */
   attribute boolean autoPosition;
 
   /**
    * If keyboard navigation is enabled, the keyboard may be used to navigate
    * the menuitems on the popup. Enabling keyboard navigation is the default
    * behaviour and will install capturing key event listeners on the popup
    * that do not propagate key events to the contents. If you wish to place
    * elements in a popup which accept key events, such as textboxes, keyboard
    * navigation should be disabled.
    *
    * Setting ignorekeys="true" on the popup element also disables keyboard
    * navigation, and is recommended over calling this method.
    */
-  void enableKeyboardNavigator(in boolean enableKeyboardNavigator);
+  void enableKeyboardNavigator(boolean enableKeyboardNavigator);
 
-  /** 
+  /**
    * Enable automatic popup dismissal. This only has effect when called
    * on an open popup.
    */
-  void enableRollup(in boolean enableRollup);
+  void enableRollup(boolean enableRollup);
 
   /**
    * Control whether the event that caused the popup to be automatically
    * dismissed ("rolled up") should be consumed, or dispatched as a
    * normal event.  This should be set immediately before calling showPopup()
    * if non-default behavior is desired.
    */
-  const uint32_t ROLLUP_DEFAULT = 0;   /* widget/platform default */
-  const uint32_t ROLLUP_CONSUME = 1;   /* consume the rollup event */
-  const uint32_t ROLLUP_NO_CONSUME = 2; /* don't consume the rollup event */
-  void setConsumeRollupEvent(in uint32_t consume);
+  const unsigned long ROLLUP_DEFAULT = 0;   /* widget/platform default */
+  const unsigned long ROLLUP_CONSUME = 1;   /* consume the rollup event */
+  const unsigned long ROLLUP_NO_CONSUME = 2; /* don't consume the rollup event */
+  void setConsumeRollupEvent(unsigned long consume);
 
-  /** 
+  /**
    * Size the popup to the given dimensions
    */
-  void sizeTo(in long width, in long height);
+  void sizeTo(long width, long height);
 
   /**
    * Move the popup to a point on screen in CSS pixels.
    */
-  void moveTo(in long left, in long top);
+  void moveTo(long left, long top);
 
   /**
    * Open the popup relative to a specified node at a specific location.
    *
    * The popup may be either anchored to another node or opened freely.
    * To anchor a popup to a node, supply an anchor node and set the position
    * to a string indicating the manner in which the popup should be anchored.
    * Possible values for position are:
@@ -88,17 +81,17 @@ interface nsIPopupBoxObject : nsISupport
    *
    * The anchor node does not need to be in the same document as the popup.
    *
    * If the attributesOverride argument is true, the popupanchor, popupalign
    * and position attributes on the popup node override the position value
    * argument. If attributesOverride is false, the attributes are only used
    * if position is empty.
    *
-   * For an anchored popup, the x and y arguments may be used to offset the 
+   * For an anchored popup, the x and y arguments may be used to offset the
    * popup from its anchored position by some distance, measured in CSS pixels.
    * x increases to the right and y increases down. Negative values may also
    * be used to move to the left and upwards respectively.
    *
    * Unanchored popups may be created by supplying null as the anchor node.
    * An unanchored popup appears at the position specified by x and y,
    * relative to the viewport of the document containing the popup node. In
    * this case, position and attributesOverride are ignored.
@@ -106,82 +99,75 @@ interface nsIPopupBoxObject : nsISupport
    * @param anchorElement the node to anchor the popup to, may be null
    * @param position manner is which to anchor the popup to node
    * @param x horizontal offset
    * @param y vertical offset
    * @param isContextMenu true for context menus, false for other popups
    * @param attributesOverride true if popup node attributes override position
    * @param triggerEvent the event that triggered this popup (mouse click for example)
    */
-  void openPopup(in nsIDOMElement anchorElement,
-                 in AString position,
-                 in long x, in long y,
-                 in boolean isContextMenu,
-                 in boolean attributesOverride,
-                 in nsIDOMEvent triggerEvent);
+  void openPopup(Element? anchorElement,
+                 DOMString position,
+                 long x, long y,
+                 boolean isContextMenu,
+                 boolean attributesOverride,
+                 Event? triggerEvent);
 
   /**
    * Open the popup at a specific screen position specified by x and y. This
    * position may be adjusted if it would cause the popup to be off of the
    * screen. The x and y coordinates are measured in CSS pixels, and like all
    * screen coordinates, are given relative to the top left of the primary
    * screen.
    *
    * @param isContextMenu true for context menus, false for other popups
    * @param x horizontal screen position
    * @param y vertical screen position
    * @param triggerEvent the event that triggered this popup (mouse click for example)
    */
-  void openPopupAtScreen(in long x, in long y,
-                         in boolean isContextMenu,
-                         in nsIDOMEvent triggerEvent);
+  void openPopupAtScreen(long x, long y,
+                         boolean isContextMenu,
+                         Event? triggerEvent);
 
   /**
    * Returns the state of the popup:
    *   closed - the popup is closed
    *   open - the popup is open
    *   showing - the popup is in the process of being shown
    *   hiding - the popup is in the process of being hidden
    */
-  readonly attribute AString popupState;
+  readonly attribute DOMString popupState;
 
   /**
    * The node that triggered the popup. If the popup is not open, will return
    * null.
    */
-  readonly attribute nsIDOMNode triggerNode;
+  readonly attribute Node? triggerNode;
 
   /**
    * Retrieve the anchor that was specified to openPopup or for menupopups in a
    * menu, the parent menu.
    */
-  readonly attribute nsIDOMElement anchorNode;
+  readonly attribute Element? anchorNode;
 
   /**
    * Retrieve the screen rectangle of the popup, including the area occupied by
    * any titlebar or borders present.
    */
-  nsIDOMClientRect getOuterScreenRect();
+  DOMRect getOuterScreenRect();
 
   /**
    * Move an open popup to the given anchor position. The arguments have the same
    * meaning as the corresponding argument to openPopup. This method has no effect
    * on popups that are not open.
    */
-  void moveToAnchor(in nsIDOMElement anchorElement,
-                    in AString position,
-                    in long x, in long y,
-                    in boolean attributesOverride);
+  void moveToAnchor(Element? anchorElement,
+                    DOMString position,
+                    long x, long y,
+                    boolean attributesOverride);
 
   /** Returns the alignment position where the popup has appeared relative to its
    *  anchor node or point, accounting for any flipping that occurred.
    */
-  readonly attribute AString alignmentPosition;
+  readonly attribute DOMString alignmentPosition;
   readonly attribute long alignmentOffset;
-};
 
-%{C++
-class nsIBoxObject;
-
-nsresult
-NS_NewPopupBoxObject(nsIBoxObject** aResult);
-
-%}
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/ScrollBoxObject.webidl
@@ -0,0 +1,70 @@
+/* -*- 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/.
+ */
+
+[NoInterfaceObject]
+interface ScrollBoxObject : BoxObject {
+
+  /**
+   * Scroll to the given coordinates, in css pixels.
+   * (0,0) will put the top left corner of the scrolled element's padding-box
+   * at the top left corner of the scrollport (which is its inner-border-box).
+   * Values will be clamped to legal values.
+   */
+  [Throws]
+  void scrollTo(long x, long y);
+
+  /**
+   * Scroll the given amount of device pixels to the right and down.
+   * Values will be clamped to make the resuling position legal.
+   */
+  [Throws]
+  void scrollBy(long dx, long dy);
+  [Throws]
+  void scrollByLine(long dlines);
+  [Throws]
+  void scrollByIndex(long dindexes);
+  [Throws]
+  void scrollToLine(long line);
+  [Throws]
+  void scrollToElement(Element child);
+  [Throws]
+  void scrollToIndex(long index);
+
+  /**
+   * Get the current scroll position in css pixels.
+   * @see scrollTo for the definition of x and y.
+   */
+  [Pure, Throws]
+  readonly attribute long positionX;
+  [Pure, Throws]
+  readonly attribute long positionY;
+  [Pure, Throws]
+  readonly attribute long scrolledWidth;
+  [Pure, Throws]
+  readonly attribute long scrolledHeight;
+
+  /**
+   * DEPRECATED: Please use positionX and positionY
+   *
+   * Get the current scroll position in css pixels.
+   * @see scrollTo for the definition of x and y.
+   */
+  [Throws]
+  void getPosition(object x, object y);
+
+  /**
+   * DEPRECATED: Please use scrolledWidth and scrolledHeight
+   */
+  [Throws]
+  void getScrolledSize(object width, object height);
+
+  [Throws]
+  void ensureElementIsVisible(Element child);
+  [Throws]
+  void ensureIndexIsVisible(long index);
+  [Throws]
+  void ensureLineIsVisible(long line);
+};
copy from layout/xul/tree/nsITreeBoxObject.idl
copy to dom/webidl/TreeBoxObject.webidl
--- a/layout/xul/tree/nsITreeBoxObject.idl
+++ b/dom/webidl/TreeBoxObject.webidl
@@ -1,64 +1,68 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsISupports.idl"
+/* -*- 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/.
+ */
 
-interface nsIDOMElement;
-interface nsITreeView;
-interface nsITreeSelection;
-interface nsITreeColumn;
-interface nsITreeColumns;
+interface MozTreeView;
+interface MozTreeColumn;
 interface nsIScriptableRegion;
 
-[scriptable, uuid(64BA5199-C4F4-4498-BBDC-F8E4C369086C)]
-interface nsITreeBoxObject : nsISupports
-{
+dictionary TreeCellInfo {
+    long row = 0;
+    MozTreeColumn? col = null;
+    DOMString childElt = "";
+};
+
+[NoInterfaceObject]
+interface TreeBoxObject : BoxObject {
+
   /**
    * Obtain the columns.
    */
-  readonly attribute nsITreeColumns columns;
+  readonly attribute TreeColumns? columns;
 
   /**
    * The view that backs the tree and that supplies it with its data.
    * It is dynamically settable, either using a view attribute on the
    * tree tag or by setting this attribute to a new value.
    */
-  attribute nsITreeView view;
+  [SetterThrows]
+  attribute MozTreeView? view;
 
   /**
    * Whether or not we are currently focused.
    */
   attribute boolean focused;
 
   /**
    * Obtain the treebody content node
    */
-  readonly attribute nsIDOMElement treeBody;
+  readonly attribute Element? treeBody;
 
   /**
    * Obtain the height of a row.
    */
   readonly attribute long rowHeight;
 
   /**
    * Obtain the width of a row.
    */
   readonly attribute long rowWidth;
 
   /**
-   * Get the pixel position of the horizontal scrollbar. 
+   * Get the pixel position of the horizontal scrollbar.
    */
   readonly attribute long horizontalPosition;
 
   /**
-   * Return the region for the visible parts of the selection, in device pixels.
+   * Return the region for the visible parts of the selection, in device pixels
    */
   readonly attribute nsIScriptableRegion selectionRegion;
 
   /**
    * Get the index of the first visible row.
    */
   long getFirstVisibleRow();
 
@@ -70,110 +74,125 @@ interface nsITreeBoxObject : nsISupports
   /**
    * Gets the number of possible visible rows.
    */
   long getPageLength();
 
   /**
    * Ensures that a row at a given index is visible.
    */
-  void ensureRowIsVisible(in long index);
+  void ensureRowIsVisible(long index);
 
   /**
    * Ensures that a given cell in the tree is visible.
    */
-  void ensureCellIsVisible(in long row, in nsITreeColumn col);
+  void ensureCellIsVisible(long row, MozTreeColumn? col);
 
   /**
    * Scrolls such that the row at index is at the top of the visible view.
    */
-  void scrollToRow(in long index);
+  void scrollToRow(long index);
 
   /**
    * Scroll the tree up or down by numLines lines. Positive
    * values move down in the tree. Prevents scrolling off the
-   * end of the tree. 
+   * end of the tree.
    */
-  void scrollByLines(in long numLines);
+  void scrollByLines(long numLines);
 
   /**
    * Scroll the tree up or down by numPages pages. A page
    * is considered to be the amount displayed by the tree.
    * Positive values move down in the tree. Prevents scrolling
    * off the end of the tree.
    */
-  void scrollByPages(in long numPages);
-  
-  /**
-   * Scrolls such that a given cell is visible (if possible) 
-   * at the top left corner of the visible view. 
-   */
-  void scrollToCell(in long row, in nsITreeColumn col);
+  void scrollByPages(long numPages);
 
   /**
-   * Scrolls horizontally so that the specified column is 
+   * Scrolls such that a given cell is visible (if possible)
+   * at the top left corner of the visible view.
+   */
+  void scrollToCell(long row, MozTreeColumn? col);
+
+  /**
+   * Scrolls horizontally so that the specified column is
    * at the left of the view (if possible).
    */
-  void scrollToColumn(in nsITreeColumn col);
+  void scrollToColumn(MozTreeColumn? col);
 
   /**
    * Scroll to a specific horizontal pixel position.
    */
-  void scrollToHorizontalPosition(in long horizontalPosition);
+  void scrollToHorizontalPosition(long horizontalPosition);
 
   /**
    * Invalidation methods for fine-grained painting control.
    */
   void invalidate();
-  void invalidateColumn(in nsITreeColumn col);
-  void invalidateRow(in long index);
-  void invalidateCell(in long row, in nsITreeColumn col);
-  void invalidateRange(in long startIndex, in long endIndex);
-  void invalidateColumnRange(in long startIndex, in long endIndex,
-                             in nsITreeColumn col);
+  void invalidateColumn(MozTreeColumn? col);
+  void invalidateRow(long index);
+  void invalidateCell(long row, MozTreeColumn? col);
+  void invalidateRange(long startIndex, long endIndex);
+  void invalidateColumnRange(long startIndex, long endIndex, MozTreeColumn? col);
 
   /**
    * A hit test that can tell you what row the mouse is over.
    * returns -1 for invalid mouse coordinates.
    *
    * The coordinate system is the client coordinate system for the
    * document this boxObject lives in, and the units are CSS pixels.
    */
-  long getRowAt(in long x, in long y);
+  long getRowAt(long x, long y);
 
   /**
-   * A hit test that can tell you what cell the mouse is over.  Row is the row index
-   * hit,  returns -1 for invalid mouse coordinates.  ColID is the column hit.
-   * ChildElt is the pseudoelement hit: this can have values of
+   * A hit test that can tell you what cell the mouse is over.
+   * TreeCellInfo.row is the row index hit,  returns -1 for invalid mouse
+   * coordinates.  TreeCellInfo.col is the column hit.
+   * TreeCellInfo.childElt is the pseudoelement hit: this can have values of
    * "cell", "twisty", "image", and "text".
    *
    * The coordinate system is the client coordinate system for the
    * document this boxObject lives in, and the units are CSS pixels.
    */
-  void getCellAt(in long x, in long y, out long row, out nsITreeColumn col, out ACString childElt);
+  [Throws]
+  TreeCellInfo getCellAt(long x, long y);
 
-  /** 
-   * Find the coordinates of an element within a specific cell. 
+  /**
+   * DEPRECATED: please use above version
+   */
+  [Throws]
+  void getCellAt(long x, long y, object row, object column, object childElt);
+
+  /**
+   * Find the coordinates of an element within a specific cell.
    */
-  void getCoordsForCellItem(in long row, in nsITreeColumn col, in ACString element, 
-                            out long x, out long y, out long width, out long height);
+  [Throws]
+  DOMRect? getCoordsForCellItem(long row, MozTreeColumn col, DOMString element);
 
-  /** 
+  /**
+   * DEPRECATED: Please use above version
+   */
+  [Throws]
+  void getCoordsForCellItem(long row, MozTreeColumn col, DOMString element,
+                            object x, object y, object width, object height);
+
+  /**
    * Determine if the text of a cell is being cropped or not.
    */
-  boolean isCellCropped(in long row, in nsITreeColumn col);
+  [Throws]
+  boolean isCellCropped(long row, MozTreeColumn? col);
 
   /**
    * The view is responsible for calling these notification methods when
    * rows are added or removed.  Index is the position at which the new
    * rows were added or at which rows were removed.  For
    * non-contiguous additions/removals, this method should be called multiple times.
    */
-  void rowCountChanged(in long index, in long count);
-  
+  void rowCountChanged(long index, long count);
+
   /**
    * Notify the tree that the view is about to perform a batch
    * update, that is, add, remove or invalidate several rows at once.
    * This must be followed by calling endUpdateBatch(), otherwise the tree
    * will get out of sync.
    */
   void beginUpdateBatch();
 
--- a/dom/webidl/TreeColumns.webidl
+++ b/dom/webidl/TreeColumns.webidl
@@ -1,21 +1,20 @@
 /* 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 MozTreeBoxObject;
 interface MozTreeColumn;
 
 [Func="IsChromeOrXBL"]
 interface TreeColumns {
   /**
    * The tree widget for these columns.
    */
-  readonly attribute MozTreeBoxObject? tree;
+  readonly attribute TreeBoxObject? tree;
 
   /**
    * The number of columns.
    */
   readonly attribute unsigned long count;
 
   /**
    * An alias for count (for the benefit of scripts which treat this as an
--- a/dom/webidl/XULDocument.webidl
+++ b/dom/webidl/XULDocument.webidl
@@ -3,17 +3,16 @@
  * 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 MozBoxObject;
 interface MozObserver;
 
 [Func="IsChromeOrXBL"]
 interface XULDocument : Document {
            attribute Node? popupNode;
 
   /**
    * These attributes correspond to trustedGetPopupNode().rangeOffset and
@@ -46,13 +45,13 @@ interface XULDocument : Document {
                                DOMString attr);
   void removeBroadcastListenerFor(Element broadcaster, Element observer,
                                   DOMString attr);
 
   [Throws]
   void persist([TreatNullAs=EmptyString] DOMString id, DOMString attr);
 
   [Throws]
-  MozBoxObject? getBoxObjectFor(Element? element);
+  BoxObject? getBoxObjectFor(Element? element);
 
   [Throws]
   void loadOverlay(DOMString url, MozObserver? observer);
 };
--- a/dom/webidl/XULElement.webidl
+++ b/dom/webidl/XULElement.webidl
@@ -1,15 +1,14 @@
 /* -*- 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/.
  */
 
-interface MozBoxObject;
 interface MozControllers;
 interface MozFrameLoader;
 interface MozRDFCompositeDataSource;
 interface MozRDFResource;
 interface MozXULTemplateBuilder;
 
 [Func="IsChromeOrXBL"]
 interface XULElement : Element {
@@ -90,17 +89,17 @@ interface XULElement : Element {
 
   readonly attribute MozRDFCompositeDataSource? database;
   readonly attribute MozXULTemplateBuilder?     builder;
   [Throws]
   readonly attribute MozRDFResource?            resource;
   [Throws]
   readonly attribute MozControllers             controllers;
   [Throws]
-  readonly attribute MozBoxObject?              boxObject;
+  readonly attribute BoxObject?                 boxObject;
 
   [Throws]
   void                      focus();
   [Throws]
   void                      blur();
   [Throws]
   void                      click();
   void                      doCommand();
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -48,16 +48,17 @@ WEBIDL_FILES = [
     'AudioTrackList.webidl',
     'AutocompleteInfo.webidl',
     'BarProp.webidl',
     'BatteryManager.webidl',
     'BeforeAfterKeyboardEvent.webidl',
     'BeforeUnloadEvent.webidl',
     'BiquadFilterNode.webidl',
     'Blob.webidl',
+    'BoxObject.webidl',
     'BrowserElementDictionaries.webidl',
     'CallsList.webidl',
     'CameraCapabilities.webidl',
     'CameraControl.webidl',
     'CameraManager.webidl',
     'CameraUtil.webidl',
     'CanvasRenderingContext2D.webidl',
     'CaretPosition.webidl',
@@ -69,16 +70,17 @@ WEBIDL_FILES = [
     'ChromeNotifications.webidl',
     'ClipboardEvent.webidl',
     'CommandEvent.webidl',
     'Comment.webidl',
     'CompositionEvent.webidl',
     'Console.webidl',
     'Constraints.webidl',
     'Contacts.webidl',
+    'ContainerBoxObject.webidl',
     'ConvolverNode.webidl',
     'Coordinates.webidl',
     'CSPReport.webidl',
     'CSS.webidl',
     'CSSPrimitiveValue.webidl',
     'CSSRuleList.webidl',
     'CSSStyleDeclaration.webidl',
     'CSSStyleSheet.webidl',
@@ -245,29 +247,31 @@ WEBIDL_FILES = [
     'InterAppConnection.webidl',
     'InterAppConnectionRequest.webidl',
     'InterAppMessagePort.webidl',
     'KeyAlgorithm.webidl',
     'KeyboardEvent.webidl',
     'KeyEvent.webidl',
     'LegacyQueryInterface.webidl',
     'LinkStyle.webidl',
+    'ListBoxObject.webidl',
     'LocalMediaStream.webidl',
     'Location.webidl',
     'MediaElementAudioSourceNode.webidl',
     'MediaError.webidl',
     'MediaList.webidl',
     'MediaQueryList.webidl',
     'MediaRecorder.webidl',
     'MediaSource.webidl',
     'MediaStream.webidl',
     'MediaStreamAudioDestinationNode.webidl',
     'MediaStreamAudioSourceNode.webidl',
     'MediaStreamTrack.webidl',
     'MediaTrackConstraintSet.webidl',
+    'MenuBoxObject.webidl',
     'MessageChannel.webidl',
     'MessageEvent.webidl',
     'MessagePort.webidl',
     'MessagePortList.webidl',
     'MimeType.webidl',
     'MimeTypeArray.webidl',
     'MouseEvent.webidl',
     'MouseScrollEvent.webidl',
@@ -315,16 +319,17 @@ WEBIDL_FILES = [
     'PerformanceResourceTiming.webidl',
     'PerformanceTiming.webidl',
     'PeriodicWave.webidl',
     'PermissionSettings.webidl',
     'PhoneNumberService.webidl',
     'Plugin.webidl',
     'PluginArray.webidl',
     'PointerEvent.webidl',
+    'PopupBoxObject.webidl',
     'Position.webidl',
     'PositionError.webidl',
     'ProcessingInstruction.webidl',
     'ProfileTimelineMarker.webidl',
     'Promise.webidl',
     'PromiseDebugging.webidl',
     'PushManager.webidl',
     'RadioNodeList.webidl',
@@ -342,16 +347,17 @@ WEBIDL_FILES = [
     'RTCPeerConnectionStatic.webidl',
     'RTCRtpReceiver.webidl',
     'RTCRtpSender.webidl',
     'RTCSessionDescription.webidl',
     'RTCStatsReport.webidl',
     'Screen.webidl',
     'ScriptProcessorNode.webidl',
     'ScrollAreaEvent.webidl',
+    'ScrollBoxObject.webidl',
     'Selection.webidl',
     'ServiceWorker.webidl',
     'ServiceWorkerContainer.webidl',
     'ServiceWorkerGlobalScope.webidl',
     'ServiceWorkerRegistration.webidl',
     'SettingChangeNotification.webidl',
     'SettingsManager.webidl',
     'ShadowRoot.webidl',
@@ -487,16 +493,17 @@ WEBIDL_FILES = [
     'TextTrackCueList.webidl',
     'TextTrackList.webidl',
     'TimeEvent.webidl',
     'TimeRanges.webidl',
     'Touch.webidl',
     'TouchEvent.webidl',
     'TouchList.webidl',
     'TransitionEvent.webidl',
+    'TreeBoxObject.webidl',
     'TreeColumns.webidl',
     'TreeWalker.webidl',
     'UDPMessageEvent.webidl',
     'UDPSocket.webidl',
     'UIEvent.webidl',
     'UndoManager.webidl',
     'URL.webidl',
     'URLSearchParams.webidl',
--- a/dom/xslt/tests/buster/buster-handlers.js
+++ b/dom/xslt/tests/buster/buster-handlers.js
@@ -3,17 +3,17 @@
  * 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/. */
 
 var xalan_field;
 
 function onLoad()
 {
     view.tree = document.getElementById('out');
-    view.boxObject = view.tree.boxObject.QueryInterface(Components.interfaces.nsITreeBoxObject);
+    view.boxObject = view.tree.boxObject;
     {  
         view.mIframe = document.getElementById('hiddenHtml');
         view.mIframe.webNavigation.allowPlugins = false;
         view.mIframe.webNavigation.allowJavascript = false;
         view.mIframe.webNavigation.allowMetaRedirects = false;
         view.mIframe.webNavigation.allowImages = false;
     }
     view.database = view.tree.database;
--- a/editor/composer/test/test_bug434998.xul
+++ b/editor/composer/test/test_bug434998.xul
@@ -93,17 +93,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     mEditor: null
   };
 
   var progress, progressListener;
 
   function runTest() {
     var newEditorElement = document.getElementById("editor");
     newEditorElement.makeEditable("html", true);
-    var docShell = newEditorElement.boxObject.QueryInterface(Components.interfaces.nsIEditorBoxObject).docShell;
+    var docShell = newEditorElement.boxObject.docShell;
     progress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebProgress);
     progressListener = new EditorContentListener(newEditorElement);
     progress.addProgressListener(progressListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
     newEditorElement.setAttribute("src", "data:text/html,");
   }
 ]]>
 </script>
 </window>
--- a/editor/libeditor/tests/test_bug607584.xul
+++ b/editor/libeditor/tests/test_bug607584.xul
@@ -99,17 +99,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       mEditor: null
   };
 
   var progress, progressListener;
 
   function runTest() {
     var newEditorElement = document.getElementById("editor");
     newEditorElement.makeEditable("html", true);
-    var docShell = newEditorElement.boxObject.QueryInterface(Components.interfaces.nsIEditorBoxObject).docShell;
+    var docShell = newEditorElement.boxObject.docShell;
     progress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebProgress);
     progressListener = new EditorContentListener(newEditorElement);
     progress.addProgressListener(progressListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
     newEditorElement.setAttribute("src", "data:text/html,");
   }
 ]]>
 </script>
 </window>
--- a/editor/libeditor/tests/test_bug616590.xul
+++ b/editor/libeditor/tests/test_bug616590.xul
@@ -89,17 +89,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     mEditor: null
   };
 
   var progress, progressListener;
 
   function runTest() {
     var editorElement = document.getElementById("editor");
     editorElement.makeEditable("htmlmail", true);
-    var docShell = editorElement.boxObject.QueryInterface(Components.interfaces.nsIEditorBoxObject).docShell;
+    var docShell = editorElement.boxObject.docShell;
     progress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebProgress);
     progressListener = new EditorContentListener(editorElement);
     progress.addProgressListener(progressListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
     editorElement.setAttribute("src", "data:text/html,");
   }
 ]]>
 </script>
 </window>
--- a/editor/libeditor/tests/test_bug780908.xul
+++ b/editor/libeditor/tests/test_bug780908.xul
@@ -97,17 +97,17 @@ adapted from test_bug607584.xul by Kent 
       mEditor: null
   };
 
   var progress, progressListener;
 
   function runTest() {
     var newEditorElement = document.getElementById("editor");
     newEditorElement.makeEditable("html", true);
-    var docShell = newEditorElement.boxObject.QueryInterface(Components.interfaces.nsIEditorBoxObject).docShell;
+    var docShell = newEditorElement.boxObject.docShell;
     progress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebProgress);
     progressListener = new EditorContentListener(newEditorElement);
     progress.addProgressListener(progressListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
     newEditorElement.setAttribute("src", "data:text/html,");
   }
 ]]>
 </script>
 </window>
--- a/gfx/tests/unit/test_nsIScriptableRegion.js
+++ b/gfx/tests/unit/test_nsIScriptableRegion.js
@@ -1,16 +1,10 @@
 function run_test()
 {
-  // XXX Work around for the fact that for non-libxul builds loading gfx
-  // components doesn't call up the layout initialisation routine. This should
-  // be fixed/improved by bug 515595.
-  Components.classes["@mozilla.org/layout/xul-boxobject-tree;1"]
-            .createInstance(Components.interfaces.nsIBoxObject);
-
   let rgn = Components.classes["@mozilla.org/gfx/region;1"].createInstance(Components.interfaces.nsIScriptableRegion);
   do_check_true (rgn.getRects() === null)
   rgn.unionRect(0,0,80,60);
   do_check_true (rgn.getRects().toString() == "0,0,80,60")
   rgn.unionRect(90,70,1,1);
   do_check_true (rgn.getRects().toString() == "0,0,80,60,90,70,1,1")
 }
 
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -26,24 +26,16 @@ members = [
     #   - nsIDOMJSWindow.{prompt,setTimeout,setInterval,open,openDialog}
     #
     # (And nsIDOMModalContentWindow.returnValue is an attribute of type
     # nsIVariant, which qsgen.py can't handle.)
 
     # dom/interfaces/xpath
     'nsIDOMXPathNSResolver.lookupNamespaceURI',
 
-    # layout/xul/base/public
-    'nsIBoxObject.x',
-    'nsIBoxObject.y',
-    'nsIBoxObject.screenX',
-    'nsIBoxObject.screenY',
-    'nsIBoxObject.width',
-    'nsIBoxObject.height',
-
     ]
 
 # Most interfaces can be found by searching the includePath; to find
 # nsIDOMEvent, for example, just look for nsIDOMEvent.idl.  But IDL filenames
 # for very long interface names are slightly abbreviated, and many interfaces
 # don't have their own files, just for extra wackiness.  So qsgen.py needs
 # a little help.
 #
--- a/layout/reftests/invalidation/540247-1-ref.xul
+++ b/layout/reftests/invalidation/540247-1-ref.xul
@@ -4,18 +4,17 @@
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
 <script><![CDATA[
 document.addEventListener("MozReftestInvalidate", runtest, false);
 
 function runtest() {
   document.getElementById('b').height = '100';
 
-  var sbo = document.getElementById('s').boxObject.
-              QueryInterface(Components.interfaces.nsIScrollBoxObject);
+  var sbo = document.getElementById('s').boxObject;
   sbo.scrollTo(0, 1000);
 
   document.documentElement.className = "";
 }
 ]]>
 </script>
 
   <scrollbox id="s" height="200" style="overflow: scroll;">
--- a/layout/reftests/invalidation/540247-1.xul
+++ b/layout/reftests/invalidation/540247-1.xul
@@ -5,18 +5,17 @@
 
 <script><![CDATA[
 document.addEventListener("MozReftestInvalidate", runtest, false);
 
 function runtest() {
   // Make sure that the effects of the scroll are painted to the screen before
   // shrinking the size of the scrolled frame.
   window.addEventListener("MozAfterPaint", finish, false);
-  var sbo = document.getElementById('s').boxObject.
-              QueryInterface(Components.interfaces.nsIScrollBoxObject);
+  var sbo = document.getElementById('s').boxObject;
   sbo.scrollTo(0, 1000);
 }
 
 function finish() {
   document.getElementById('b').height = '100';
   document.documentElement.className = "";
 }
 ]]>
rename from layout/xul/nsBoxObject.cpp
rename to layout/xul/BoxObject.cpp
--- a/layout/xul/nsBoxObject.cpp
+++ b/layout/xul/BoxObject.cpp
@@ -1,14 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsBoxObject.h"
+#include "mozilla/dom/BoxObject.h"
 #include "nsCOMPtr.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIContent.h"
 #include "nsContainerFrame.h"
 #include "nsIDocShell.h"
 #include "nsReadableUtils.h"
@@ -19,102 +19,107 @@
 #else
 #include "nsIDOMElement.h"
 #endif
 #include "nsLayoutUtils.h"
 #include "nsISupportsPrimitives.h"
 #include "nsSupportsPrimitives.h"
 #include "mozilla/dom/Element.h"
 #include "nsComponentManagerUtils.h"
-
-using namespace mozilla::dom;
+#include "mozilla/dom/BoxObjectBinding.h"
 
 // Implementation /////////////////////////////////////////////////////////////////
 
+namespace mozilla {
+namespace dom {
+
 // Static member variable initialization
 
 // Implement our nsISupports methods
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsBoxObject)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsBoxObject)
+NS_IMPL_CYCLE_COLLECTION_CLASS(BoxObject)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(BoxObject)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(BoxObject)
 
-DOMCI_DATA(BoxObject, nsBoxObject)
-
-// QueryInterface implementation for nsBoxObject
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsBoxObject)
+// QueryInterface implementation for BoxObject
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BoxObject)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIBoxObject)
   NS_INTERFACE_MAP_ENTRY(nsPIBoxObject)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BoxObject)
 NS_INTERFACE_MAP_END
 
 static PLDHashOperator
 PropertyTraverser(const nsAString& aKey, nsISupports* aProperty, void* userArg)
 {
-  nsCycleCollectionTraversalCallback *cb = 
+  nsCycleCollectionTraversalCallback *cb =
     static_cast<nsCycleCollectionTraversalCallback*>(userArg);
 
   cb->NoteXPCOMChild(aProperty);
 
   return PL_DHASH_NEXT;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsBoxObject)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BoxObject)
+  // XXX jmorton: why aren't we unlinking mPropertyTable?
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsBoxObject)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsBoxObject)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BoxObject)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   if (tmp->mPropertyTable) {
     tmp->mPropertyTable->EnumerateRead(PropertyTraverser, &cb);
   }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
+NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(BoxObject)
+
 // Constructors/Destructors
-nsBoxObject::nsBoxObject(void)
-  :mContent(nullptr)
+BoxObject::BoxObject()
+  : mContent(nullptr)
 {
 }
 
-nsBoxObject::~nsBoxObject(void)
+BoxObject::~BoxObject()
 {
 }
 
 NS_IMETHODIMP
-nsBoxObject::GetElement(nsIDOMElement** aResult)
+BoxObject::GetElement(nsIDOMElement** aResult)
 {
   if (mContent) {
     return CallQueryInterface(mContent, aResult);
   }
 
   *aResult = nullptr;
   return NS_OK;
 }
 
 // nsPIBoxObject //////////////////////////////////////////////////////////////////////////
 
 nsresult
-nsBoxObject::Init(nsIContent* aContent)
+BoxObject::Init(nsIContent* aContent)
 {
   mContent = aContent;
   return NS_OK;
 }
 
 void
-nsBoxObject::Clear()
+BoxObject::Clear()
 {
   mPropertyTable = nullptr;
   mContent = nullptr;
 }
 
 void
-nsBoxObject::ClearCachedValues()
+BoxObject::ClearCachedValues()
 {
 }
 
 nsIFrame*
-nsBoxObject::GetFrame(bool aFlushLayout)
+BoxObject::GetFrame(bool aFlushLayout)
 {
   nsIPresShell* shell = GetPresShell(aFlushLayout);
   if (!shell)
     return nullptr;
 
   if (!aFlushLayout) {
     // If we didn't flush layout when getting the presshell, we should at least
     // flush to make sure our frame model is up to date.
@@ -127,17 +132,17 @@ nsBoxObject::GetFrame(bool aFlushLayout)
   if (!mContent) {
     return nullptr;
   }
 
   return mContent->GetPrimaryFrame();
 }
 
 nsIPresShell*
-nsBoxObject::GetPresShell(bool aFlushLayout)
+BoxObject::GetPresShell(bool aFlushLayout)
 {
   if (!mContent) {
     return nullptr;
   }
 
   nsCOMPtr<nsIDocument> doc = mContent->GetCurrentDoc();
   if (!doc) {
     return nullptr;
@@ -145,21 +150,21 @@ nsBoxObject::GetPresShell(bool aFlushLay
 
   if (aFlushLayout) {
     doc->FlushPendingNotifications(Flush_Layout);
   }
 
   return doc->GetShell();
 }
 
-nsresult 
-nsBoxObject::GetOffsetRect(nsIntRect& aRect)
+nsresult
+BoxObject::GetOffsetRect(nsIntRect& aRect)
 {
   aRect.SetRect(0, 0, 0, 0);
- 
+
   if (!mContent)
     return NS_ERROR_NOT_INITIALIZED;
 
   // Get the Frame for our content
   nsIFrame* frame = GetFrame(true);
   if (frame) {
     // Get its origin
     nsPoint origin = frame->GetPositionIgnoringScrolling();
@@ -180,168 +185,165 @@ nsBoxObject::GetOffsetRect(nsIntRect& aR
         break;
       }
 
       // Add the parent's origin to our own to get to the
       // right coordinate system
       origin += next->GetPositionOfChildIgnoringScrolling(parent);
       parent = next;
     }
-  
+
     // For the origin, add in the border for the frame
     const nsStyleBorder* border = frame->StyleBorder();
     origin.x += border->GetComputedBorderWidth(NS_SIDE_LEFT);
     origin.y += border->GetComputedBorderWidth(NS_SIDE_TOP);
 
     // And subtract out the border for the parent
     const nsStyleBorder* parentBorder = parent->StyleBorder();
     origin.x -= parentBorder->GetComputedBorderWidth(NS_SIDE_LEFT);
     origin.y -= parentBorder->GetComputedBorderWidth(NS_SIDE_TOP);
 
     aRect.x = nsPresContext::AppUnitsToIntCSSPixels(origin.x);
     aRect.y = nsPresContext::AppUnitsToIntCSSPixels(origin.y);
-    
+
     // Get the union of all rectangles in this and continuation frames.
     // It doesn't really matter what we use as aRelativeTo here, since
     // we only care about the size. Using 'parent' might make things
     // a bit faster by speeding up the internal GetOffsetTo operations.
     nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, parent);
     aRect.width = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.width);
     aRect.height = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.height);
   }
 
   return NS_OK;
 }
 
 nsresult
-nsBoxObject::GetScreenPosition(nsIntPoint& aPoint)
+BoxObject::GetScreenPosition(nsIntPoint& aPoint)
 {
   aPoint.x = aPoint.y = 0;
-  
+
   if (!mContent)
     return NS_ERROR_NOT_INITIALIZED;
 
   nsIFrame* frame = GetFrame(true);
   if (frame) {
     nsIntRect rect = frame->GetScreenRect();
     aPoint.x = rect.x;
     aPoint.y = rect.y;
   }
-  
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsBoxObject::GetX(int32_t* aResult)
+BoxObject::GetX(int32_t* aResult)
 {
   nsIntRect rect;
   GetOffsetRect(rect);
   *aResult = rect.x;
   return NS_OK;
 }
 
-NS_IMETHODIMP 
-nsBoxObject::GetY(int32_t* aResult)
+NS_IMETHODIMP
+BoxObject::GetY(int32_t* aResult)
 {
   nsIntRect rect;
   GetOffsetRect(rect);
   *aResult = rect.y;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsBoxObject::GetWidth(int32_t* aResult)
+BoxObject::GetWidth(int32_t* aResult)
 {
   nsIntRect rect;
   GetOffsetRect(rect);
   *aResult = rect.width;
   return NS_OK;
 }
 
-NS_IMETHODIMP 
-nsBoxObject::GetHeight(int32_t* aResult)
+NS_IMETHODIMP
+BoxObject::GetHeight(int32_t* aResult)
 {
   nsIntRect rect;
   GetOffsetRect(rect);
   *aResult = rect.height;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsBoxObject::GetScreenX(int32_t *_retval)
+BoxObject::GetScreenX(int32_t *_retval)
 {
   nsIntPoint position;
   nsresult rv = GetScreenPosition(position);
   if (NS_FAILED(rv)) return rv;
-
   *_retval = position.x;
-
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsBoxObject::GetScreenY(int32_t *_retval)
+BoxObject::GetScreenY(int32_t *_retval)
 {
   nsIntPoint position;
   nsresult rv = GetScreenPosition(position);
   if (NS_FAILED(rv)) return rv;
-
   *_retval = position.y;
-
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsBoxObject::GetPropertyAsSupports(const char16_t* aPropertyName, nsISupports** aResult)
+BoxObject::GetPropertyAsSupports(const char16_t* aPropertyName, nsISupports** aResult)
 {
   NS_ENSURE_ARG(aPropertyName && *aPropertyName);
   if (!mPropertyTable) {
     *aResult = nullptr;
     return NS_OK;
   }
   nsDependentString propertyName(aPropertyName);
   mPropertyTable->Get(propertyName, aResult); // Addref here.
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsBoxObject::SetPropertyAsSupports(const char16_t* aPropertyName, nsISupports* aValue)
+BoxObject::SetPropertyAsSupports(const char16_t* aPropertyName, nsISupports* aValue)
 {
   NS_ENSURE_ARG(aPropertyName && *aPropertyName);
 
   if (!mPropertyTable) {
     mPropertyTable = new nsInterfaceHashtable<nsStringHashKey,nsISupports>(4);
   }
 
   nsDependentString propertyName(aPropertyName);
   mPropertyTable->Put(propertyName, aValue);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsBoxObject::GetProperty(const char16_t* aPropertyName, char16_t** aResult)
+BoxObject::GetProperty(const char16_t* aPropertyName, char16_t** aResult)
 {
   nsCOMPtr<nsISupports> data;
   nsresult rv = GetPropertyAsSupports(aPropertyName,getter_AddRefs(data));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!data) {
     *aResult = nullptr;
     return NS_OK;
   }
 
   nsCOMPtr<nsISupportsString> supportsStr = do_QueryInterface(data);
-  if (!supportsStr)
+  if (!supportsStr) {
     return NS_ERROR_FAILURE;
+  }
 
   return supportsStr->ToString(aResult);
 }
 
 NS_IMETHODIMP
-nsBoxObject::SetProperty(const char16_t* aPropertyName, const char16_t* aPropertyValue)
+BoxObject::SetProperty(const char16_t* aPropertyName, const char16_t* aPropertyValue)
 {
   NS_ENSURE_ARG(aPropertyName && *aPropertyName);
 
   nsDependentString propertyName(aPropertyName);
   nsDependentString propertyValue;
   if (aPropertyValue) {
     propertyValue.Rebind(aPropertyValue);
   } else {
@@ -351,115 +353,270 @@ nsBoxObject::SetProperty(const char16_t*
   nsCOMPtr<nsISupportsString> supportsStr(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
   NS_ENSURE_TRUE(supportsStr, NS_ERROR_OUT_OF_MEMORY);
   supportsStr->SetData(propertyValue);
 
   return SetPropertyAsSupports(aPropertyName,supportsStr);
 }
 
 NS_IMETHODIMP
-nsBoxObject::RemoveProperty(const char16_t* aPropertyName)
+BoxObject::RemoveProperty(const char16_t* aPropertyName)
 {
   NS_ENSURE_ARG(aPropertyName && *aPropertyName);
 
   if (!mPropertyTable) return NS_OK;
 
   nsDependentString propertyName(aPropertyName);
   mPropertyTable->Remove(propertyName);
   return NS_OK;
 }
 
-NS_IMETHODIMP 
-nsBoxObject::GetParentBox(nsIDOMElement * *aParentBox)
+NS_IMETHODIMP
+BoxObject::GetParentBox(nsIDOMElement * *aParentBox)
 {
   *aParentBox = nullptr;
   nsIFrame* frame = GetFrame(false);
   if (!frame) return NS_OK;
   nsIFrame* parent = frame->GetParent();
   if (!parent) return NS_OK;
 
   nsCOMPtr<nsIDOMElement> el = do_QueryInterface(parent->GetContent());
   *aParentBox = el;
   NS_IF_ADDREF(*aParentBox);
   return NS_OK;
 }
 
-NS_IMETHODIMP 
-nsBoxObject::GetFirstChild(nsIDOMElement * *aFirstVisibleChild)
+NS_IMETHODIMP
+BoxObject::GetFirstChild(nsIDOMElement * *aFirstVisibleChild)
 {
   *aFirstVisibleChild = nullptr;
   nsIFrame* frame = GetFrame(false);
   if (!frame) return NS_OK;
   nsIFrame* firstFrame = frame->GetFirstPrincipalChild();
   if (!firstFrame) return NS_OK;
   // get the content for the box and query to a dom element
   nsCOMPtr<nsIDOMElement> el = do_QueryInterface(firstFrame->GetContent());
   el.swap(*aFirstVisibleChild);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsBoxObject::GetLastChild(nsIDOMElement * *aLastVisibleChild)
+BoxObject::GetLastChild(nsIDOMElement * *aLastVisibleChild)
 {
   *aLastVisibleChild = nullptr;
   nsIFrame* frame = GetFrame(false);
   if (!frame) return NS_OK;
   return GetPreviousSibling(frame, nullptr, aLastVisibleChild);
 }
 
 NS_IMETHODIMP
-nsBoxObject::GetNextSibling(nsIDOMElement **aNextOrdinalSibling)
+BoxObject::GetNextSibling(nsIDOMElement **aNextOrdinalSibling)
 {
   *aNextOrdinalSibling = nullptr;
   nsIFrame* frame = GetFrame(false);
   if (!frame) return NS_OK;
   nsIFrame* nextFrame = frame->GetNextSibling();
   if (!nextFrame) return NS_OK;
   // get the content for the box and query to a dom element
   nsCOMPtr<nsIDOMElement> el = do_QueryInterface(nextFrame->GetContent());
   el.swap(*aNextOrdinalSibling);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsBoxObject::GetPreviousSibling(nsIDOMElement **aPreviousOrdinalSibling)
+BoxObject::GetPreviousSibling(nsIDOMElement **aPreviousOrdinalSibling)
 {
   *aPreviousOrdinalSibling = nullptr;
   nsIFrame* frame = GetFrame(false);
   if (!frame) return NS_OK;
   nsIFrame* parentFrame = frame->GetParent();
   if (!parentFrame) return NS_OK;
   return GetPreviousSibling(parentFrame, frame, aPreviousOrdinalSibling);
 }
 
 nsresult
-nsBoxObject::GetPreviousSibling(nsIFrame* aParentFrame, nsIFrame* aFrame,
-                                nsIDOMElement** aResult)
+BoxObject::GetPreviousSibling(nsIFrame* aParentFrame, nsIFrame* aFrame,
+                              nsIDOMElement** aResult)
 {
   *aResult = nullptr;
   nsIFrame* nextFrame = aParentFrame->GetFirstPrincipalChild();
   nsIFrame* prevFrame = nullptr;
   while (nextFrame) {
     if (nextFrame == aFrame)
       break;
     prevFrame = nextFrame;
     nextFrame = nextFrame->GetNextSibling();
   }
-   
+
   if (!prevFrame) return NS_OK;
   // get the content for the box and query to a dom element
   nsCOMPtr<nsIDOMElement> el = do_QueryInterface(prevFrame->GetContent());
   el.swap(*aResult);
   return NS_OK;
 }
 
+nsIContent*
+BoxObject::GetParentObject() const
+{
+  return mContent;
+}
+
+JSObject*
+BoxObject::WrapObject(JSContext* aCx)
+{
+  return BoxObjectBinding::Wrap(aCx, this);
+}
+
+Element*
+BoxObject::GetElement() const
+{
+  return mContent && mContent->IsElement() ? mContent->AsElement() : nullptr;
+}
+
+int32_t
+BoxObject::X()
+{
+  int32_t ret = 0;
+  GetX(&ret);
+  return ret;
+}
+
+int32_t
+BoxObject::Y()
+{
+  int32_t ret = 0;
+  GetY(&ret);
+  return ret;
+}
+
+int32_t
+BoxObject::GetScreenX(ErrorResult& aRv)
+{
+  int32_t ret = 0;
+  aRv = GetScreenX(&ret);
+  return ret;
+}
+
+int32_t
+BoxObject::GetScreenY(ErrorResult& aRv)
+{
+  int32_t ret = 0;
+  aRv = GetScreenY(&ret);
+  return ret;
+}
+
+int32_t
+BoxObject::Width()
+{
+  int32_t ret = 0;
+  GetWidth(&ret);
+  return ret;
+}
+
+int32_t
+BoxObject::Height()
+{
+  int32_t ret = 0;
+  GetHeight(&ret);
+  return ret;
+}
+
+already_AddRefed<nsISupports>
+BoxObject::GetPropertyAsSupports(const nsAString& propertyName)
+{
+  nsCOMPtr<nsISupports> ret;
+  GetPropertyAsSupports(PromiseFlatString(propertyName).get(), getter_AddRefs(ret));
+  return ret.forget();
+}
+
+void
+BoxObject::SetPropertyAsSupports(const nsAString& propertyName, nsISupports* value)
+{
+  SetPropertyAsSupports(PromiseFlatString(propertyName).get(), value);
+}
+
+void
+BoxObject::GetProperty(const nsAString& propertyName, nsString& aRetVal, ErrorResult& aRv)
+{
+  nsCOMPtr<nsISupports> data(GetPropertyAsSupports(propertyName));
+  if (!data) {
+    return;
+  }
+
+  nsCOMPtr<nsISupportsString> supportsStr(do_QueryInterface(data));
+  if (!supportsStr) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  supportsStr->GetData(aRetVal);
+}
+
+void
+BoxObject::SetProperty(const nsAString& propertyName, const nsAString& propertyValue)
+{
+  SetProperty(PromiseFlatString(propertyName).get(), PromiseFlatString(propertyValue).get());
+}
+
+void
+BoxObject::RemoveProperty(const nsAString& propertyName)
+{
+  RemoveProperty(PromiseFlatString(propertyName).get());
+}
+
+already_AddRefed<Element>
+BoxObject::GetParentBox()
+{
+  nsCOMPtr<nsIDOMElement> el;
+  GetParentBox(getter_AddRefs(el));
+  nsCOMPtr<Element> ret(do_QueryInterface(el));
+  return ret.forget();
+}
+
+already_AddRefed<Element>
+BoxObject::GetFirstChild()
+{
+  nsCOMPtr<nsIDOMElement> el;
+  GetFirstChild(getter_AddRefs(el));
+  nsCOMPtr<Element> ret(do_QueryInterface(el));
+  return ret.forget();
+}
+
+already_AddRefed<Element>
+BoxObject::GetLastChild()
+{
+  nsCOMPtr<nsIDOMElement> el;
+  GetLastChild(getter_AddRefs(el));
+  nsCOMPtr<Element> ret(do_QueryInterface(el));
+  return ret.forget();
+}
+
+already_AddRefed<Element>
+BoxObject::GetNextSibling()
+{
+  nsCOMPtr<nsIDOMElement> el;
+  GetNextSibling(getter_AddRefs(el));
+  nsCOMPtr<Element> ret(do_QueryInterface(el));
+  return ret.forget();
+}
+
+already_AddRefed<Element>
+BoxObject::GetPreviousSibling()
+{
+  nsCOMPtr<nsIDOMElement> el;
+  GetPreviousSibling(getter_AddRefs(el));
+  nsCOMPtr<Element> ret(do_QueryInterface(el));
+  return ret.forget();
+}
+
+} // namespace dom
+} // namespace mozilla
+
 // Creation Routine ///////////////////////////////////////////////////////////////////////
 
+using namespace mozilla::dom;
+
 nsresult
 NS_NewBoxObject(nsIBoxObject** aResult)
 {
-  *aResult = new nsBoxObject;
-  if (!*aResult)
-    return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(*aResult);
+  NS_ADDREF(*aResult = new BoxObject());
   return NS_OK;
 }
-
rename from layout/xul/nsBoxObject.h
rename to layout/xul/BoxObject.h
--- a/layout/xul/nsBoxObject.h
+++ b/layout/xul/BoxObject.h
@@ -1,55 +1,92 @@
 /* -*- 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 nsBoxObject_h_
-#define nsBoxObject_h_
+
+#ifndef mozilla_dom_BoxObject_h__
+#define mozilla_dom_BoxObject_h__
 
 #include "mozilla/Attributes.h"
+#include "mozilla/ErrorResult.h"
 #include "nsCOMPtr.h"
 #include "nsIBoxObject.h"
 #include "nsPIBoxObject.h"
 #include "nsPoint.h"
 #include "nsAutoPtr.h"
 #include "nsHashKeys.h"
 #include "nsInterfaceHashtable.h"
 #include "nsCycleCollectionParticipant.h"
+#include "nsWrapperCache.h"
 
 class nsIFrame;
 class nsIDocShell;
 struct nsIntRect;
 class nsIPresShell;
 
-class nsBoxObject : public nsPIBoxObject
+namespace mozilla {
+namespace dom {
+
+class Element;
+
+class BoxObject : public nsPIBoxObject,
+                  public nsWrapperCache
 {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS(nsBoxObject)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BoxObject)
   NS_DECL_NSIBOXOBJECT
 
 public:
-  nsBoxObject();
+  BoxObject();
 
   // nsPIBoxObject
   virtual nsresult Init(nsIContent* aContent) MOZ_OVERRIDE;
   virtual void Clear() MOZ_OVERRIDE;
   virtual void ClearCachedValues() MOZ_OVERRIDE;
 
   nsIFrame* GetFrame(bool aFlushLayout);
   nsIPresShell* GetPresShell(bool aFlushLayout);
   nsresult GetOffsetRect(nsIntRect& aRect);
   nsresult GetScreenPosition(nsIntPoint& aPoint);
 
   // Given a parent frame and a child frame, find the frame whose
   // next sibling is the given child frame and return its element
   static nsresult GetPreviousSibling(nsIFrame* aParentFrame, nsIFrame* aFrame,
                                      nsIDOMElement** aResult);
 
+  // WebIDL (wraps old impls)
+  nsIContent* GetParentObject() const;
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  Element* GetElement() const;
+
+  int32_t X();
+  int32_t Y();
+  int32_t GetScreenX(ErrorResult& aRv);
+  int32_t GetScreenY(ErrorResult& aRv);
+  int32_t Width();
+  int32_t Height();
+
+  already_AddRefed<nsISupports> GetPropertyAsSupports(const nsAString& propertyName);
+  void SetPropertyAsSupports(const nsAString& propertyName, nsISupports* value);
+  void GetProperty(const nsAString& propertyName, nsString& aRetVal, ErrorResult& aRv);
+  void SetProperty(const nsAString& propertyName, const nsAString& propertyValue);
+  void RemoveProperty(const nsAString& propertyName);
+
+  already_AddRefed<Element> GetParentBox();
+  already_AddRefed<Element> GetFirstChild();
+  already_AddRefed<Element> GetLastChild();
+  already_AddRefed<Element> GetNextSibling();
+  already_AddRefed<Element> GetPreviousSibling();
+
 protected:
-  virtual ~nsBoxObject();
+  virtual ~BoxObject();
 
   nsAutoPtr<nsInterfaceHashtable<nsStringHashKey,nsISupports> > mPropertyTable; //[OWNER]
 
   nsIContent* mContent; // [WEAK]
 };
 
+}
+}
+
 #endif
new file mode 100644
--- /dev/null
+++ b/layout/xul/ContainerBoxObject.cpp
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/ContainerBoxObject.h"
+#include "mozilla/dom/ContainerBoxObjectBinding.h"
+#include "nsCOMPtr.h"
+#include "nsIDocShell.h"
+#include "nsIContent.h"
+#include "nsIDocument.h"
+#include "nsIFrame.h"
+#include "nsSubDocumentFrame.h"
+
+namespace mozilla {
+namespace dom {
+  
+ContainerBoxObject::ContainerBoxObject()
+{
+}
+
+ContainerBoxObject::~ContainerBoxObject()
+{
+}
+
+JSObject*
+ContainerBoxObject::WrapObject(JSContext* aCx)
+{
+  return ContainerBoxObjectBinding::Wrap(aCx, this);
+}
+
+already_AddRefed<nsIDocShell>
+ContainerBoxObject::GetDocShell()
+{
+  nsSubDocumentFrame *subDocFrame = do_QueryFrame(GetFrame(false));
+  if (subDocFrame) {
+    // Ok, the frame for mContent is an nsSubDocumentFrame, it knows how
+    // to reach the docshell, so ask it...
+    nsCOMPtr<nsIDocShell> ret;
+    subDocFrame->GetDocShell(getter_AddRefs(ret));
+    return ret.forget();
+  }
+
+  if (!mContent) {
+    return nullptr;
+  }
+
+  // No nsSubDocumentFrame available for mContent, try if there's a mapping
+  // between mContent's document to mContent's subdocument.
+
+  nsIDocument *doc = mContent->GetComposedDoc();
+
+  if (!doc) {
+    return nullptr;
+  }
+
+  nsIDocument *sub_doc = doc->GetSubDocumentFor(mContent);
+
+  if (!sub_doc) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIDocShell> result = sub_doc->GetDocShell();
+  return result.forget();
+}
+
+} // namespace dom
+} // namespace mozilla
+
+nsresult
+NS_NewContainerBoxObject(nsIBoxObject** aResult)
+{
+  NS_ADDREF(*aResult = new mozilla::dom::ContainerBoxObject());
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/layout/xul/ContainerBoxObject.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 mozilla_dom_ContainerBoxObject_h
+#define mozilla_dom_ContainerBoxObject_h
+
+#include "mozilla/dom/BoxObject.h"
+
+namespace mozilla {
+namespace dom {
+
+class ContainerBoxObject MOZ_FINAL : public BoxObject
+{
+public:
+  ContainerBoxObject();
+
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  already_AddRefed<nsIDocShell> GetDocShell();
+
+private:
+  ~ContainerBoxObject();
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_ContainerBoxObject_h
rename from layout/xul/nsListBoxObject.cpp
rename to layout/xul/ListBoxObject.cpp
--- a/layout/xul/nsListBoxObject.cpp
+++ b/layout/xul/ListBoxObject.cpp
@@ -1,130 +1,150 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "mozilla/dom/ListBoxObject.h"
 #include "nsCOMPtr.h"
-#include "nsPIListBoxObject.h"
-#include "nsBoxObject.h"
 #include "nsIFrame.h"
-#include "nsBindingManager.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMNodeList.h"
 #include "nsGkAtoms.h"
 #include "nsIScrollableFrame.h"
 #include "nsListBoxBodyFrame.h"
 #include "ChildIterator.h"
-
-class nsListBoxObject MOZ_FINAL : public nsPIListBoxObject, public nsBoxObject
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSILISTBOXOBJECT
-
-  // nsPIListBoxObject
-  virtual nsListBoxBodyFrame* GetListBoxBody(bool aFlush) MOZ_OVERRIDE;
-
-  nsListBoxObject();
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/ListBoxObjectBinding.h"
 
-  // nsPIBoxObject
-  virtual void Clear() MOZ_OVERRIDE;
-  virtual void ClearCachedValues() MOZ_OVERRIDE;
+namespace mozilla {
+namespace dom {
 
-protected:
-  virtual ~nsListBoxObject() {}
-
-  nsListBoxBodyFrame *mListBoxBody;
-};
-
-NS_IMPL_ISUPPORTS_INHERITED(nsListBoxObject, nsBoxObject, nsIListBoxObject,
+NS_IMPL_ISUPPORTS_INHERITED(ListBoxObject, BoxObject, nsIListBoxObject,
                             nsPIListBoxObject)
 
-nsListBoxObject::nsListBoxObject()
+ListBoxObject::ListBoxObject()
   : mListBoxBody(nullptr)
 {
 }
 
-//////////////////////////////////////////////////////////////////////////
-//// nsIListBoxObject
+ListBoxObject::~ListBoxObject()
+{
+}
 
+JSObject* ListBoxObject::WrapObject(JSContext* aCx)
+{
+  return ListBoxObjectBinding::Wrap(aCx, this);
+}
+
+// nsIListBoxObject
 NS_IMETHODIMP
-nsListBoxObject::GetRowCount(int32_t *aResult)
+ListBoxObject::GetRowCount(int32_t *aResult)
 {
-  nsListBoxBodyFrame* body = GetListBoxBody(true);
-  if (body)
-    return body->GetRowCount(aResult);
+  *aResult = GetRowCount();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsListBoxObject::GetNumberOfVisibleRows(int32_t *aResult)
-{
-  nsListBoxBodyFrame* body = GetListBoxBody(true);
-  if (body)
-    return body->GetNumberOfVisibleRows(aResult);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsListBoxObject::GetIndexOfFirstVisibleRow(int32_t *aResult)
+ListBoxObject::GetItemAtIndex(int32_t index, nsIDOMElement **_retval)
 {
   nsListBoxBodyFrame* body = GetListBoxBody(true);
-  if (body)
-    return body->GetIndexOfFirstVisibleRow(aResult);
+  if (body) {
+    return body->GetItemAtIndex(index, _retval);
+  }
   return NS_OK;
-}
-
-NS_IMETHODIMP nsListBoxObject::EnsureIndexIsVisible(int32_t aRowIndex)
-{
-  nsListBoxBodyFrame* body = GetListBoxBody(true);
-  if (body)
-    return body->EnsureIndexIsVisible(aRowIndex);
-  return NS_OK;
-}
+ }
 
 NS_IMETHODIMP
-nsListBoxObject::ScrollToIndex(int32_t aRowIndex)
-{
-  nsListBoxBodyFrame* body = GetListBoxBody(true);
-  if (body)
-    return body->ScrollToIndex(aRowIndex);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsListBoxObject::ScrollByLines(int32_t aNumLines)
-{
-  nsListBoxBodyFrame* body = GetListBoxBody(true);
-  if (body)
-    return body->ScrollByLines(aNumLines);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsListBoxObject::GetItemAtIndex(int32_t index, nsIDOMElement **_retval)
-{
-  nsListBoxBodyFrame* body = GetListBoxBody(true);
-  if (body)
-    return body->GetItemAtIndex(index, _retval);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsListBoxObject::GetIndexOfItem(nsIDOMElement* aElement, int32_t *aResult)
+ListBoxObject::GetIndexOfItem(nsIDOMElement* aElement, int32_t *aResult)
 {
   *aResult = 0;
 
   nsListBoxBodyFrame* body = GetListBoxBody(true);
-  if (body)
+  if (body) {
     return body->GetIndexOfItem(aElement, aResult);
+  }
   return NS_OK;
 }
 
+// ListBoxObject
+
+int32_t
+ListBoxObject::GetRowCount()
+{
+  nsListBoxBodyFrame* body = GetListBoxBody(true);
+  if (body) {
+    return body->GetRowCount();
+  }
+  return 0;
+}
+
+int32_t
+ListBoxObject::GetNumberOfVisibleRows()
+{
+  nsListBoxBodyFrame* body = GetListBoxBody(true);
+  if (body) {
+    return body->GetNumberOfVisibleRows();
+  }
+  return 0;
+}
+
+int32_t
+ListBoxObject::GetIndexOfFirstVisibleRow()
+{
+  nsListBoxBodyFrame* body = GetListBoxBody(true);
+  if (body) {
+    return body->GetIndexOfFirstVisibleRow();
+  }
+  return 0;
+}
+
+void
+ListBoxObject::EnsureIndexIsVisible(int32_t aRowIndex)
+{
+  nsListBoxBodyFrame* body = GetListBoxBody(true);
+  if (body) {
+    body->EnsureIndexIsVisible(aRowIndex);
+  }
+}
+
+void
+ListBoxObject::ScrollToIndex(int32_t aRowIndex)
+{
+  nsListBoxBodyFrame* body = GetListBoxBody(true);
+  if (body) {
+    body->ScrollToIndex(aRowIndex);
+  }
+}
+
+void
+ListBoxObject::ScrollByLines(int32_t aNumLines)
+{
+  nsListBoxBodyFrame* body = GetListBoxBody(true);
+  if (body) {
+    body->ScrollByLines(aNumLines);
+  }
+}
+
+already_AddRefed<Element>
+ListBoxObject::GetItemAtIndex(int32_t index)
+{
+  nsCOMPtr<nsIDOMElement> el;
+  GetItemAtIndex(index, getter_AddRefs(el));
+  nsCOMPtr<Element> ret(do_QueryInterface(el));
+  return ret.forget();
+}
+
+int32_t
+ListBoxObject::GetIndexOfItem(Element& aElement)
+{
+  int32_t ret;
+  nsCOMPtr<nsIDOMElement> el(do_QueryInterface(&aElement));
+  GetIndexOfItem(el, &ret);
+  return ret;
+}
+
 //////////////////////
 
 static nsIContent*
 FindBodyContent(nsIContent* aParent)
 {
   if (aParent->Tag() == nsGkAtoms::listboxbody) {
     return aParent;
   }
@@ -136,78 +156,83 @@ FindBodyContent(nsIContent* aParent)
       return result;
     }
   }
 
   return nullptr;
 }
 
 nsListBoxBodyFrame*
-nsListBoxObject::GetListBoxBody(bool aFlush)
+ListBoxObject::GetListBoxBody(bool aFlush)
 {
   if (mListBoxBody) {
     return mListBoxBody;
   }
 
   nsIPresShell* shell = GetPresShell(false);
   if (!shell) {
     return nullptr;
   }
 
-  nsIFrame* frame = aFlush ? 
+  nsIFrame* frame = aFlush ?
                       GetFrame(false) /* does Flush_Frames */ :
                       mContent->GetPrimaryFrame();
-  if (!frame)
+  if (!frame) {
     return nullptr;
+  }
 
   // Iterate over our content model children looking for the body.
   nsCOMPtr<nsIContent> content = FindBodyContent(frame->GetContent());
 
-  if (!content)
+  if (!content) {
     return nullptr;
+  }
 
   // this frame will be a nsGFXScrollFrame
   frame = content->GetPrimaryFrame();
-  if (!frame)
+  if (!frame) {
      return nullptr;
+  }
+
   nsIScrollableFrame* scrollFrame = do_QueryFrame(frame);
-  if (!scrollFrame)
+  if (!scrollFrame) {
     return nullptr;
+  }
 
   // this frame will be the one we want
   nsIFrame* yeahBaby = scrollFrame->GetScrolledFrame();
-  if (!yeahBaby)
+  if (!yeahBaby) {
      return nullptr;
+  }
 
   // It's a frame. Refcounts are irrelevant.
   nsListBoxBodyFrame* listBoxBody = do_QueryFrame(yeahBaby);
   NS_ENSURE_TRUE(listBoxBody &&
                  listBoxBody->SetBoxObject(this),
                  nullptr);
   mListBoxBody = listBoxBody;
   return mListBoxBody;
 }
 
 void
-nsListBoxObject::Clear()
+ListBoxObject::Clear()
 {
   ClearCachedValues();
-
-  nsBoxObject::Clear();
+  BoxObject::Clear();
 }
 
 void
-nsListBoxObject::ClearCachedValues()
+ListBoxObject::ClearCachedValues()
 {
   mListBoxBody = nullptr;
 }
 
+}
+}
+
 // Creation Routine ///////////////////////////////////////////////////////////////////////
 
 nsresult
 NS_NewListBoxObject(nsIBoxObject** aResult)
 {
-  *aResult = new nsListBoxObject;
-  if (!*aResult)
-    return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(*aResult);
+  NS_ADDREF(*aResult = new mozilla::dom::ListBoxObject());
   return NS_OK;
 }
new file mode 100644
--- /dev/null
+++ b/layout/xul/ListBoxObject.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 mozilla_dom_ListBoxObject_h
+#define mozilla_dom_ListBoxObject_h
+
+#include "mozilla/dom/BoxObject.h"
+#include "nsPIListBoxObject.h"
+
+namespace mozilla {
+namespace dom {
+
+class ListBoxObject MOZ_FINAL : public BoxObject,
+                                public nsPIListBoxObject
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSILISTBOXOBJECT
+
+  ListBoxObject();
+
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  // nsPIListBoxObject
+  virtual nsListBoxBodyFrame* GetListBoxBody(bool aFlush) MOZ_OVERRIDE;
+
+  // nsPIBoxObject
+  virtual void Clear() MOZ_OVERRIDE;
+  virtual void ClearCachedValues() MOZ_OVERRIDE;
+
+  // ListBoxObject.webidl
+  int32_t GetRowCount();
+  int32_t GetNumberOfVisibleRows();
+  int32_t GetIndexOfFirstVisibleRow();
+  void EnsureIndexIsVisible(int32_t rowIndex);
+  void ScrollToIndex(int32_t rowIndex);
+  void ScrollByLines(int32_t numLines);
+  already_AddRefed<Element> GetItemAtIndex(int32_t index);
+  int32_t GetIndexOfItem(Element& item);
+
+protected:
+  nsListBoxBodyFrame *mListBoxBody;
+
+private:
+  ~ListBoxObject();
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_ListBoxObject_h
rename from layout/xul/nsMenuBoxObject.cpp
rename to layout/xul/MenuBoxObject.cpp
--- a/layout/xul/nsMenuBoxObject.cpp
+++ b/layout/xul/MenuBoxObject.cpp
@@ -1,46 +1,42 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "nsISupportsUtils.h"
-#include "nsIMenuBoxObject.h"
-#include "nsBoxObject.h"
+
+#include "mozilla/dom/MenuBoxObject.h"
+#include "mozilla/dom/MenuBoxObjectBinding.h"
+
+#include "mozilla/dom/KeyboardEvent.h"
+#include "mozilla/dom/Element.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIFrame.h"
 #include "nsMenuBarFrame.h"
 #include "nsMenuBarListener.h"
 #include "nsMenuFrame.h"
 #include "nsMenuPopupFrame.h"
 
-class nsMenuBoxObject : public nsIMenuBoxObject,
-                        public nsBoxObject
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIMENUBOXOBJECT
+namespace mozilla {
+namespace dom {
 
-  nsMenuBoxObject();
-protected:
-  virtual ~nsMenuBoxObject();
-};
-
-nsMenuBoxObject::nsMenuBoxObject()
+MenuBoxObject::MenuBoxObject()
 {
 }
 
-nsMenuBoxObject::~nsMenuBoxObject()
+MenuBoxObject::~MenuBoxObject()
 {
 }
 
-NS_IMPL_ISUPPORTS_INHERITED(nsMenuBoxObject, nsBoxObject, nsIMenuBoxObject)
+JSObject* MenuBoxObject::WrapObject(JSContext* aCx)
+{
+  return MenuBoxObjectBinding::Wrap(aCx, this);
+}
 
-/* void openMenu (in boolean openFlag); */
-NS_IMETHODIMP nsMenuBoxObject::OpenMenu(bool aOpenFlag)
+void MenuBoxObject::OpenMenu(bool aOpenFlag)
 {
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (pm) {
     nsIFrame* frame = GetFrame(false);
     if (frame) {
       if (aOpenFlag) {
         nsCOMPtr<nsIContent> content = mContent;
         pm->ShowMenu(content, false, false);
@@ -50,111 +46,106 @@ NS_IMETHODIMP nsMenuBoxObject::OpenMenu(
         if (menu) {
           nsMenuPopupFrame* popupFrame = menu->GetPopup();
           if (popupFrame)
             pm->HidePopup(popupFrame->GetContent(), false, true, false, false);
         }
       }
     }
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP nsMenuBoxObject::GetActiveChild(nsIDOMElement** aResult)
+already_AddRefed<Element>
+MenuBoxObject::GetActiveChild()
 {
-  *aResult = nullptr;
   nsMenuFrame* menu = do_QueryFrame(GetFrame(false));
-  if (menu)
-    return menu->GetActiveChild(aResult);
-  return NS_OK;
+  if (menu) {
+    nsCOMPtr<nsIDOMElement> el;
+    menu->GetActiveChild(getter_AddRefs(el));
+    nsCOMPtr<Element> ret(do_QueryInterface(el));
+    return ret.forget();
+  }
+  return nullptr;
 }
 
-NS_IMETHODIMP nsMenuBoxObject::SetActiveChild(nsIDOMElement* aResult)
+void MenuBoxObject::SetActiveChild(Element* arg)
 {
   nsMenuFrame* menu = do_QueryFrame(GetFrame(false));
-  if (menu)
-    return menu->SetActiveChild(aResult);
-  return NS_OK;
+  if (menu) {
+    nsCOMPtr<nsIDOMElement> el(do_QueryInterface(arg));
+    menu->SetActiveChild(el);
+  }
 }
 
-/* boolean handleKeyPress (in nsIDOMKeyEvent keyEvent); */
-NS_IMETHODIMP nsMenuBoxObject::HandleKeyPress(nsIDOMKeyEvent* aKeyEvent, bool* aHandledFlag)
+bool MenuBoxObject::HandleKeyPress(KeyboardEvent& keyEvent)
 {
-  *aHandledFlag = false;
-  NS_ENSURE_ARG(aKeyEvent);
-
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
-  if (!pm)
-    return NS_OK;
+  if (!pm) {
+    return false;
+  }
 
   // if event has already been handled, bail
   bool eventHandled = false;
-  aKeyEvent->GetDefaultPrevented(&eventHandled);
-  if (eventHandled)
-    return NS_OK;
+  keyEvent.GetDefaultPrevented(&eventHandled);
+  if (eventHandled) {
+    return false;
+  }
 
-  if (nsMenuBarListener::IsAccessKeyPressed(aKeyEvent))
-    return NS_OK;
+  if (nsMenuBarListener::IsAccessKeyPressed(&keyEvent))
+    return false;
 
   nsMenuFrame* menu = do_QueryFrame(GetFrame(false));
-  if (!menu)
-    return NS_OK;
+  if (!menu) {
+    return false;
+  }
 
   nsMenuPopupFrame* popupFrame = menu->GetPopup();
-  if (!popupFrame)
-    return NS_OK;
+  if (!popupFrame) {
+    return false;
+  }
 
-  uint32_t keyCode;
-  aKeyEvent->GetKeyCode(&keyCode);
+  uint32_t keyCode = keyEvent.KeyCode();
   switch (keyCode) {
     case nsIDOMKeyEvent::DOM_VK_UP:
     case nsIDOMKeyEvent::DOM_VK_DOWN:
     case nsIDOMKeyEvent::DOM_VK_HOME:
     case nsIDOMKeyEvent::DOM_VK_END:
     {
       nsNavigationDirection theDirection;
       theDirection = NS_DIRECTION_FROM_KEY_CODE(popupFrame, keyCode);
-      *aHandledFlag =
-        pm->HandleKeyboardNavigationInPopup(popupFrame, theDirection);
-      return NS_OK;
+      return pm->HandleKeyboardNavigationInPopup(popupFrame, theDirection);
     }
     default:
-      *aHandledFlag = pm->HandleShortcutNavigation(aKeyEvent, popupFrame);
-      return NS_OK;
+      return pm->HandleShortcutNavigation(&keyEvent, popupFrame);
   }
 }
 
-NS_IMETHODIMP
-nsMenuBoxObject::GetOpenedWithKey(bool* aOpenedWithKey)
+bool MenuBoxObject::OpenedWithKey()
 {
-  *aOpenedWithKey = false;
-
   nsMenuFrame* menuframe = do_QueryFrame(GetFrame(false));
-  if (!menuframe)
-    return NS_OK;
+  if (!menuframe) {
+    return false;
+  }
 
   nsIFrame* frame = menuframe->GetParent();
   while (frame) {
     nsMenuBarFrame* menubar = do_QueryFrame(frame);
     if (menubar) {
-      *aOpenedWithKey = menubar->IsActiveByKeyboard();
-      return NS_OK;
+      return menubar->IsActiveByKeyboard();
     }
     frame = frame->GetParent();
   }
-
-  return NS_OK;
+  return false;
 }
 
+} // namespace dom
+} // namespace mozilla
 
 // Creation Routine ///////////////////////////////////////////////////////////////////////
 
+using namespace mozilla::dom;
+
 nsresult
 NS_NewMenuBoxObject(nsIBoxObject** aResult)
 {
-  *aResult = new nsMenuBoxObject;
-  if (!*aResult)
-    return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(*aResult);
+  NS_ADDREF(*aResult = new MenuBoxObject());
   return NS_OK;
 }
-
new file mode 100644
--- /dev/null
+++ b/layout/xul/MenuBoxObject.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 mozilla_dom_MenuBoxObject_h
+#define mozilla_dom_MenuBoxObject_h
+
+#include "mozilla/dom/BoxObject.h"
+
+namespace mozilla {
+namespace dom {
+
+class KeyboardEvent;
+
+class MenuBoxObject MOZ_FINAL : public BoxObject
+{
+public:
+
+  MenuBoxObject();
+
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  void OpenMenu(bool aOpenFlag);
+  already_AddRefed<Element> GetActiveChild();
+  void SetActiveChild(Element* arg);
+  bool HandleKeyPress(KeyboardEvent& keyEvent);
+  bool OpenedWithKey();
+
+private:
+  ~MenuBoxObject();
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_MenuBoxObject_h
rename from layout/xul/nsPopupBoxObject.cpp
rename to layout/xul/PopupBoxObject.cpp
--- a/layout/xul/nsPopupBoxObject.cpp
+++ b/layout/xul/PopupBoxObject.cpp
@@ -1,229 +1,215 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 #include "nsCOMPtr.h"
-#include "nsIPopupBoxObject.h"
 #include "nsIRootBox.h"
-#include "nsBoxObject.h"
 #include "nsIPresShell.h"
 #include "nsIContent.h"
-#include "nsIDOMElement.h"
 #include "nsNameSpaceManager.h"
 #include "nsGkAtoms.h"
 #include "nsMenuPopupFrame.h"
 #include "nsView.h"
 #include "mozilla/AppUnits.h"
 #include "mozilla/dom/DOMRect.h"
-
-using namespace mozilla::dom;
+#include "mozilla/dom/PopupBoxObject.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/Event.h"
+#include "mozilla/dom/PopupBoxObjectBinding.h"
 
-class nsPopupBoxObject : public nsBoxObject,
-                         public nsIPopupBoxObject
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_ADDREF_INHERITED(PopupBoxObject, BoxObject)
+NS_IMPL_RELEASE_INHERITED(PopupBoxObject, BoxObject)
+NS_INTERFACE_MAP_BEGIN(PopupBoxObject)
+NS_INTERFACE_MAP_END_INHERITING(BoxObject)
+
+PopupBoxObject::PopupBoxObject()
 {
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIPOPUPBOXOBJECT
+}
+
+PopupBoxObject::~PopupBoxObject()
+{
+}
 
-  nsPopupBoxObject() {}
-protected:
-  virtual ~nsPopupBoxObject() {}
+nsIContent* PopupBoxObject::GetParentObject() const
+{
+  return BoxObject::GetParentObject();
+}
 
-  nsPopupSetFrame* GetPopupSetFrame();
-};
-
-NS_IMPL_ISUPPORTS_INHERITED(nsPopupBoxObject, nsBoxObject, nsIPopupBoxObject)
+JSObject* PopupBoxObject::WrapObject(JSContext* aCx)
+{
+  return PopupBoxObjectBinding::Wrap(aCx, this);
+}
 
 nsPopupSetFrame*
-nsPopupBoxObject::GetPopupSetFrame()
+PopupBoxObject::GetPopupSetFrame()
 {
   nsIRootBox* rootBox = nsIRootBox::GetRootBox(GetPresShell(false));
   if (!rootBox)
     return nullptr;
 
   return rootBox->GetPopupSetFrame();
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::HidePopup(bool aCancel)
+void
+PopupBoxObject::HidePopup(bool aCancel)
 {
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
-  if (pm && mContent)
+  if (pm && mContent) {
     pm->HidePopup(mContent, false, true, false, aCancel);
-
-  return NS_OK;
+  }
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::ShowPopup(nsIDOMElement* aAnchorElement,
-                            nsIDOMElement* aPopupElement,
-                            int32_t aXPos, int32_t aYPos,
-                            const char16_t *aPopupType,
-                            const char16_t *aAnchorAlignment,
-                            const char16_t *aPopupAlignment)
+void
+PopupBoxObject::ShowPopup(Element* aAnchorElement,
+                          Element& aPopupElement,
+                          int32_t aXPos, int32_t aYPos,
+                          const nsAString& aPopupType,
+                          const nsAString& aAnchorAlignment,
+                          const nsAString& aPopupAlignment)
 {
-  NS_ENSURE_TRUE(aPopupElement, NS_ERROR_INVALID_ARG);
-  // srcContent can be null.
-
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (pm && mContent) {
     nsCOMPtr<nsIContent> anchorContent(do_QueryInterface(aAnchorElement));
     nsAutoString popupType(aPopupType);
     nsAutoString anchor(aAnchorAlignment);
     nsAutoString align(aPopupAlignment);
     pm->ShowPopupWithAnchorAlign(mContent, anchorContent, anchor, align,
-                                 aXPos, aYPos, popupType.EqualsLiteral("context"));
+                                 aXPos, aYPos,
+                                 popupType.EqualsLiteral("context"));
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::OpenPopup(nsIDOMElement* aAnchorElement,
-                            const nsAString& aPosition,
-                            int32_t aXPos, int32_t aYPos,
-                            bool aIsContextMenu,
-                            bool aAttributesOverride,
-                            nsIDOMEvent* aTriggerEvent)
+void
+PopupBoxObject::OpenPopup(Element* aAnchorElement,
+                          const nsAString& aPosition,
+                          int32_t aXPos, int32_t aYPos,
+                          bool aIsContextMenu,
+                          bool aAttributesOverride,
+                          Event* aTriggerEvent)
 {
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (pm && mContent) {
     nsCOMPtr<nsIContent> anchorContent(do_QueryInterface(aAnchorElement));
     pm->ShowPopup(mContent, anchorContent, aPosition, aXPos, aYPos,
                   aIsContextMenu, aAttributesOverride, false, aTriggerEvent);
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::OpenPopupAtScreen(int32_t aXPos, int32_t aYPos,
-                                    bool aIsContextMenu,
-                                    nsIDOMEvent* aTriggerEvent)
+void
+PopupBoxObject::OpenPopupAtScreen(int32_t aXPos, int32_t aYPos,
+                                  bool aIsContextMenu,
+                                  Event* aTriggerEvent)
 {
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (pm && mContent)
     pm->ShowPopupAtScreen(mContent, aXPos, aYPos, aIsContextMenu, aTriggerEvent);
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::MoveTo(int32_t aLeft, int32_t aTop)
+void
+PopupBoxObject::MoveTo(int32_t aLeft, int32_t aTop)
 {
   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
   if (menuPopupFrame) {
     menuPopupFrame->MoveTo(aLeft, aTop, true);
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::MoveToAnchor(nsIDOMElement* aAnchorElement,
-                               const nsAString& aPosition,
-                               int32_t aXPos, int32_t aYPos,
-                               bool aAttributesOverride)
+void
+PopupBoxObject::MoveToAnchor(Element* aAnchorElement,
+                             const nsAString& aPosition,
+                             int32_t aXPos, int32_t aYPos,
+                             bool aAttributesOverride)
 {
   if (mContent) {
     nsCOMPtr<nsIContent> anchorContent(do_QueryInterface(aAnchorElement));
 
     nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(mContent->GetPrimaryFrame());
     if (menuPopupFrame && menuPopupFrame->IsVisible()) {
       menuPopupFrame->MoveToAnchor(anchorContent, aPosition, aXPos, aYPos, aAttributesOverride);
     }
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::SizeTo(int32_t aWidth, int32_t aHeight)
+void
+PopupBoxObject::SizeTo(int32_t aWidth, int32_t aHeight)
 {
   if (!mContent)
-    return NS_OK;
+    return;
 
   nsAutoString width, height;
   width.AppendInt(aWidth);
   height.AppendInt(aHeight);
 
   nsCOMPtr<nsIContent> content = mContent;
 
   // We only want to pass aNotify=true to SetAttr once, but must make sure
   // we pass it when a value is being changed.  Thus, we check if the height
   // is the same and if so, pass true when setting the width.
   bool heightSame = content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::height, height, eCaseMatters);
 
   content->SetAttr(kNameSpaceID_None, nsGkAtoms::width, width, heightSame);
   content->SetAttr(kNameSpaceID_None, nsGkAtoms::height, height, true);
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::GetAutoPosition(bool* aShouldAutoPosition)
+bool
+PopupBoxObject::AutoPosition()
 {
-  *aShouldAutoPosition = true;
-
   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
   if (menuPopupFrame) {
-    *aShouldAutoPosition = menuPopupFrame->GetAutoPosition();
+    return menuPopupFrame->GetAutoPosition();
   }
-
-  return NS_OK;
+  return true;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::SetAutoPosition(bool aShouldAutoPosition)
+void
+PopupBoxObject::SetAutoPosition(bool aShouldAutoPosition)
 {
   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
   if (menuPopupFrame) {
     menuPopupFrame->SetAutoPosition(aShouldAutoPosition);
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::EnableRollup(bool aShouldRollup)
+void
+PopupBoxObject::EnableRollup(bool aShouldRollup)
 {
   // this does nothing now
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::SetConsumeRollupEvent(uint32_t aConsume)
+void
+PopupBoxObject::SetConsumeRollupEvent(uint32_t aConsume)
 {
   nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
   if (menuPopupFrame) {
     menuPopupFrame->SetConsumeRollupEvent(aConsume);
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::EnableKeyboardNavigator(bool aEnableKeyboardNavigator)
+void
+PopupBoxObject::EnableKeyboardNavigator(bool aEnableKeyboardNavigator)
 {
   if (!mContent)
-    return NS_OK;
+    return;
 
   // Use ignorekeys="true" on the popup instead of using this function.
   if (aEnableKeyboardNavigator)
     mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::ignorekeys, true);
   else
     mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::ignorekeys,
                       NS_LITERAL_STRING("true"), true);
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::GetPopupState(nsAString& aState)
+void
+PopupBoxObject::GetPopupState(nsString& aState)
 {
   // set this here in case there's no frame for the popup
   aState.AssignLiteral("closed");
 
   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
   if (menuPopupFrame) {
     switch (menuPopupFrame->PopupState()) {
       case ePopupShown:
@@ -240,85 +226,71 @@ nsPopupBoxObject::GetPopupState(nsAStrin
         break;
       case ePopupClosed:
         break;
       default:
         NS_NOTREACHED("Bad popup state");
         break;
     }
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::GetTriggerNode(nsIDOMNode** aTriggerNode)
+nsINode*
+PopupBoxObject::GetTriggerNode() const
 {
-  *aTriggerNode = nullptr;
-
   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
-  nsIContent* triggerContent = nsMenuPopupFrame::GetTriggerContent(menuPopupFrame);
-  if (triggerContent)
-    CallQueryInterface(triggerContent, aTriggerNode);
-
-  return NS_OK;
+  return nsMenuPopupFrame::GetTriggerContent(menuPopupFrame);
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::GetAnchorNode(nsIDOMElement** aAnchor)
+Element*
+PopupBoxObject::GetAnchorNode() const
 {
-  *aAnchor = nullptr;
-
   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
-  if (!menuPopupFrame)
-    return NS_OK;
+  if (!menuPopupFrame) {
+    return nullptr;
+  }
 
   nsIContent* anchor = menuPopupFrame->GetAnchor();
-  if (anchor)
-    CallQueryInterface(anchor, aAnchor);
-
-  return NS_OK;
+  return anchor && anchor->IsElement() ? anchor->AsElement() : nullptr;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::GetOuterScreenRect(nsIDOMClientRect** aRect)
+already_AddRefed<DOMRect>
+PopupBoxObject::GetOuterScreenRect()
 {
-  DOMRect* rect = new DOMRect(mContent);
-
-  NS_ADDREF(*aRect = rect);
+  nsRefPtr<DOMRect> rect = new DOMRect(mContent);
 
   // Return an empty rectangle if the popup is not open.
   nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
-  if (!menuPopupFrame || !menuPopupFrame->IsOpen())
-    return NS_OK;
+  if (!menuPopupFrame || !menuPopupFrame->IsOpen()) {
+    return rect.forget();
+  }
 
   nsView* view = menuPopupFrame->GetView();
   if (view) {
     nsIWidget* widget = view->GetWidget();
     if (widget) {
       nsIntRect screenRect;
       widget->GetScreenBounds(screenRect);
 
       int32_t pp = menuPopupFrame->PresContext()->AppUnitsPerDevPixel();
       rect->SetLayoutRect(screenRect.ToAppUnits(pp));
     }
   }
-
-  return NS_OK;
+  return rect.forget();
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::GetAlignmentPosition(nsAString& positionStr)
+void
+PopupBoxObject::GetAlignmentPosition(nsString& positionStr)
 {
   positionStr.Truncate();
 
   // This needs to flush layout.
   nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(true));
   if (!menuPopupFrame)
-    return NS_OK;
+    return;
 
   int8_t position = menuPopupFrame->GetAlignmentPosition();
   switch (position) {
     case POPUPPOSITION_AFTERSTART:
       positionStr.AssignLiteral("after_start");
       break;
     case POPUPPOSITION_AFTEREND:
       positionStr.AssignLiteral("after_end");
@@ -346,40 +318,38 @@ nsPopupBoxObject::GetAlignmentPosition(n
       break;
     case POPUPPOSITION_AFTERPOINTER:
       positionStr.AssignLiteral("after_pointer");
       break;
     default:
       // Leave as an empty string.
       break;
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::GetAlignmentOffset(int32_t *aAlignmentOffset)
+int32_t
+PopupBoxObject::AlignmentOffset()
 {
   nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
   if (!menuPopupFrame)
-    return NS_OK;
+    return 0;
 
   int32_t pp = mozilla::AppUnitsPerCSSPixel();
   // Note that the offset might be along either the X or Y axis, but for the
   // sake of simplicity we use a point with only the X axis set so we can
   // use ToNearestPixels().
   nsPoint appOffset(menuPopupFrame->GetAlignmentOffset(), 0);
   nsIntPoint popupOffset = appOffset.ToNearestPixels(pp);
-  *aAlignmentOffset = popupOffset.x;
-  return NS_OK;
+  return popupOffset.x;
 }
 
+} // namespace dom
+} // namespace mozilla
+
 // Creation Routine ///////////////////////////////////////////////////////////////////////
 
 nsresult
 NS_NewPopupBoxObject(nsIBoxObject** aResult)
 {
-  *aResult = new nsPopupBoxObject;
-  if (!*aResult)
-    return NS_ERROR_OUT_OF_MEMORY;
+  *aResult = new mozilla::dom::PopupBoxObject();
   NS_ADDREF(*aResult);
   return NS_OK;
 }
new file mode 100644
--- /dev/null
+++ b/layout/xul/PopupBoxObject.h
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 mozilla_dom_PopupBoxObject_h
+#define mozilla_dom_PopupBoxObject_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/ErrorResult.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsWrapperCache.h"
+#include "mozilla/dom/BoxObject.h"
+#include "nsString.h"
+
+struct JSContext;
+class nsPopupSetFrame;
+
+namespace mozilla {
+namespace dom {
+
+class DOMRect;
+class Element;
+class Event;
+
+class PopupBoxObject MOZ_FINAL : public BoxObject
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // also in PopupBoxObject.webidl
+  static const uint32_t ROLLUP_DEFAULT = 0;   /* widget/platform default */
+  static const uint32_t ROLLUP_CONSUME = 1;   /* consume the rollup event */
+  static const uint32_t ROLLUP_NO_CONSUME = 2; /* don't consume the rollup event */
+
+  PopupBoxObject();
+
+  nsIContent* GetParentObject() const;
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  void ShowPopup(Element* aAnchorElement,
+                 Element& aPopupElement,
+                 int32_t aXPos,
+                 int32_t aYPos,
+                 const nsAString& aPopupType,
+                 const nsAString& aAnchorAlignment,
+                 const nsAString& aPopupAlignment);
+
+  void HidePopup(bool aCancel);
+
+  bool AutoPosition();
+
+  void SetAutoPosition(bool aShouldAutoPosition);
+
+  void EnableKeyboardNavigator(bool aEnableKeyboardNavigator);
+
+  void EnableRollup(bool aShouldRollup);
+
+  void SetConsumeRollupEvent(uint32_t aConsume);
+
+  void SizeTo(int32_t aWidth, int32_t aHeight);
+
+  void MoveTo(int32_t aLeft, int32_t aTop);
+
+  void OpenPopup(Element* aAnchorElement,
+                 const nsAString& aPosition,
+                 int32_t aXPos,
+                 int32_t aYPos,
+                 bool aIsContextMenu, bool aAttributesOverride,
+                 Event* aTriggerEvent);
+
+  void OpenPopupAtScreen(int32_t aXPos,
+                         int32_t aYPos,
+                         bool aIsContextMenu,
+                         Event* aTriggerEvent);
+
+  void GetPopupState(nsString& aState);
+
+  nsINode* GetTriggerNode() const;
+
+  Element* GetAnchorNode() const;
+
+  already_AddRefed<DOMRect> GetOuterScreenRect();
+
+  void MoveToAnchor(Element* aAnchorElement,
+                    const nsAString& aPosition,
+                    int32_t aXPos,
+                    int32_t aYPos,
+                    bool aAttributesOverride);
+
+  void GetAlignmentPosition(nsString& positionStr);
+
+  int32_t AlignmentOffset();
+
+private:
+  ~PopupBoxObject();
+
+protected:
+  nsPopupSetFrame* GetPopupSetFrame();
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_PopupBoxObject_h
new file mode 100644
--- /dev/null
+++ b/layout/xul/ScrollBoxObject.cpp
@@ -0,0 +1,394 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/ScrollBoxObject.h"
+#include "mozilla/dom/ScrollBoxObjectBinding.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/ToJSValue.h"
+#include "nsCOMPtr.h"
+#include "nsIPresShell.h"
+#include "nsIContent.h"
+#include "nsIDOMElement.h"
+#include "nsPresContext.h"
+#include "nsBox.h"
+#include "nsIScrollableFrame.h"
+
+namespace mozilla {
+namespace dom {
+
+ScrollBoxObject::ScrollBoxObject()
+{
+}
+
+ScrollBoxObject::~ScrollBoxObject()
+{
+}
+
+JSObject* ScrollBoxObject::WrapObject(JSContext* aCx)
+{
+  return ScrollBoxObjectBinding::Wrap(aCx, this);
+}
+
+nsIScrollableFrame* ScrollBoxObject::GetScrollFrame()
+{
+  return do_QueryFrame(GetFrame(false));
+}
+
+/* void scrollTo (long x, long y); */
+void ScrollBoxObject::ScrollTo(int32_t x, int32_t y, ErrorResult& aRv)
+{
+  nsIScrollableFrame* sf = GetScrollFrame();
+  if (!sf) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  sf->ScrollToCSSPixels(CSSIntPoint(x, y));
+}
+
+/* void scrollBy (long dx, long dy); */
+void ScrollBoxObject::ScrollBy(int32_t dx, int32_t dy, ErrorResult& aRv)
+{
+  CSSIntPoint pt;
+  GetPosition(pt, aRv);
+
+  if (aRv.Failed()) {
+    return;
+  }
+
+  ScrollTo(pt.x + dx, pt.y + dy, aRv);
+}
+
+/* void scrollByLine (long dlines); */
+void ScrollBoxObject::ScrollByLine(int32_t dlines, ErrorResult& aRv)
+{
+  nsIScrollableFrame* sf = GetScrollFrame();
+  if (!sf) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  sf->ScrollBy(nsIntPoint(0, dlines), nsIScrollableFrame::LINES,
+               nsIScrollableFrame::SMOOTH);
+}
+
+// XUL <scrollbox> elements have a single box child element.
+// Get a pointer to that box.
+// Note that now that the <scrollbox> is just a regular box
+// with 'overflow:hidden', the boxobject's frame is an nsXULScrollFrame,
+// the <scrollbox>'s box frame is the scrollframe's "scrolled frame", and
+// the <scrollbox>'s child box is a child of that.
+static nsIFrame* GetScrolledBox(BoxObject* aScrollBox) {
+  nsIFrame* frame = aScrollBox->GetFrame(false);
+  if (!frame) {
+    return nullptr;
+  }
+
+  nsIScrollableFrame* scrollFrame = do_QueryFrame(frame);
+  if (!scrollFrame) {
+    NS_WARNING("ScrollBoxObject attached to something that's not a scroll frame!");
+    return nullptr;
+  }
+
+  nsIFrame* scrolledFrame = scrollFrame->GetScrolledFrame();
+  if (!scrolledFrame)
+    return nullptr;
+  return nsBox::GetChildBox(scrolledFrame);
+}
+
+/* void scrollByIndex (long dindexes); */
+void ScrollBoxObject::ScrollByIndex(int32_t dindexes, ErrorResult& aRv)
+{
+    nsIScrollableFrame* sf = GetScrollFrame();
+    if (!sf) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return;
+    }
+
+    nsIFrame* scrolledBox = GetScrolledBox(this);
+    if (!scrolledBox) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return;
+    }
+
+    nsRect rect;
+
+    // now get the scrolled boxes first child.
+    nsIFrame* child = nsBox::GetChildBox(scrolledBox);
+
+    bool horiz = scrolledBox->IsHorizontal();
+    nsPoint cp = sf->GetScrollPosition();
+    nscoord diff = 0;
+    int32_t curIndex = 0;
+    bool isLTR = scrolledBox->IsNormalDirection();
+
+    int32_t frameWidth = 0;
+    if (!isLTR && horiz) {
+      GetWidth(&frameWidth);
+      nsCOMPtr<nsIPresShell> shell = GetPresShell(false);
+      if (!shell) {
+        aRv.Throw(NS_ERROR_UNEXPECTED);
+        return;
+      }
+      frameWidth = nsPresContext::CSSPixelsToAppUnits(frameWidth);
+    }
+
+    // first find out what index we are currently at
+    while(child) {
+      rect = child->GetRect();
+      if (horiz) {
+        // In the left-to-right case we break from the loop when the center of
+        // the current child rect is greater than the scrolled position of
+        // the left edge of the scrollbox
+        // In the right-to-left case we break when the center of the current
+        // child rect is less than the scrolled position of the right edge of
+        // the scrollbox.
+        diff = rect.x + rect.width/2; // use the center, to avoid rounding errors
+        if ((isLTR && diff > cp.x) ||
+            (!isLTR && diff < cp.x + frameWidth)) {
+          break;
+        }
+      } else {
+        diff = rect.y + rect.height/2;// use the center, to avoid rounding errors
+        if (diff > cp.y) {
+          break;
+        }
+      }
+      child = nsBox::GetNextBox(child);
+      curIndex++;
+    }
+
+    int32_t count = 0;
+
+    if (dindexes == 0)
+      return;
+
+    if (dindexes > 0) {
+      while(child) {
+        child = nsBox::GetNextBox(child);
+        if (child) {
+          rect = child->GetRect();
+        }
+        count++;
+        if (count >= dindexes) {
+          break;
+        }
+      }
+
+   } else if (dindexes < 0) {
+      child = nsBox::GetChildBox(scrolledBox);
+      while(child) {
+        rect = child->GetRect();
+        if (count >= curIndex + dindexes) {
+          break;
+        }
+
+        count++;
+        child = nsBox::GetNextBox(child);
+
+      }
+   }
+
+   nscoord csspixel = nsPresContext::CSSPixelsToAppUnits(1);
+   if (horiz) {
+       // In the left-to-right case we scroll so that the left edge of the
+       // selected child is scrolled to the left edge of the scrollbox.
+       // In the right-to-left case we scroll so that the right edge of the
+       // selected child is scrolled to the right edge of the scrollbox.
+
+       nsPoint pt(isLTR ? rect.x : rect.x + rect.width - frameWidth,
+                  cp.y);
+
+       // Use a destination range that ensures the left edge (or right edge,
+       // for RTL) will indeed be visible. Also ensure that the top edge
+       // is visible.
+       nsRect range(pt.x, pt.y, csspixel, 0);
+       if (isLTR) {
+         range.x -= csspixel;
+       }
+       sf->ScrollTo(pt, nsIScrollableFrame::INSTANT, &range);
+   } else {
+       // Use a destination range that ensures the top edge will be visible.
+       nsRect range(cp.x, rect.y - csspixel, 0, csspixel);
+       sf->ScrollTo(nsPoint(cp.x, rect.y), nsIScrollableFrame::INSTANT, &range);
+   }
+}
+
+/* void scrollToLine (in long line); */
+void ScrollBoxObject::ScrollToLine(int32_t line, ErrorResult& aRv)
+{
+  nsIScrollableFrame* sf = GetScrollFrame();
+  if (!sf) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  nscoord y = sf->GetLineScrollAmount().height * line;
+  nsRect range(0, y - nsPresContext::CSSPixelsToAppUnits(1),
+               0, nsPresContext::CSSPixelsToAppUnits(1));
+  sf->ScrollTo(nsPoint(0, y), nsIScrollableFrame::INSTANT, &range);
+}
+
+/* void scrollToElement (Element child); */
+void ScrollBoxObject::ScrollToElement(Element& child, ErrorResult& aRv)
+{
+  nsCOMPtr<nsIPresShell> shell = GetPresShell(false);
+  if (!shell) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return;
+  }
+
+  shell->ScrollContentIntoView(&child,
+                               nsIPresShell::ScrollAxis(
+                                 nsIPresShell::SCROLL_TOP,
+                                 nsIPresShell::SCROLL_ALWAYS),
+                               nsIPresShell::ScrollAxis(
+                                 nsIPresShell::SCROLL_LEFT,
+                                 nsIPresShell::SCROLL_ALWAYS),
+                               nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY |
+                               nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
+}
+
+/* void scrollToIndex (long index); */
+void ScrollBoxObject::ScrollToIndex(int32_t index, ErrorResult& aRv)
+{
+  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+}
+
+int32_t ScrollBoxObject::GetPositionX(ErrorResult& aRv)
+{
+  CSSIntPoint pt;
+  GetPosition(pt, aRv);
+  return pt.x;
+}
+
+int32_t ScrollBoxObject::GetPositionY(ErrorResult& aRv)
+{
+  CSSIntPoint pt;
+  GetPosition(pt, aRv);
+  return pt.y;
+}
+
+int32_t ScrollBoxObject::GetScrolledWidth(ErrorResult& aRv)
+{
+  nsRect scrollRect;
+  GetScrolledSize(scrollRect, aRv);
+  return scrollRect.width;
+}
+
+int32_t ScrollBoxObject::GetScrolledHeight(ErrorResult& aRv)
+{
+  nsRect scrollRect;
+  GetScrolledSize(scrollRect, aRv);
+  return scrollRect.height;
+}
+
+/* private helper */
+void ScrollBoxObject::GetPosition(CSSIntPoint& aPos, ErrorResult& aRv)
+{
+  nsIScrollableFrame* sf = GetScrollFrame();
+  if (!sf) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  aPos = sf->GetScrollPositionCSSPixels();
+}
+
+/* private helper */
+void ScrollBoxObject::GetScrolledSize(nsRect& aRect, ErrorResult& aRv)
+{
+    nsIFrame* scrolledBox = GetScrolledBox(this);
+    if (!scrolledBox) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return;
+    }
+
+    aRect = scrolledBox->GetRect();
+    aRect.width  = nsPresContext::AppUnitsToIntCSSPixels(aRect.width);
+    aRect.height = nsPresContext::AppUnitsToIntCSSPixels(aRect.height);
+}
+
+void ScrollBoxObject::GetPosition(JSContext* cx,
+                                  JS::Handle<JSObject*> x,
+                                  JS::Handle<JSObject*> y,
+                                  ErrorResult& aRv)
+{
+  CSSIntPoint pt;
+  GetPosition(pt, aRv);
+  JS::Rooted<JS::Value> v(cx);
+  if (!ToJSValue(cx, pt.x, &v) ||
+      !JS_SetProperty(cx, x, "value", v)) {
+    aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
+    return;
+  }
+  if (!ToJSValue(cx, pt.y, &v) ||
+      !JS_SetProperty(cx, y, "value", v)) {
+    aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
+    return;
+  }
+}
+
+void ScrollBoxObject::GetScrolledSize(JSContext* cx,
+                                      JS::Handle<JSObject*> width,
+                                      JS::Handle<JSObject*> height,
+                                      ErrorResult& aRv)
+{
+  nsRect rect;
+  GetScrolledSize(rect, aRv);
+  JS::Rooted<JS::Value> v(cx);
+  if (!ToJSValue(cx, rect.width, &v) ||
+      !JS_SetProperty(cx, width, "value", v)) {
+    aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
+    return;
+  }
+  if (!ToJSValue(cx, rect.height, &v) ||
+      !JS_SetProperty(cx, height, "value", v)) {
+    aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
+    return;
+  }
+}
+
+/* void ensureElementIsVisible (in nsIDOMElement child); */
+void ScrollBoxObject::EnsureElementIsVisible(Element& child, ErrorResult& aRv)
+{
+    nsCOMPtr<nsIPresShell> shell = GetPresShell(false);
+    if (!shell) {
+      aRv.Throw(NS_ERROR_UNEXPECTED);
+      return;
+    }
+
+    shell->ScrollContentIntoView(&child,
+                                 nsIPresShell::ScrollAxis(),
+                                 nsIPresShell::ScrollAxis(),
+                                 nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY |
+                                 nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
+}
+
+/* void ensureIndexIsVisible (long index); */
+void ScrollBoxObject::EnsureIndexIsVisible(int32_t index, ErrorResult& aRv)
+{
+  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+}
+
+/* void ensureLineIsVisible (long line); */
+void ScrollBoxObject::EnsureLineIsVisible(int32_t line, ErrorResult& aRv)
+{
+  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+}
+
+} // namespace dom
+} // namespace mozilla
+
+// Creation Routine ///////////////////////////////////////////////////////////////////////
+
+using namespace mozilla::dom;
+
+nsresult
+NS_NewScrollBoxObject(nsIBoxObject** aResult)
+{
+  NS_ADDREF(*aResult = new ScrollBoxObject());
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/layout/xul/ScrollBoxObject.h
@@ -0,0 +1,64 @@
+/* -*- 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 mozilla_dom_ScrollBoxObject_h
+#define mozilla_dom_ScrollBoxObject_h
+
+#include "mozilla/dom/BoxObject.h"
+#include "Units.h"
+
+class nsIScrollableFrame;
+struct nsRect;
+
+namespace mozilla {
+namespace dom {
+
+class ScrollBoxObject MOZ_FINAL : public BoxObject
+{
+public:
+  ScrollBoxObject();
+
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  virtual nsIScrollableFrame* GetScrollFrame();
+
+  void ScrollTo(int32_t x, int32_t y, ErrorResult& aRv);
+  void ScrollBy(int32_t dx, int32_t dy, ErrorResult& aRv);
+  void ScrollByLine(int32_t dlines, ErrorResult& aRv);
+  void ScrollByIndex(int32_t dindexes, ErrorResult& aRv);
+  void ScrollToLine(int32_t line, ErrorResult& aRv);
+  void ScrollToElement(Element& child, ErrorResult& aRv);
+  void ScrollToIndex(int32_t index, ErrorResult& aRv);
+  int32_t GetPositionX(ErrorResult& aRv);
+  int32_t GetPositionY(ErrorResult& aRv);
+  int32_t GetScrolledWidth(ErrorResult& aRv);
+  int32_t GetScrolledHeight(ErrorResult& aRv);
+  void EnsureElementIsVisible(Element& child, ErrorResult& aRv);
+  void EnsureIndexIsVisible(int32_t index, ErrorResult& aRv);
+  void EnsureLineIsVisible(int32_t line, ErrorResult& aRv);
+
+  // Deprecated APIs from old IDL
+  void GetPosition(JSContext* cx,
+                   JS::Handle<JSObject*> x,
+                   JS::Handle<JSObject*> y,
+                   ErrorResult& aRv);
+
+  void GetScrolledSize(JSContext* cx,
+                       JS::Handle<JSObject*> width,
+                       JS::Handle<JSObject*> height,
+                       ErrorResult& aRv);
+
+protected:
+  void GetScrolledSize(nsRect& aRect, ErrorResult& aRv);
+  void GetPosition(CSSIntPoint& aPos, ErrorResult& aRv);
+
+private:
+  ~ScrollBoxObject();
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_ScrollBoxObject_h
--- a/layout/xul/moz.build
+++ b/layout/xul/moz.build
@@ -8,89 +8,95 @@ if CONFIG['ENABLE_TESTS']:
     MOCHITEST_MANIFESTS += ['test/mochitest.ini']
     MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
     BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
 XPIDL_SOURCES += [
     'nsIBoxObject.idl',
     'nsIBrowserBoxObject.idl',
     'nsIContainerBoxObject.idl',
-    'nsIEditorBoxObject.idl',
-    'nsIIFrameBoxObject.idl',
     'nsIListBoxObject.idl',
     'nsIMenuBoxObject.idl',
-    'nsIPopupBoxObject.idl',
     'nsIScrollBoxObject.idl',
     'nsISliderListener.idl',
 ]
 
 XPIDL_MODULE = 'layout_xul'
 
 EXPORTS += [
     'nsBox.h',
     'nsIScrollbarMediator.h',
     'nsPIBoxObject.h',
+    'nsPIListBoxObject.h',
     'nsXULPopupManager.h',
 ]
 
+EXPORTS.mozilla.dom += [
+    'BoxObject.h',
+    'ContainerBoxObject.h',
+    'ListBoxObject.h',
+    'MenuBoxObject.h',
+    'PopupBoxObject.h',
+    'ScrollBoxObject.h',
+]
+
 UNIFIED_SOURCES += [
+    'BoxObject.cpp',
     'nsBox.cpp',
     'nsBoxFrame.cpp',
     'nsBoxLayout.cpp',
     'nsBoxLayoutState.cpp',
-    'nsBoxObject.cpp',
     'nsButtonBoxFrame.cpp',
     'nsRepeatService.cpp',
     'nsRootBoxFrame.cpp',
     'nsScrollbarButtonFrame.cpp',
     'nsScrollbarFrame.cpp',
     'nsScrollBoxFrame.cpp',
     'nsSliderFrame.cpp',
     'nsSprocketLayout.cpp',
     'nsStackFrame.cpp',
     'nsStackLayout.cpp',
     'nsXULTooltipListener.cpp',
 ]
 
 if CONFIG['MOZ_XUL']:
     UNIFIED_SOURCES += [
-        'nsContainerBoxObject.cpp',
+        'ContainerBoxObject.cpp',
+        'ListBoxObject.cpp',
+        'MenuBoxObject.cpp',
         'nsDeckFrame.cpp',
         'nsDocElementBoxFrame.cpp',
         'nsGroupBoxFrame.cpp',
         'nsImageBoxFrame.cpp',
         'nsLeafBoxFrame.cpp',
         'nsListBoxBodyFrame.cpp',
         'nsListBoxLayout.cpp',
-        'nsListBoxObject.cpp',
         'nsListItemFrame.cpp',
         'nsMenuBarFrame.cpp',
         'nsMenuBarListener.cpp',
-        'nsMenuBoxObject.cpp',
         'nsMenuFrame.cpp',
         'nsMenuPopupFrame.cpp',
-        'nsPopupBoxObject.cpp',
         'nsPopupSetFrame.cpp',
         'nsProgressMeterFrame.cpp',
         'nsResizerFrame.cpp',
-        'nsScrollBoxObject.cpp',
         'nsSplitterFrame.cpp',
         'nsTextBoxFrame.cpp',
         'nsTitleBarFrame.cpp',
         'nsXULLabelFrame.cpp',
         'nsXULPopupManager.cpp',
+        'PopupBoxObject.cpp',
+        'ScrollBoxObject.cpp',
     ]
 
 if CONFIG['MOZ_XUL']:
     DIRS += ['tree', 'grid']
 
 FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '../base',
     '../generic',
     '../style',
     '/content/base/src',
 ]
-
deleted file mode 100644
--- a/layout/xul/nsContainerBoxObject.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsCOMPtr.h"
-#include "nsIContainerBoxObject.h"
-#include "nsIBrowserBoxObject.h"
-#include "nsIEditorBoxObject.h"
-#include "nsIIFrameBoxObject.h"
-#include "nsBoxObject.h"
-#include "nsIDocShell.h"
-#include "nsIContent.h"
-#include "nsIDocument.h"
-#include "nsIFrame.h"
-#include "nsSubDocumentFrame.h"
-
-/**
- * nsContainerBoxObject implements deprecated nsIBrowserBoxObject,
- * nsIEditorBoxObject and nsIIFrameBoxObject interfaces only because of the
- * backward compatibility.
- */
-
-class nsContainerBoxObject : public nsBoxObject,
-                             public nsIBrowserBoxObject,
-                             public nsIEditorBoxObject,
-                             public nsIIFrameBoxObject
-{
-protected:
-  virtual ~nsContainerBoxObject() {}
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSICONTAINERBOXOBJECT
-  NS_DECL_NSIBROWSERBOXOBJECT
-  NS_DECL_NSIEDITORBOXOBJECT
-  NS_DECL_NSIIFRAMEBOXOBJECT
-};
-
-NS_INTERFACE_MAP_BEGIN(nsContainerBoxObject)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIContainerBoxObject, nsIBrowserBoxObject)
-  NS_INTERFACE_MAP_ENTRY(nsIBrowserBoxObject)
-  NS_INTERFACE_MAP_ENTRY(nsIEditorBoxObject)
-  NS_INTERFACE_MAP_ENTRY(nsIIFrameBoxObject)
-NS_INTERFACE_MAP_END_INHERITING(nsBoxObject)
-
-NS_IMPL_ADDREF_INHERITED(nsContainerBoxObject, nsBoxObject)
-NS_IMPL_RELEASE_INHERITED(nsContainerBoxObject, nsBoxObject)
-
-NS_IMETHODIMP nsContainerBoxObject::GetDocShell(nsIDocShell** aResult)
-{
-  *aResult = nullptr;
-
-  nsSubDocumentFrame *subDocFrame = do_QueryFrame(GetFrame(false));
-  if (subDocFrame) {
-    // Ok, the frame for mContent is an nsSubDocumentFrame, it knows how
-    // to reach the docshell, so ask it...
-
-    return subDocFrame->GetDocShell(aResult);
-  }
-
-  if (!mContent) {
-    return NS_OK;
-  }
-  
-  // No nsSubDocumentFrame available for mContent, try if there's a mapping
-  // between mContent's document to mContent's subdocument.
-
-  nsIDocument *doc = mContent->GetComposedDoc();
-
-  if (!doc) {
-    return NS_OK;
-  }
-  
-  nsIDocument *sub_doc = doc->GetSubDocumentFor(mContent);
-
-  if (!sub_doc) {
-    return NS_OK;
-  }
-
-  NS_IF_ADDREF(*aResult = sub_doc->GetDocShell());
-  return NS_OK;
-}
-
-nsresult
-NS_NewContainerBoxObject(nsIBoxObject** aResult)
-{
-  *aResult = new nsContainerBoxObject();
-  if (!*aResult)
-    return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(*aResult);
-  return NS_OK;
-}
-
--- a/layout/xul/nsIBoxObject.idl
+++ b/layout/xul/nsIBoxObject.idl
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMElement;
 
-[scriptable, uuid(ce572460-b0f2-4650-a9e7-c53a99d3b6ad)]
+[uuid(ce572460-b0f2-4650-a9e7-c53a99d3b6ad)]
 interface nsIBoxObject : nsISupports
 {
   readonly attribute nsIDOMElement element;
 
   readonly attribute long x;
   readonly attribute long y;
   readonly attribute long screenX;
   readonly attribute long screenY;
--- a/layout/xul/nsIBrowserBoxObject.idl
+++ b/layout/xul/nsIBrowserBoxObject.idl
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIContainerBoxObject.idl"
 
 /**
- * @deprecated Please consider using nsIContainerBoxObject.
+ * @deprecated Please consider using ContainerBoxObject.
  */
 
-[scriptable, uuid(db436f2f-c656-4754-b0fa-99bc353bd63f)]
+[uuid(db436f2f-c656-4754-b0fa-99bc353bd63f)]
 interface nsIBrowserBoxObject : nsIContainerBoxObject
 {
 };
 
--- a/layout/xul/nsIContainerBoxObject.idl
+++ b/layout/xul/nsIContainerBoxObject.idl
@@ -1,20 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-interface nsIDocShell;
-interface nsIBoxObject;
+// DEPRECATED: This file exists for shim purposes only,
+// see ContainerBoxObject.webidl
 
-[scriptable, uuid(35d4c04b-3bd3-4375-92e2-a818b4b4acb6)]
+[uuid(35d4c04b-3bd3-4375-92e2-a818b4b4acb6)]
 interface nsIContainerBoxObject : nsISupports
 {
-  readonly attribute nsIDocShell docShell;
 };
-
-%{C++
-nsresult
-NS_NewContainerBoxObject(nsIBoxObject** aResult);
-%}
deleted file mode 100644
--- a/layout/xul/nsIEditorBoxObject.idl
+++ /dev/null
@@ -1,16 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIContainerBoxObject.idl"
-
-/**
- * @deprecated Please consider using nsIContainerBoxObject.
- */
-
-[scriptable, uuid(e3800a23-5b83-49aa-b18c-efa1ac5416e0)]
-interface nsIEditorBoxObject : nsIContainerBoxObject
-{
-};
-
deleted file mode 100644
--- a/layout/xul/nsIIFrameBoxObject.idl
+++ /dev/null
@@ -1,16 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIContainerBoxObject.idl"
-
-/**
- * @deprecated Please consider using nsIContainerBoxObject.
- */
-
-[scriptable, uuid(30114c44-d398-44a5-9e01-b48b711291cd)]
-interface nsIIFrameBoxObject : nsIContainerBoxObject
-{
-};
-
--- a/layout/xul/nsIListBoxObject.idl
+++ b/layout/xul/nsIListBoxObject.idl
@@ -1,31 +1,19 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
+// DEPRECATED: see ListBoxObject.webidl
+
 interface nsIDOMElement;
 
-[scriptable, uuid(AA9DEF4E-2E59-412d-A6DF-B76F52167795)]
+[uuid(AA9DEF4E-2E59-412d-A6DF-B76F52167795)]
 interface nsIListBoxObject : nsISupports
 {
   long getRowCount();
-  long getNumberOfVisibleRows();
-  long getIndexOfFirstVisibleRow();
-
-  void ensureIndexIsVisible(in long rowIndex);
-  void scrollToIndex(in long rowIndex);
-  void scrollByLines(in long numLines);
 
   nsIDOMElement getItemAtIndex(in long index);
   long getIndexOfItem(in nsIDOMElement item);
 };
-
-%{C++
-class nsIBoxObject;
-
-nsresult
-NS_NewListBoxObject(nsIBoxObject** aResult);
-
-%}
--- a/layout/xul/nsIMenuBoxObject.idl
+++ b/layout/xul/nsIMenuBoxObject.idl
@@ -1,30 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-interface nsIDOMElement;
-interface nsIDOMKeyEvent;
+// DEPRECATED: This file exists for shim purposes only,
+// see MenuBoxObject.webidl
 
-[scriptable, uuid(689ebf3d-0184-450a-9bfa-5a26be0e7a8c)]
+[uuid(689ebf3d-0184-450a-9bfa-5a26be0e7a8c)]
 interface nsIMenuBoxObject : nsISupports
 {
-  void openMenu(in boolean openFlag);
-
-  attribute nsIDOMElement activeChild;
-
-  boolean handleKeyPress(in nsIDOMKeyEvent keyEvent);
-
-  // true if the menu or menubar was opened via a keypress.
-  readonly attribute boolean openedWithKey;
 };
-
-%{C++
-class nsIBoxObject;
-
-nsresult
-NS_NewMenuBoxObject(nsIBoxObject** aResult);
-
-%}
--- a/layout/xul/nsIScrollBoxObject.idl
+++ b/layout/xul/nsIScrollBoxObject.idl
@@ -1,52 +1,12 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-interface nsIDOMElement;
 
-
-[scriptable, uuid(56E2ADA8-4631-11d4-BA11-001083023C1E)]
+[uuid(56E2ADA8-4631-11d4-BA11-001083023C1E)]
 interface nsIScrollBoxObject : nsISupports
 {
-  /**
-   * Scroll to the given coordinates, in css pixels.
-   * (0,0) will put the top left corner of the scrolled element's padding-box
-   * at the top left corner of the scrollport (which is its inner-border-box).
-   * Values will be clamped to legal values.
-   */
-  void scrollTo(in long x, in long y);
-
-  /**
-   * Scroll the given amount of device pixels to the right and down.
-   * Values will be clamped to make the resuling position legal.
-   */
-  void scrollBy(in long dx, in long dy);
-
-  void scrollByLine(in long dlines);
-  void scrollByIndex(in long dindexes);
-  void scrollToLine(in long line);
-  void scrollToElement(in nsIDOMElement child);
-  void scrollToIndex(in long index);
-
-  /**
-   * Get the current scroll position in css pixels.
-   * @see scrollTo for the definition of x and y.
-   */
-  void getPosition(out long x, out long y);
-
-  void getScrolledSize(out long width, out long height);
-  void ensureElementIsVisible(in nsIDOMElement child);
-  void ensureIndexIsVisible(in long index);
-  void ensureLineIsVisible(in long line);
 };
-
-%{C++
-class nsIBoxObject;
-
-nsresult
-NS_NewScrollBoxObject(nsIBoxObject** aResult);
-
-%}
--- a/layout/xul/nsListBoxBodyFrame.cpp
+++ b/layout/xul/nsListBoxBodyFrame.cpp
@@ -490,37 +490,28 @@ nsListBoxBodyFrame::ReflowFinished()
 }
 
 void
 nsListBoxBodyFrame::ReflowCallbackCanceled()
 {
   mReflowCallbackPosted = false;
 }
 
-///////// nsIListBoxObject ///////////////
+///////// ListBoxObject ///////////////
 
-nsresult
-nsListBoxBodyFrame::GetRowCount(int32_t* aResult)
+int32_t
+nsListBoxBodyFrame::GetNumberOfVisibleRows()
 {
-  *aResult = GetRowCount();
-  return NS_OK;
+  return mRowHeight ? GetAvailableHeight() / mRowHeight : 0;
 }
 
-nsresult
-nsListBoxBodyFrame::GetNumberOfVisibleRows(int32_t *aResult)
+int32_t
+nsListBoxBodyFrame::GetIndexOfFirstVisibleRow()
 {
-  *aResult= mRowHeight ? GetAvailableHeight() / mRowHeight : 0;
-  return NS_OK;
-}
-
-nsresult
-nsListBoxBodyFrame::GetIndexOfFirstVisibleRow(int32_t *aResult)
-{
-  *aResult = mCurrentIndex;
-  return NS_OK;
+  return mCurrentIndex;
 }
 
 nsresult
 nsListBoxBodyFrame::EnsureIndexIsVisible(int32_t aRowIndex)
 {
   if (aRowIndex < 0)
     return NS_ERROR_ILLEGAL_VALUE;
 
@@ -556,19 +547,18 @@ nsListBoxBodyFrame::EnsureIndexIsVisible
   // box object.
   DoInternalPositionChangedSync(up, delta);
   return NS_OK;
 }
 
 nsresult
 nsListBoxBodyFrame::ScrollByLines(int32_t aNumLines)
 {
-  int32_t scrollIndex, visibleRows;
-  GetIndexOfFirstVisibleRow(&scrollIndex);
-  GetNumberOfVisibleRows(&visibleRows);
+  int32_t scrollIndex = GetIndexOfFirstVisibleRow(),
+    visibleRows = GetNumberOfVisibleRows();
 
   scrollIndex += aNumLines;
   
   if (scrollIndex < 0)
     scrollIndex = 0;
   else {
     int32_t numRows = GetRowCount();
     int32_t lastPageTopRow = numRows - visibleRows;
--- a/layout/xul/nsListBoxBodyFrame.h
+++ b/layout/xul/nsListBoxBodyFrame.h
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsListBoxBodyFrame_h
 #define nsListBoxBodyFrame_h
 
 #include "mozilla/Attributes.h"
 #include "nsCOMPtr.h"
 #include "nsBoxFrame.h"
-#include "nsIListBoxObject.h"
 #include "nsIScrollbarMediator.h"
 #include "nsIReflowCallback.h"
 #include "nsBoxLayoutState.h"
 #include "nsThreadUtils.h"
 #include "nsPIBoxObject.h"
 
 class nsPresContext;
 class nsListScrollSmoother;
@@ -29,20 +28,19 @@ class nsListBoxBodyFrame MOZ_FINAL : pub
                      nsBoxLayout* aLayoutManager);
   virtual ~nsListBoxBodyFrame();
 
 public:
   NS_DECL_QUERYFRAME_TARGET(nsListBoxBodyFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
-  // non-virtual nsIListBoxObject
-  nsresult GetRowCount(int32_t *aResult);
-  nsresult GetNumberOfVisibleRows(int32_t *aResult);
-  nsresult GetIndexOfFirstVisibleRow(int32_t *aResult);
+  // non-virtual ListBoxObject
+  int32_t GetNumberOfVisibleRows();
+  int32_t GetIndexOfFirstVisibleRow();
   nsresult EnsureIndexIsVisible(int32_t aRowIndex);
   nsresult ScrollToIndex(int32_t aRowIndex);
   nsresult ScrollByLines(int32_t aNumLines);
   nsresult GetItemAtIndex(int32_t aIndex, nsIDOMElement **aResult);
   nsresult GetIndexOfItem(nsIDOMElement *aItem, int32_t *aResult);
 
   friend nsIFrame* NS_NewListBoxBodyFrame(nsIPresShell* aPresShell,
                                           nsStyleContext* aContext);
--- a/layout/xul/nsMenuPopupFrame.cpp
+++ b/layout/xul/nsMenuPopupFrame.cpp
@@ -29,17 +29,16 @@
 #include "nsIScrollableFrame.h"
 #include "nsIRootBox.h"
 #include "nsIDocShell.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsContentUtils.h"
 #include "nsCSSFrameConstructor.h"
-#include "nsIPopupBoxObject.h"
 #include "nsPIWindowRoot.h"
 #include "nsIReflowCallback.h"
 #include "nsBindingManager.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIBaseWindow.h"
 #include "nsISound.h"
 #include "nsIScreenManager.h"
 #include "nsIServiceManager.h"
@@ -48,19 +47,21 @@
 #include "nsDisplayList.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/PopupBoxObject.h"
 #include <algorithm>
 
 using namespace mozilla;
+using mozilla::dom::PopupBoxObject;
 
 int8_t nsMenuPopupFrame::sDefaultLevelIsTop = -1;
 
 // NS_NewMenuPopupFrame
 //
 // Wrapper for creating a new menu popup container
 //
 nsIFrame*
@@ -83,17 +84,17 @@ nsMenuPopupFrame::nsMenuPopupFrame(nsIPr
   mCurrentMenu(nullptr),
   mPrefSize(-1, -1),
   mLastClientOffset(0, 0),
   mPopupType(ePopupTypePanel),
   mPopupState(ePopupClosed),
   mPopupAlignment(POPUPALIGNMENT_NONE),
   mPopupAnchor(POPUPALIGNMENT_NONE),
   mPosition(POPUPPOSITION_UNKNOWN),
-  mConsumeRollupEvent(nsIPopupBoxObject::ROLLUP_DEFAULT),
+  mConsumeRollupEvent(PopupBoxObject::ROLLUP_DEFAULT),
   mFlip(FlipType_Default),
   mIsOpenChanged(false),
   mIsContextMenu(false),
   mAdjustOffsetForContextMenu(false),
   mGeneratedChildren(false),
   mMenuCanOverlapOSBar(false),
   mShouldAutoPosition(true),
   mInContentShell(true),
@@ -1504,31 +1505,35 @@ void nsMenuPopupFrame::CanAdjustEdges(in
       aChange.y = 0;
     }
   }
 }
 
 bool nsMenuPopupFrame::ConsumeOutsideClicks()
 {
   // If the popup has explicitly set a consume mode, honor that.
-  if (mConsumeRollupEvent != nsIPopupBoxObject::ROLLUP_DEFAULT)
-    return (mConsumeRollupEvent == nsIPopupBoxObject::ROLLUP_CONSUME);
+  if (mConsumeRollupEvent != PopupBoxObject::ROLLUP_DEFAULT) {
+    return (mConsumeRollupEvent == PopupBoxObject::ROLLUP_CONSUME);
+  }
 
   if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::consumeoutsideclicks,
-                            nsGkAtoms::_true, eCaseMatters))
+                            nsGkAtoms::_true, eCaseMatters)) {
     return true;
+  }
   if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::consumeoutsideclicks,
-                            nsGkAtoms::_false, eCaseMatters))
+                            nsGkAtoms::_false, eCaseMatters)) {
     return false;
+  }
 
   nsCOMPtr<nsIContent> parentContent = mContent->GetParent();
   if (parentContent) {
     dom::NodeInfo *ni = parentContent->NodeInfo();
-    if (ni->Equals(nsGkAtoms::menulist, kNameSpaceID_XUL))
+    if (ni->Equals(nsGkAtoms::menulist, kNameSpaceID_XUL)) {
       return true;  // Consume outside clicks for combo boxes on all platforms
+    }
 #if defined(XP_WIN)
     // Don't consume outside clicks for menus in Windows
     if (ni->Equals(nsGkAtoms::menu, kNameSpaceID_XUL) ||
         ni->Equals(nsGkAtoms::splitmenu, kNameSpaceID_XUL) ||
         ni->Equals(nsGkAtoms::popupset, kNameSpaceID_XUL) ||
         ((ni->Equals(nsGkAtoms::button, kNameSpaceID_XUL) ||
           ni->Equals(nsGkAtoms::toolbarbutton, kNameSpaceID_XUL)) &&
          (parentContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
@@ -1536,18 +1541,19 @@ bool nsMenuPopupFrame::ConsumeOutsideCli
           parentContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
                                      nsGkAtoms::menuButton, eCaseMatters)))) {
       return false;
     }
 #endif
     if (ni->Equals(nsGkAtoms::textbox, kNameSpaceID_XUL)) {
       // Don't consume outside clicks for autocomplete widget
       if (parentContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                                     nsGkAtoms::autocomplete, eCaseMatters))
+                                     nsGkAtoms::autocomplete, eCaseMatters)) {
         return false;
+      }
     }
   }
 
   return true;
 }
 
 // XXXroc this is megalame. Fossicking around for a frame of the right
 // type is a recipe for disaster in the long term.
@@ -1858,17 +1864,17 @@ nsMenuPopupFrame::GetWidget()
     return nullptr;
 
   return view->GetWidget();
 }
 
 void
 nsMenuPopupFrame::AttachedDismissalListener()
 {
-  mConsumeRollupEvent = nsIPopupBoxObject::ROLLUP_DEFAULT;
+  mConsumeRollupEvent = PopupBoxObject::ROLLUP_DEFAULT;
 }
 
 // helpers /////////////////////////////////////////////////////////////
 
 nsresult 
 nsMenuPopupFrame::AttributeChanged(int32_t aNameSpaceID,
                                    nsIAtom* aAttribute,
                                    int32_t aModType)
@@ -1899,17 +1905,17 @@ nsMenuPopupFrame::AttributeChanged(int32
 }
 
 void
 nsMenuPopupFrame::MoveToAttributePosition()
 {
   // Move the widget around when the user sets the |left| and |top| attributes. 
   // Note that this is not the best way to move the widget, as it results in lots
   // of FE notifications and is likely to be slow as molasses. Use |moveTo| on
-  // nsIPopupBoxObject if possible. 
+  // PopupBoxObject if possible.
   nsAutoString left, top;
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::left, left);
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::top, top);
   nsresult err1, err2;
   int32_t xpos = left.ToInteger(&err1);
   int32_t ypos = top.ToInteger(&err2);
 
   if (NS_SUCCEEDED(err1) && NS_SUCCEEDED(err2))
--- a/layout/xul/nsMenuPopupFrame.h
+++ b/layout/xul/nsMenuPopupFrame.h
@@ -511,18 +511,18 @@ protected:
   nsPopupType mPopupType; // type of popup
   nsPopupState mPopupState; // open state of the popup
 
   // popup alignment relative to the anchor node
   int8_t mPopupAlignment;
   int8_t mPopupAnchor;
   int8_t mPosition;
 
-  // One of nsIPopupBoxObject::ROLLUP_DEFAULT/ROLLUP_CONSUME/ROLLUP_NO_CONSUME
-  int8_t mConsumeRollupEvent;
+  // One of PopupBoxObject::ROLLUP_DEFAULT/ROLLUP_CONSUME/ROLLUP_NO_CONSUME
+  uint8_t mConsumeRollupEvent;
   FlipType mFlip; // Whether to flip
 
   bool mIsOpenChanged; // true if the open state changed since the last layout
   bool mIsContextMenu; // true for context menus
   // true if we need to offset the popup to ensure it's not under the mouse
   bool mAdjustOffsetForContextMenu;
   bool mGeneratedChildren; // true if the contents have been created
 
deleted file mode 100644
--- a/layout/xul/nsScrollBoxObject.cpp
+++ /dev/null
@@ -1,331 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsCOMPtr.h"
-#include "nsIScrollBoxObject.h"
-#include "nsBoxObject.h"
-#include "nsIPresShell.h"
-#include "nsIContent.h"
-#include "nsIDOMElement.h"
-#include "nsPresContext.h"
-#include "nsBox.h"
-#include "nsIScrollableFrame.h"
-
-using namespace mozilla;
-
-class nsScrollBoxObject MOZ_FINAL : public nsIScrollBoxObject,
-                                    public nsBoxObject
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSISCROLLBOXOBJECT
-
-  nsScrollBoxObject();
-
-  virtual nsIScrollableFrame* GetScrollFrame() {
-    return do_QueryFrame(GetFrame(false));
-  }
-
-protected:
-  virtual ~nsScrollBoxObject();
-};
-
-/* Implementation file */
-
-NS_INTERFACE_MAP_BEGIN(nsScrollBoxObject)
-  NS_INTERFACE_MAP_ENTRY(nsIScrollBoxObject)
-NS_INTERFACE_MAP_END_INHERITING(nsBoxObject)
-
-NS_IMPL_ADDREF_INHERITED(nsScrollBoxObject, nsBoxObject)
-NS_IMPL_RELEASE_INHERITED(nsScrollBoxObject, nsBoxObject)
-
-nsScrollBoxObject::nsScrollBoxObject()
-{
-  /* member initializers and constructor code */
-}
-
-nsScrollBoxObject::~nsScrollBoxObject()
-{
-  /* destructor code */
-}
-
-/* void scrollTo (in long x, in long y); */
-NS_IMETHODIMP nsScrollBoxObject::ScrollTo(int32_t x, int32_t y)
-{
-  nsIScrollableFrame* sf = GetScrollFrame();
-  if (!sf)
-    return NS_ERROR_FAILURE;
-  sf->ScrollToCSSPixels(CSSIntPoint(x, y));
-  return NS_OK;
-}
-
-/* void scrollBy (in long dx, in long dy); */
-NS_IMETHODIMP nsScrollBoxObject::ScrollBy(int32_t dx, int32_t dy)
-{
-  int32_t x, y;
-  nsresult rv = GetPosition(&x, &y);
-  if (NS_FAILED(rv))
-    return rv;
-
-  return ScrollTo(x + dx, y + dy);
-}
-
-/* void scrollByLine (in long dlines); */
-NS_IMETHODIMP nsScrollBoxObject::ScrollByLine(int32_t dlines)
-{
-  nsIScrollableFrame* sf = GetScrollFrame();
-  if (!sf)
-    return NS_ERROR_FAILURE;
-
-  sf->ScrollBy(nsIntPoint(0, dlines), nsIScrollableFrame::LINES,
-               nsIScrollableFrame::SMOOTH);
-  return NS_OK;
-}
-
-// XUL <scrollbox> elements have a single box child element.
-// Get a pointer to that box.
-// Note that now that the <scrollbox> is just a regular box
-// with 'overflow:hidden', the boxobject's frame is an nsXULScrollFrame,
-// the <scrollbox>'s box frame is the scrollframe's "scrolled frame", and
-// the <scrollbox>'s child box is a child of that.
-static nsIFrame* GetScrolledBox(nsBoxObject* aScrollBox) {
-  nsIFrame* frame = aScrollBox->GetFrame(false);
-  if (!frame) 
-    return nullptr;
-  nsIScrollableFrame* scrollFrame = do_QueryFrame(frame);
-  if (!scrollFrame) {
-    NS_WARNING("nsIScrollBoxObject attached to something that's not a scroll frame!");
-    return nullptr;
-  }
-  nsIFrame* scrolledFrame = scrollFrame->GetScrolledFrame();
-  if (!scrolledFrame)
-    return nullptr;
-  return nsBox::GetChildBox(scrolledFrame);
-}
-
-/* void scrollByIndex (in long dindexes); */
-NS_IMETHODIMP nsScrollBoxObject::ScrollByIndex(int32_t dindexes)
-{
-    nsIScrollableFrame* sf = GetScrollFrame();
-    if (!sf)
-       return NS_ERROR_FAILURE;
-    nsIFrame* scrolledBox = GetScrolledBox(this);
-    if (!scrolledBox)
-       return NS_ERROR_FAILURE;
-
-    nsRect rect;
-
-    // now get the scrolled boxes first child.
-    nsIFrame* child = nsBox::GetChildBox(scrolledBox);
-
-    bool horiz = scrolledBox->IsHorizontal();
-    nsPoint cp = sf->GetScrollPosition();
-    nscoord diff = 0;
-    int32_t curIndex = 0;
-    bool isLTR = scrolledBox->IsNormalDirection();
-
-    int32_t frameWidth = 0;
-    if (!isLTR && horiz) {
-      GetWidth(&frameWidth);
-      nsCOMPtr<nsIPresShell> shell = GetPresShell(false);
-      if (!shell) {
-        return NS_ERROR_UNEXPECTED;
-      }
-      frameWidth = nsPresContext::CSSPixelsToAppUnits(frameWidth);
-    }
-
-    // first find out what index we are currently at
-    while(child) {
-      rect = child->GetRect();
-      if (horiz) {
-        // In the left-to-right case we break from the loop when the center of
-        // the current child rect is greater than the scrolled position of
-        // the left edge of the scrollbox
-        // In the right-to-left case we break when the center of the current
-        // child rect is less than the scrolled position of the right edge of
-        // the scrollbox.
-        diff = rect.x + rect.width/2; // use the center, to avoid rounding errors
-        if ((isLTR && diff > cp.x) ||
-            (!isLTR && diff < cp.x + frameWidth)) {
-          break;
-        }
-      } else {
-        diff = rect.y + rect.height/2;// use the center, to avoid rounding errors
-        if (diff > cp.y) {
-          break;
-        }
-      }
-      child = nsBox::GetNextBox(child);
-      curIndex++;
-    }
-
-    int32_t count = 0;
-
-    if (dindexes == 0)
-       return NS_OK;
-
-    if (dindexes > 0) {
-      while(child) {
-        child = nsBox::GetNextBox(child);
-        if (child)
-          rect = child->GetRect();
-        count++;
-        if (count >= dindexes)
-          break;
-      }
-
-   } else if (dindexes < 0) {
-      child = nsBox::GetChildBox(scrolledBox);
-      while(child) {
-        rect = child->GetRect();
-        if (count >= curIndex + dindexes)
-          break;
-
-        count++;
-        child = nsBox::GetNextBox(child);
-
-      }
-   }
-
-   nscoord csspixel = nsPresContext::CSSPixelsToAppUnits(1);
-   if (horiz) {
-       // In the left-to-right case we scroll so that the left edge of the
-       // selected child is scrolled to the left edge of the scrollbox.
-       // In the right-to-left case we scroll so that the right edge of the
-       // selected child is scrolled to the right edge of the scrollbox.
-
-       nsPoint pt(isLTR ? rect.x : rect.x + rect.width - frameWidth,
-                  cp.y);
-
-       // Use a destination range that ensures the left edge (or right edge,
-       // for RTL) will indeed be visible. Also ensure that the top edge
-       // is visible.
-       nsRect range(pt.x, pt.y, csspixel, 0);
-       if (isLTR) {
-         range.x -= csspixel;
-       }
-       sf->ScrollTo(pt, nsIScrollableFrame::INSTANT, &range);
-   } else {
-       // Use a destination range that ensures the top edge will be visible.
-       nsRect range(cp.x, rect.y - csspixel, 0, csspixel);
-       sf->ScrollTo(nsPoint(cp.x, rect.y), nsIScrollableFrame::INSTANT, &range);
-   }
-
-   return NS_OK;
-}
-
-/* void scrollToLine (in long line); */
-NS_IMETHODIMP nsScrollBoxObject::ScrollToLine(int32_t line)
-{
-  nsIScrollableFrame* sf = GetScrollFrame();
-  if (!sf)
-     return NS_ERROR_FAILURE;
-  
-  nscoord y = sf->GetLineScrollAmount().height * line;
-  nsRect range(0, y - nsPresContext::CSSPixelsToAppUnits(1),
-               0, nsPresContext::CSSPixelsToAppUnits(1));
-  sf->ScrollTo(nsPoint(0, y), nsIScrollableFrame::INSTANT, &range);
-  return NS_OK;
-}
-
-/* void scrollToElement (in nsIDOMElement child); */
-NS_IMETHODIMP nsScrollBoxObject::ScrollToElement(nsIDOMElement *child)
-{
-    NS_ENSURE_ARG_POINTER(child);
-
-    nsCOMPtr<nsIPresShell> shell = GetPresShell(false);
-    if (!shell) {
-      return NS_ERROR_UNEXPECTED;
-    }
-
-    nsCOMPtr<nsIContent> content = do_QueryInterface(child);
-    shell->ScrollContentIntoView(content,
-                                 nsIPresShell::ScrollAxis(
-                                   nsIPresShell::SCROLL_TOP,
-                                   nsIPresShell::SCROLL_ALWAYS),
-                                 nsIPresShell::ScrollAxis(
-                                   nsIPresShell::SCROLL_LEFT,
-                                   nsIPresShell::SCROLL_ALWAYS),
-                                 nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY |
-                                 nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
-    return NS_OK;
-}
-
-/* void scrollToIndex (in long index); */
-NS_IMETHODIMP nsScrollBoxObject::ScrollToIndex(int32_t index)
-{
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* void getPosition (out long x, out long y); */
-NS_IMETHODIMP nsScrollBoxObject::GetPosition(int32_t *x, int32_t *y)
-{
-  nsIScrollableFrame* sf = GetScrollFrame();
-  if (!sf)
-     return NS_ERROR_FAILURE;
-
-  CSSIntPoint pt = sf->GetScrollPositionCSSPixels();
-  *x = pt.x;
-  *y = pt.y;
-
-  return NS_OK;  
-}
-
-/* void getScrolledSize (out long width, out long height); */
-NS_IMETHODIMP nsScrollBoxObject::GetScrolledSize(int32_t *width, int32_t *height)
-{
-    nsIFrame* scrolledBox = GetScrolledBox(this);
-    if (!scrolledBox)
-        return NS_ERROR_FAILURE;
-        	
-    nsRect scrollRect = scrolledBox->GetRect();
-
-    *width  = nsPresContext::AppUnitsToIntCSSPixels(scrollRect.width);
-    *height = nsPresContext::AppUnitsToIntCSSPixels(scrollRect.height);
-
-    return NS_OK;
-}
-
-/* void ensureElementIsVisible (in nsIDOMElement child); */
-NS_IMETHODIMP nsScrollBoxObject::EnsureElementIsVisible(nsIDOMElement *child)
-{
-    NS_ENSURE_ARG_POINTER(child);
-
-    nsCOMPtr<nsIPresShell> shell = GetPresShell(false);
-    if (!shell) {
-      return NS_ERROR_UNEXPECTED;
-    }
-
-    nsCOMPtr<nsIContent> content = do_QueryInterface(child);
-    shell->ScrollContentIntoView(content,
-                                 nsIPresShell::ScrollAxis(),
-                                 nsIPresShell::ScrollAxis(),
-                                 nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY |
-                                 nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
-    return NS_OK;
-}
-
-/* void ensureIndexIsVisible (in long index); */
-NS_IMETHODIMP nsScrollBoxObject::EnsureIndexIsVisible(int32_t index)
-{
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* void ensureLineIsVisible (in long line); */
-NS_IMETHODIMP nsScrollBoxObject::EnsureLineIsVisible(int32_t line)
-{
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-nsresult
-NS_NewScrollBoxObject(nsIBoxObject** aResult)
-{
-  *aResult = new nsScrollBoxObject;
-  if (!*aResult)
-    return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(*aResult);
-  return NS_OK;
-}
-
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -3,17 +3,16 @@
  * 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 "nsGkAtoms.h"
 #include "nsXULPopupManager.h"
 #include "nsMenuFrame.h"
 #include "nsMenuPopupFrame.h"
 #include "nsMenuBarFrame.h"
-#include "nsIPopupBoxObject.h"
 #include "nsMenuBarListener.h"
 #include "nsContentUtils.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMXULElement.h"
 #include "nsIXULDocument.h"
 #include "nsIXULTemplateBuilder.h"
 #include "nsCSSFrameConstructor.h"
--- a/layout/xul/nsXULTooltipListener.cpp
+++ b/layout/xul/nsXULTooltipListener.cpp
@@ -5,17 +5,16 @@
 
 #include "nsXULTooltipListener.h"
 
 #include "nsIDOMMouseEvent.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDocument.h"
 #include "nsGkAtoms.h"
-#include "nsIPopupBoxObject.h"
 #include "nsMenuPopupFrame.h"
 #include "nsIServiceManager.h"
 #include "nsIDragService.h"
 #include "nsIDragSession.h"
 #ifdef MOZ_XUL
 #include "nsITreeView.h"
 #endif
 #include "nsIScriptContext.h"
@@ -24,16 +23,17 @@
 #include "nsXULPopupManager.h"
 #endif
 #include "nsIRootBox.h"
 #include "nsIBoxObject.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
+#include "mozilla/dom/BoxObject.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsXULTooltipListener* nsXULTooltipListener::mInstance = nullptr;
 
 //////////////////////////////////////////////////////////////////////////
 //// nsISupports
@@ -341,17 +341,17 @@ nsXULTooltipListener::CheckTreeBodyMove(
   GetSourceTreeBoxObject(getter_AddRefs(obx));
   if (bx && obx) {
     int32_t x, y;
     aMouseEvent->GetScreenX(&x);
     aMouseEvent->GetScreenY(&y);
 
     int32_t row;
     nsCOMPtr<nsITreeColumn> col;
-    nsAutoCString obj;
+    nsAutoString obj;
 
     // subtract off the documentElement's boxObject
     int32_t boxX, boxY;
     bx->GetScreenX(&boxX);
     bx->GetScreenY(&boxY);
     x -= boxX;
     y -= boxY;
 
new file mode 100644
--- /dev/null
+++ b/layout/xul/tree/TreeBoxObject.cpp
@@ -0,0 +1,693 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/TreeBoxObject.h"
+#include "nsCOMPtr.h"
+#include "nsIDOMXULElement.h"
+#include "nsIScriptableRegion.h"
+#include "nsIXULTemplateBuilder.h"
+#include "nsTreeContentView.h"
+#include "nsITreeSelection.h"
+#include "ChildIterator.h"
+#include "nsContentUtils.h"
+#include "nsError.h"
+#include "nsTreeBodyFrame.h"
+#include "mozilla/dom/TreeBoxObjectBinding.h"
+#include "nsITreeColumns.h"
+#include "mozilla/dom/DOMRect.h"
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/ToJSValue.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(TreeBoxObject, BoxObject,
+                                   mView)
+
+NS_IMPL_ADDREF_INHERITED(TreeBoxObject, BoxObject)
+NS_IMPL_RELEASE_INHERITED(TreeBoxObject, BoxObject)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TreeBoxObject)
+  NS_INTERFACE_MAP_ENTRY(nsITreeBoxObject)
+NS_INTERFACE_MAP_END_INHERITING(BoxObject)
+
+void
+TreeBoxObject::Clear()
+{
+  ClearCachedValues();
+
+  // Drop the view's ref to us.
+  if (mView) {
+    nsCOMPtr<nsITreeSelection> sel;
+    mView->GetSelection(getter_AddRefs(sel));
+    if (sel)
+      sel->SetTree(nullptr);
+    mView->SetTree(nullptr); // Break the circular ref between the view and us.
+  }
+  mView = nullptr;
+
+  BoxObject::Clear();
+}
+
+
+TreeBoxObject::TreeBoxObject()
+  : mTreeBody(nullptr)
+{
+}
+
+TreeBoxObject::~TreeBoxObject()
+{
+}
+
+static nsIContent* FindBodyElement(nsIContent* aParent)
+{
+  mozilla::dom::FlattenedChildIterator iter(aParent);
+  for (nsIContent* content = iter.GetNextChild(); content; content = iter.GetNextChild()) {
+    mozilla::dom::NodeInfo *ni = content->NodeInfo();
+    if (ni->Equals(nsGkAtoms::treechildren, kNameSpaceID_XUL)) {
+      return content;
+    } else if (ni->Equals(nsGkAtoms::tree, kNameSpaceID_XUL)) {
+      // There are nesting tree elements. Only the innermost should
+      // find the treechilren.
+      return nullptr;
+    } else if (content->IsElement() &&
+               !ni->Equals(nsGkAtoms::_template, kNameSpaceID_XUL)) {
+      nsIContent* result = FindBodyElement(content);
+      if (result)
+        return result;
+    }
+  }
+
+  return nullptr;
+}
+
+nsTreeBodyFrame*
+TreeBoxObject::GetTreeBodyFrame(bool aFlushLayout)
+{
+  // Make sure our frames are up to date, and layout as needed.  We
+  // have to do this before checking for our cached mTreeBody, since
+  // it might go away on style flush, and in any case if aFlushLayout
+  // is true we need to make sure to flush no matter what.
+  // XXXbz except that flushing style when we were not asked to flush
+  // layout here breaks things.  See bug 585123.
+  nsIFrame* frame;
+  if (aFlushLayout) {
+    frame = GetFrame(aFlushLayout);
+    if (!frame)
+      return nullptr;
+  }
+
+  if (mTreeBody) {
+    // Have one cached already.
+    return mTreeBody;
+  }
+
+  if (!aFlushLayout) {
+    frame = GetFrame(aFlushLayout);
+    if (!frame)
+      return nullptr;
+  }
+
+  // Iterate over our content model children looking for the body.
+  nsCOMPtr<nsIContent> content = FindBodyElement(frame->GetContent());
+  if (!content)
+    return nullptr;
+
+  frame = content->GetPrimaryFrame();
+  if (!frame)
+     return nullptr;
+
+  // Make sure that the treebodyframe has a pointer to |this|.
+  nsTreeBodyFrame *treeBody = do_QueryFrame(frame);
+  NS_ENSURE_TRUE(treeBody && treeBody->GetTreeBoxObject() == this, nullptr);
+
+  mTreeBody = treeBody;
+  return mTreeBody;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::GetView(nsITreeView * *aView)
+{
+  if (!mTreeBody) {
+    if (!GetTreeBodyFrame()) {
+      // Don't return an uninitialised view
+      *aView = nullptr;
+      return NS_OK;
+    }
+
+    if (mView)
+      // Our new frame needs to initialise itself
+      return mTreeBody->GetView(aView);
+  }
+  if (!mView) {
+    nsCOMPtr<nsIDOMXULElement> xulele = do_QueryInterface(mContent);
+    if (xulele) {
+      // See if there is a XUL tree builder associated with the element
+      nsCOMPtr<nsIXULTemplateBuilder> builder;
+      xulele->GetBuilder(getter_AddRefs(builder));
+      mView = do_QueryInterface(builder);
+
+      if (!mView) {
+        // No tree builder, create a tree content view.
+        nsresult rv = NS_NewTreeContentView(getter_AddRefs(mView));
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
+
+      // Initialise the frame and view
+      mTreeBody->SetView(mView);
+    }
+  }
+  NS_IF_ADDREF(*aView = mView);
+  return NS_OK;
+}
+
+already_AddRefed<nsITreeView>
+TreeBoxObject::GetView() {
+  nsCOMPtr<nsITreeView> view;
+  GetView(getter_AddRefs(view));
+  return view.forget();
+}
+
+static bool
+CanTrustView(nsISupports* aValue)
+{
+  // Untrusted content is only allowed to specify known-good views
+  if (nsContentUtils::IsCallerChrome())
+    return true;
+  nsCOMPtr<nsINativeTreeView> nativeTreeView = do_QueryInterface(aValue);
+  if (!nativeTreeView || NS_FAILED(nativeTreeView->EnsureNative())) {
+    // XXX ERRMSG need a good error here for developers
+    return false;
+  }
+  return true;
+}
+
+NS_IMETHODIMP TreeBoxObject::SetView(nsITreeView * aView)
+{
+  if (!CanTrustView(aView))
+    return NS_ERROR_DOM_SECURITY_ERR;
+
+  mView = aView;
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    body->SetView(aView);
+
+  return NS_OK;
+}
+
+void TreeBoxObject::SetView(nsITreeView* aView, ErrorResult& aRv)
+{
+  aRv = SetView(aView);
+}
+
+bool TreeBoxObject::Focused()
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->GetFocused();
+  return false;
+}
+
+NS_IMETHODIMP TreeBoxObject::GetFocused(bool* aFocused)
+{
+  *aFocused = Focused();
+  return NS_OK;
+}
+
+NS_IMETHODIMP TreeBoxObject::SetFocused(bool aFocused)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->SetFocused(aFocused);
+  return NS_OK;
+}
+
+NS_IMETHODIMP TreeBoxObject::GetTreeBody(nsIDOMElement** aElement)
+{
+  *aElement = nullptr;
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->GetTreeBody(aElement);
+  return NS_OK;
+}
+
+already_AddRefed<Element>
+TreeBoxObject::GetTreeBody()
+{
+  nsCOMPtr<nsIDOMElement> el;
+  GetTreeBody(getter_AddRefs(el));
+  nsCOMPtr<Element> ret(do_QueryInterface(el));
+  return ret.forget();
+}
+
+already_AddRefed<nsTreeColumns>
+TreeBoxObject::GetColumns()
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->Columns();
+  return nullptr;
+}
+
+NS_IMETHODIMP TreeBoxObject::GetColumns(nsITreeColumns** aColumns)
+{
+  *aColumns = GetColumns().take();
+  return NS_OK;
+}
+
+int32_t TreeBoxObject::RowHeight()
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->RowHeight();
+  return 0;
+}
+
+int32_t TreeBoxObject::RowWidth()
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->RowWidth();
+  return 0;
+}
+
+NS_IMETHODIMP TreeBoxObject::GetRowHeight(int32_t* aRowHeight)
+{
+  *aRowHeight = RowHeight();
+  return NS_OK;
+}
+
+NS_IMETHODIMP TreeBoxObject::GetRowWidth(int32_t *aRowWidth)
+{
+  *aRowWidth = RowWidth();
+  return NS_OK;
+}
+
+int32_t TreeBoxObject::GetFirstVisibleRow()
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->FirstVisibleRow();
+  return 0;
+}
+
+NS_IMETHODIMP TreeBoxObject::GetFirstVisibleRow(int32_t *aFirstVisibleRow)
+{
+  *aFirstVisibleRow = GetFirstVisibleRow();
+  return NS_OK;
+}
+
+int32_t TreeBoxObject::GetLastVisibleRow()
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->LastVisibleRow();
+  return 0;
+}
+
+NS_IMETHODIMP TreeBoxObject::GetLastVisibleRow(int32_t *aLastVisibleRow)
+{
+  *aLastVisibleRow = GetLastVisibleRow();
+  return NS_OK;
+}
+
+int32_t TreeBoxObject::HorizontalPosition()
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->GetHorizontalPosition();
+  return 0;
+}
+
+NS_IMETHODIMP TreeBoxObject::GetHorizontalPosition(int32_t *aHorizontalPosition)
+{
+  *aHorizontalPosition = HorizontalPosition();
+  return NS_OK;
+}
+
+int32_t TreeBoxObject::GetPageLength()
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->PageLength();
+  return 0;
+}
+
+NS_IMETHODIMP TreeBoxObject::GetPageLength(int32_t *aPageLength)
+{
+  *aPageLength = GetPageLength();
+  return NS_OK;
+}
+
+NS_IMETHODIMP TreeBoxObject::GetSelectionRegion(nsIScriptableRegion **aRegion)
+{
+  *aRegion = nullptr;
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->GetSelectionRegion(aRegion);
+  return NS_OK;
+}
+
+already_AddRefed<nsIScriptableRegion>
+TreeBoxObject::SelectionRegion()
+{
+  nsCOMPtr<nsIScriptableRegion> region;
+  GetSelectionRegion(getter_AddRefs(region));
+  return region.forget();
+}
+
+NS_IMETHODIMP
+TreeBoxObject::EnsureRowIsVisible(int32_t aRow)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->EnsureRowIsVisible(aRow);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::EnsureCellIsVisible(int32_t aRow, nsITreeColumn* aCol)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->EnsureCellIsVisible(aRow, aCol);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::ScrollToRow(int32_t aRow)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame(true);
+  if (body)
+    return body->ScrollToRow(aRow);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::ScrollByLines(int32_t aNumLines)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->ScrollByLines(aNumLines);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::ScrollByPages(int32_t aNumPages)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->ScrollByPages(aNumPages);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::ScrollToCell(int32_t aRow, nsITreeColumn* aCol)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->ScrollToCell(aRow, aCol);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::ScrollToColumn(nsITreeColumn* aCol)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->ScrollToColumn(aCol);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::ScrollToHorizontalPosition(int32_t aHorizontalPosition)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->ScrollToHorizontalPosition(aHorizontalPosition);
+  return NS_OK;
+}
+
+NS_IMETHODIMP TreeBoxObject::Invalidate()
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->Invalidate();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::InvalidateColumn(nsITreeColumn* aCol)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->InvalidateColumn(aCol);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::InvalidateRow(int32_t aIndex)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->InvalidateRow(aIndex);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::InvalidateCell(int32_t aRow, nsITreeColumn* aCol)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->InvalidateCell(aRow, aCol);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::InvalidateRange(int32_t aStart, int32_t aEnd)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->InvalidateRange(aStart, aEnd);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::InvalidateColumnRange(int32_t aStart, int32_t aEnd, nsITreeColumn* aCol)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->InvalidateColumnRange(aStart, aEnd, aCol);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::GetRowAt(int32_t x, int32_t y, int32_t *aRow)
+{
+  *aRow = 0;
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->GetRowAt(x, y, aRow);
+  return NS_OK;
+}
+
+int32_t
+TreeBoxObject::GetRowAt(int32_t x, int32_t y)
+{
+  int32_t row;
+  GetRowAt(x, y, &row);
+  return row;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::GetCellAt(int32_t aX, int32_t aY, int32_t *aRow,
+                         nsITreeColumn** aCol, nsAString& aChildElt)
+{
+  *aRow = 0;
+  *aCol = nullptr;
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body) {
+    nsAutoCString element;
+    nsresult retval = body->GetCellAt(aX, aY, aRow, aCol, element);
+    CopyUTF8toUTF16(element, aChildElt);
+    return retval;
+  }
+  return NS_OK;
+}
+
+void
+TreeBoxObject::GetCellAt(int32_t x, int32_t y, TreeCellInfo& aRetVal, ErrorResult& aRv)
+{
+  GetCellAt(x, y, &aRetVal.mRow, getter_AddRefs(aRetVal.mCol), aRetVal.mChildElt);
+}
+
+void
+TreeBoxObject::GetCellAt(JSContext* cx,
+                         int32_t x, int32_t y,
+                         JS::Handle<JSObject*> rowOut,
+                         JS::Handle<JSObject*> colOut,
+                         JS::Handle<JSObject*> childEltOut,
+                         ErrorResult& aRv)
+{
+  int32_t row;
+  nsITreeColumn* col;
+  nsAutoString childElt;
+  GetCellAt(x, y, &row, &col, childElt);
+
+  JS::Rooted<JS::Value> v(cx);
+
+  if (!ToJSValue(cx, row, &v) ||
+      !JS_SetProperty(cx, rowOut, "value", v)) {
+    aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
+    return;
+  }
+  if (!dom::WrapObject(cx, col, &v) ||
+      !JS_SetProperty(cx, colOut, "value", v)) {
+    aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
+    return;
+  }
+  if (!ToJSValue(cx, childElt, &v) ||
+      !JS_SetProperty(cx, childEltOut, "value", v)) {
+    aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
+    return;
+  }
+}
+
+NS_IMETHODIMP
+TreeBoxObject::GetCoordsForCellItem(int32_t aRow, nsITreeColumn* aCol, const nsAString& aElement,
+                                      int32_t *aX, int32_t *aY, int32_t *aWidth, int32_t *aHeight)
+{
+  *aX = *aY = *aWidth = *aHeight = 0;
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  NS_ConvertUTF16toUTF8 element(aElement);
+  if (body)
+    return body->GetCoordsForCellItem(aRow, aCol, element, aX, aY, aWidth, aHeight);
+  return NS_OK;
+}
+
+already_AddRefed<DOMRect>
+TreeBoxObject::GetCoordsForCellItem(int32_t row, nsITreeColumn* col, const nsAString& element, ErrorResult& aRv)
+{
+  int32_t x, y, w, h;
+  GetCoordsForCellItem(row, col, element, &x, &y, &w, &h);
+  nsRefPtr<DOMRect> rect = new DOMRect(mContent, x, y, w, h);
+  return rect.forget();
+}
+
+void
+TreeBoxObject::GetCoordsForCellItem(JSContext* cx,
+                                    int32_t row,
+                                    nsITreeColumn* col,
+                                    const nsAString& element,
+                                    JS::Handle<JSObject*> xOut,
+                                    JS::Handle<JSObject*> yOut,
+                                    JS::Handle<JSObject*> widthOut,
+                                    JS::Handle<JSObject*> heightOut,
+                                    ErrorResult& aRv)
+{
+  int32_t x, y, w, h;
+  GetCoordsForCellItem(row, col, element, &x, &y, &w, &h);
+  JS::Rooted<JS::Value> v(cx, INT_TO_JSVAL(x));
+  if (!JS_SetProperty(cx, xOut, "value", v)) {
+    aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
+    return;
+  }
+  v = INT_TO_JSVAL(y);
+  if (!JS_SetProperty(cx, yOut, "value", v)) {
+    aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
+    return;
+  }
+  v = INT_TO_JSVAL(w);
+  if (!JS_SetProperty(cx, widthOut, "value", v)) {
+    aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
+    return;
+  }
+  v = INT_TO_JSVAL(h);
+  if (!JS_SetProperty(cx, heightOut, "value", v)) {
+    aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
+    return;
+  }
+}
+
+NS_IMETHODIMP
+TreeBoxObject::IsCellCropped(int32_t aRow, nsITreeColumn* aCol, bool *aIsCropped)
+{
+  *aIsCropped = false;
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->IsCellCropped(aRow, aCol, aIsCropped);
+  return NS_OK;
+}
+
+bool
+TreeBoxObject::IsCellCropped(int32_t row, nsITreeColumn* col, ErrorResult& aRv)
+{
+  bool ret;
+  aRv = IsCellCropped(row, col, &ret);
+  return ret;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::RowCountChanged(int32_t aIndex, int32_t aDelta)
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->RowCountChanged(aIndex, aDelta);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::BeginUpdateBatch()
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->BeginUpdateBatch();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::EndUpdateBatch()
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->EndUpdateBatch();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TreeBoxObject::ClearStyleAndImageCaches()
+{
+  nsTreeBodyFrame* body = GetTreeBodyFrame();
+  if (body)
+    return body->ClearStyleAndImageCaches();
+  return NS_OK;
+}
+
+void
+TreeBoxObject::ClearCachedValues()
+{
+  mTreeBody = nullptr;
+}
+
+JSObject*
+TreeBoxObject::WrapObject(JSContext* aCx)
+{
+  return TreeBoxObjectBinding::Wrap(aCx, this);
+}
+
+} // namespace dom
+} // namespace mozilla
+
+// Creation Routine ///////////////////////////////////////////////////////////////////////
+
+using namespace mozilla::dom;
+
+nsresult
+NS_NewTreeBoxObject(nsIBoxObject** aResult)
+{
+  NS_ADDREF(*aResult = new TreeBoxObject());
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/layout/xul/tree/TreeBoxObject.h
@@ -0,0 +1,127 @@
+/* -*- 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 mozilla_dom_TreeBoxObject_h
+#define mozilla_dom_TreeBoxObject_h
+
+#include "mozilla/dom/BoxObject.h"
+#include "nsITreeView.h"
+#include "nsITreeBoxObject.h"
+
+class nsTreeBodyFrame;
+class nsTreeColumns;
+
+namespace mozilla {
+namespace dom {
+
+struct TreeCellInfo;
+class DOMRect;
+
+class TreeBoxObject MOZ_FINAL : public BoxObject,
+                                public nsITreeBoxObject
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TreeBoxObject, BoxObject)
+  NS_DECL_NSITREEBOXOBJECT
+
+  TreeBoxObject();
+
+  nsTreeBodyFrame* GetTreeBodyFrame(bool aFlushLayout = false);
+  nsTreeBodyFrame* GetCachedTreeBodyFrame() { return mTreeBody; }
+
+  //NS_PIBOXOBJECT interfaces
+  virtual void Clear() MOZ_OVERRIDE;
+  virtual void ClearCachedValues() MOZ_OVERRIDE;
+
+  // WebIDL
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  already_AddRefed<nsTreeColumns> GetColumns();
+
+  already_AddRefed<nsITreeView> GetView();
+
+  void SetView(nsITreeView* arg, ErrorResult& aRv);
+
+  bool Focused();
+
+  already_AddRefed<Element> GetTreeBody();
+
+  int32_t RowHeight();
+
+  int32_t RowWidth();
+
+  int32_t HorizontalPosition();
+
+  already_AddRefed<nsIScriptableRegion> SelectionRegion();
+
+  int32_t GetFirstVisibleRow();
+
+  int32_t GetLastVisibleRow();
+
+  int32_t GetPageLength();
+
+  int32_t GetRowAt(int32_t x, int32_t y);
+
+  void GetCellAt(int32_t x, int32_t y, TreeCellInfo& aRetVal, ErrorResult& aRv);
+
+  already_AddRefed<DOMRect> GetCoordsForCellItem(int32_t row,
+                                                 nsITreeColumn* col,
+                                                 const nsAString& element,
+                                                 ErrorResult& aRv);
+
+  bool IsCellCropped(int32_t row, nsITreeColumn* col, ErrorResult& aRv);
+
+  // Deprecated APIs from old IDL
+  void GetCellAt(JSContext* cx,
+                 int32_t x, int32_t y,
+                 JS::Handle<JSObject*> rowOut,
+                 JS::Handle<JSObject*> colOut,
+                 JS::Handle<JSObject*> childEltOut,
+                 ErrorResult& aRv);
+
+  void GetCoordsForCellItem(JSContext* cx,
+                            int32_t row,
+                            nsITreeColumn* col,
+                            const nsAString& element,
+                            JS::Handle<JSObject*> xOut,
+                            JS::Handle<JSObject*> yOut,
+                            JS::Handle<JSObject*> widthOut,
+                            JS::Handle<JSObject*> heightOut,
+                            ErrorResult& aRv);
+
+  // Same signature (except for nsresult return type) as the XPIDL impls
+  // void Invalidate();
+  // void BeginUpdateBatch();
+  // void EndUpdateBatch();
+  // void ClearStyleAndImageCaches();
+  // void SetFocused(bool arg);
+  // void EnsureRowIsVisible(int32_t index);
+  // void EnsureCellIsVisible(int32_t row, nsITreeColumn* col);
+  // void ScrollToRow(int32_t index);
+  // void ScrollByLines(int32_t numLines);
+  // void ScrollByPages(int32_t numPages);
+  // void ScrollToCell(int32_t row, nsITreeColumn* col);
+  // void ScrollToColumn(nsITreeColumn* col);
+  // void ScrollToHorizontalPosition(int32_t horizontalPosition);
+  // void InvalidateColumn(nsITreeColumn* col);
+  // void InvalidateRow(int32_t index);
+  // void InvalidateCell(int32_t row, nsITreeColumn* col);
+  // void InvalidateRange(int32_t startIndex, int32_t endIndex);
+  // void InvalidateColumnRange(int32_t startIndex, int32_t endIndex, nsITreeColumn* col);
+  // void RowCountChanged(int32_t index, int32_t count);
+
+protected:
+  nsTreeBodyFrame* mTreeBody;
+  nsCOMPtr<nsITreeView> mView;
+
+private:
+  ~TreeBoxObject();
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif
--- a/layout/xul/tree/crashtests/585815-iframe.xul
+++ b/layout/xul/tree/crashtests/585815-iframe.xul
@@ -57,17 +57,16 @@
       </treerow>  
     </treeitem> 
   </treechildren>
 </tree>
 
 <script type="text/javascript"><![CDATA[
 function run() {
   var tree = document.getElementsByTagName("tree")[0];
-  var sel = tree.treeBoxObject.view.selection;
+  var sel = tree.view.selection;
   sel.rangedSelect(0, 0, true);
   sel.rangedSelect(1000, 1001, true);
   sel.adjustSelection(1, 0x7fffffff);
 }
 ]]></script>
 
 </window>
-
--- a/layout/xul/tree/moz.build
+++ b/layout/xul/tree/moz.build
@@ -14,32 +14,35 @@ XPIDL_SOURCES += [
 
 XPIDL_MODULE = 'layout_xul_tree'
 
 EXPORTS += [
     'nsTreeColFrame.h',
     'nsTreeUtils.h',
 ]
 
+EXPORTS.mozilla.dom += [
+    'TreeBoxObject.h'
+]
+
 UNIFIED_SOURCES += [
     'nsTreeBodyFrame.cpp',
-    'nsTreeBoxObject.cpp',
     'nsTreeColFrame.cpp',
     'nsTreeColumns.cpp',
     'nsTreeContentView.cpp',
     'nsTreeImageListener.cpp',
     'nsTreeSelection.cpp',
     'nsTreeStyleCache.cpp',
     'nsTreeUtils.cpp',
+    'TreeBoxObject.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '..',
     '../../base',
     '../../forms',
     '../../generic',
     '../../style',
     '/content/base/src',
 ]
-
--- a/layout/xul/tree/nsITreeBoxObject.idl
+++ b/layout/xul/tree/nsITreeBoxObject.idl
@@ -7,17 +7,17 @@
 
 interface nsIDOMElement;
 interface nsITreeView;
 interface nsITreeSelection;
 interface nsITreeColumn;
 interface nsITreeColumns;
 interface nsIScriptableRegion;
 
-[scriptable, uuid(64BA5199-C4F4-4498-BBDC-F8E4C369086C)]
+[uuid(64BA5199-C4F4-4498-BBDC-F8E4C369086C)]
 interface nsITreeBoxObject : nsISupports
 {
   /**
    * Obtain the columns.
    */
   readonly attribute nsITreeColumns columns;
 
   /**
@@ -143,22 +143,22 @@ interface nsITreeBoxObject : nsISupports
    * A hit test that can tell you what cell the mouse is over.  Row is the row index
    * hit,  returns -1 for invalid mouse coordinates.  ColID is the column hit.
    * ChildElt is the pseudoelement hit: this can have values of
    * "cell", "twisty", "image", and "text".
    *
    * The coordinate system is the client coordinate system for the
    * document this boxObject lives in, and the units are CSS pixels.
    */
-  void getCellAt(in long x, in long y, out long row, out nsITreeColumn col, out ACString childElt);
+  void getCellAt(in long x, in long y, out long row, out nsITreeColumn col, out AString childElt);
 
   /** 
    * Find the coordinates of an element within a specific cell. 
    */
-  void getCoordsForCellItem(in long row, in nsITreeColumn col, in ACString element, 
+  void getCoordsForCellItem(in long row, in nsITreeColumn col, in AString element,
                             out long x, out long y, out long width, out long height);
 
   /** 
    * Determine if the text of a cell is being cropped or not.
    */
   boolean isCellCropped(in long row, in nsITreeColumn col);
 
   /**
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -37,32 +37,31 @@
 #include "nsCSSRendering.h"
 #include "nsIXULTemplateBuilder.h"
 #include "nsXPIDLString.h"
 #include "nsContainerFrame.h"
 #include "nsView.h"
 #include "nsViewManager.h"
 #include "nsWidgetsCID.h"
 #include "nsBoxFrame.h"
-#include "nsBoxObject.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 #include "nsBoxLayoutState.h"
 #include "nsTreeContentView.h"
 #include "nsTreeUtils.h"
 #include "nsITheme.h"
 #include "imgIRequest.h"
 #include "imgIContainer.h"
 #include "imgILoader.h"
 #include "mozilla/dom/NodeInfo.h"
 #include "nsContentUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsIScrollableFrame.h"
 #include "nsDisplayList.h"
-#include "nsTreeBoxObject.h"
+#include "mozilla/dom/TreeBoxObject.h"
 #include "nsRenderingContext.h"
 #include "nsIScriptableRegion.h"
 #include <algorithm>
 #include "ScrollbarActivity.h"
 
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #include "nsIWritablePropertyBag2.h"
@@ -327,18 +326,18 @@ nsTreeBodyFrame::EnsureBoxObject()
       nsCOMPtr<nsIBoxObject> box =
         nsDoc->GetBoxObjectFor(parent->AsElement(), ignored);
       // Ensure that we got a native box object.
       nsCOMPtr<nsPIBoxObject> pBox = do_QueryInterface(box);
       if (pBox) {
         nsCOMPtr<nsITreeBoxObject> realTreeBoxObject = do_QueryInterface(pBox);
         if (realTreeBoxObject) {
           nsTreeBodyFrame* innerTreeBoxObject =
-            static_cast<nsTreeBoxObject*>(realTreeBoxObject.get())
-              ->GetCachedTreeBody();
+            static_cast<dom::TreeBoxObject*>(realTreeBoxObject.get())
+              ->GetCachedTreeBodyFrame();
           ENSURE_TRUE(!innerTreeBoxObject || innerTreeBoxObject == this);
           mTreeBoxObject = realTreeBoxObject;
         }
       }
     }
   }
 }
 
@@ -534,23 +533,16 @@ nsTreeBodyFrame::SetView(nsITreeView * a
       PresContext()->PresShell()->PostReflowCallback(this);
     }
   }
  
   return NS_OK;
 }
 
 nsresult
-nsTreeBodyFrame::GetFocused(bool* aFocused)
-{
-  *aFocused = mFocused;
-  return NS_OK;
-}
-
-nsresult
 nsTreeBodyFrame::SetFocused(bool aFocused)
 {
   if (mFocused != aFocused) {
     mFocused = aFocused;
     if (mView) {
       nsCOMPtr<nsITreeSelection> sel;
       mView->GetSelection(getter_AddRefs(sel));
       if (sel)
@@ -565,35 +557,32 @@ nsTreeBodyFrame::GetTreeBody(nsIDOMEleme
 {
   //NS_ASSERTION(mContent, "no content, see bug #104878");
   if (!mContent)
     return NS_ERROR_NULL_POINTER;
 
   return mContent->QueryInterface(NS_GET_IID(nsIDOMElement), (void**)aElement);
 }
 
-nsresult
-nsTreeBodyFrame::GetRowHeight(int32_t* _retval)
-{
-  *_retval = nsPresContext::AppUnitsToIntCSSPixels(mRowHeight);
-  return NS_OK;
-}
-
-nsresult
-nsTreeBodyFrame::GetRowWidth(int32_t *aRowWidth)
+int32_t
+nsTreeBodyFrame::RowHeight() const
 {
-  *aRowWidth = nsPresContext::AppUnitsToIntCSSPixels(CalcHorzWidth(GetScrollParts()));
-  return NS_OK;
+  return nsPresContext::AppUnitsToIntCSSPixels(mRowHeight);
 }
 
-nsresult
-nsTreeBodyFrame::GetHorizontalPosition(int32_t *aHorizontalPosition)
+int32_t
+nsTreeBodyFrame::RowWidth()
 {
-  *aHorizontalPosition = nsPresContext::AppUnitsToIntCSSPixels(mHorzPosition); 
-  return NS_OK;
+  return nsPresContext::AppUnitsToIntCSSPixels(CalcHorzWidth(GetScrollParts()));
+}
+
+int32_t
+nsTreeBodyFrame::GetHorizontalPosition() const
+{
+  return nsPresContext::AppUnitsToIntCSSPixels(mHorzPosition);
 }
 
 nsresult
 nsTreeBodyFrame::GetSelectionRegion(nsIScriptableRegion **aRegion)
 {
   *aRegion = nullptr;
 
   nsCOMPtr<nsITreeSelection> selection;
--- a/layout/xul/tree/nsTreeBodyFrame.h
+++ b/layout/xul/tree/nsTreeBodyFrame.h
@@ -75,22 +75,22 @@ public:
   }
   already_AddRefed<nsITreeView> GetExistingView() const
   {
     nsCOMPtr<nsITreeView> view = mView;
     return view.forget();
   }
   nsresult GetView(nsITreeView **aView);
   nsresult SetView(nsITreeView *aView);
-  nsresult GetFocused(bool *aFocused);
+  bool GetFocused() const { return mFocused; }
   nsresult SetFocused(bool aFocused);
   nsresult GetTreeBody(nsIDOMElement **aElement);
-  nsresult GetRowHeight(int32_t *aValue);
-  nsresult GetRowWidth(int32_t *aValue);
-  nsresult GetHorizontalPosition(int32_t *aValue);
+  int32_t RowHeight() const;
+  int32_t RowWidth();
+  int32_t GetHorizontalPosition() const;
   nsresult GetSelectionRegion(nsIScriptableRegion **aRegion);
   int32_t FirstVisibleRow() const { return mTopRowIndex; }
   int32_t LastVisibleRow() const { return mTopRowIndex + mPageLength; }
   int32_t PageLength() const { return mPageLength; }
   nsresult EnsureRowIsVisible(int32_t aRow);
   nsresult EnsureCellIsVisible(int32_t aRow, nsITreeColumn *aCol);
   nsresult ScrollToRow(int32_t aRow);
   nsresult ScrollByLines(int32_t aNumLines);
deleted file mode 100644
--- a/layout/xul/tree/nsTreeBoxObject.cpp
+++ /dev/null
@@ -1,493 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsTreeBoxObject.h"
-#include "nsCOMPtr.h"
-#include "nsIDOMXULElement.h"
-#include "nsIXULTemplateBuilder.h"
-#include "nsTreeContentView.h"
-#include "nsITreeSelection.h"
-#include "ChildIterator.h"
-#include "nsContentUtils.h"
-#include "nsError.h"
-#include "nsTreeBodyFrame.h"
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(nsTreeBoxObject, nsBoxObject,
-                                   mView)
-
-NS_IMPL_ADDREF_INHERITED(nsTreeBoxObject, nsBoxObject)
-NS_IMPL_RELEASE_INHERITED(nsTreeBoxObject, nsBoxObject)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsTreeBoxObject)
-  NS_INTERFACE_MAP_ENTRY(nsITreeBoxObject)
-NS_INTERFACE_MAP_END_INHERITING(nsBoxObject)
-
-void
-nsTreeBoxObject::Clear()
-{
-  ClearCachedValues();
-
-  // Drop the view's ref to us.
-  if (mView) {
-    nsCOMPtr<nsITreeSelection> sel;
-    mView->GetSelection(getter_AddRefs(sel));
-    if (sel)
-      sel->SetTree(nullptr);
-    mView->SetTree(nullptr); // Break the circular ref between the view and us.
-  }
-  mView = nullptr;
-
-  nsBoxObject::Clear();
-}
-
-
-nsTreeBoxObject::nsTreeBoxObject()
-  : mTreeBody(nullptr)
-{
-}
-
-nsTreeBoxObject::~nsTreeBoxObject()
-{
-  /* destructor code */
-}
-
-static nsIContent* FindBodyElement(nsIContent* aParent)
-{
-  mozilla::dom::FlattenedChildIterator iter(aParent);
-  for (nsIContent* content = iter.GetNextChild(); content; content = iter.GetNextChild()) {
-    mozilla::dom::NodeInfo *ni = content->NodeInfo();
-    if (ni->Equals(nsGkAtoms::treechildren, kNameSpaceID_XUL)) {
-      return content;
-    } else if (ni->Equals(nsGkAtoms::tree, kNameSpaceID_XUL)) {
-      // There are nesting tree elements. Only the innermost should
-      // find the treechilren.
-      return nullptr;
-    } else if (content->IsElement() &&
-               !ni->Equals(nsGkAtoms::_template, kNameSpaceID_XUL)) {
-      nsIContent* result = FindBodyElement(content);
-      if (result)
-        return result;
-    }
-  }
-
-  return nullptr;
-}
-
-nsTreeBodyFrame*
-nsTreeBoxObject::GetTreeBody(bool aFlushLayout)
-{
-  // Make sure our frames are up to date, and layout as needed.  We
-  // have to do this before checking for our cached mTreeBody, since
-  // it might go away on style flush, and in any case if aFlushLayout
-  // is true we need to make sure to flush no matter what.
-  // XXXbz except that flushing style when we were not asked to flush
-  // layout here breaks things.  See bug 585123.
-  nsIFrame* frame;
-  if (aFlushLayout) {
-    frame = GetFrame(aFlushLayout);
-    if (!frame)
-      return nullptr;
-  }
-
-  if (mTreeBody) {
-    // Have one cached already.
-    return mTreeBody;
-  }
-
-  if (!aFlushLayout) {
-    frame = GetFrame(aFlushLayout);
-    if (!frame)
-      return nullptr;
-  }
-
-  // Iterate over our content model children looking for the body.
-  nsCOMPtr<nsIContent> content = FindBodyElement(frame->GetContent());
-  if (!content)
-    return nullptr;
-
-  frame = content->GetPrimaryFrame();
-  if (!frame)
-     return nullptr;
-
-  // Make sure that the treebodyframe has a pointer to |this|.
-  nsTreeBodyFrame *treeBody = do_QueryFrame(frame);
-  NS_ENSURE_TRUE(treeBody && treeBody->GetTreeBoxObject() == this, nullptr);
-
-  mTreeBody = treeBody;
-  return mTreeBody;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::GetView(nsITreeView * *aView)
-{
-  if (!mTreeBody) {
-    if (!GetTreeBody()) {
-      // Don't return an uninitialised view
-      *aView = nullptr;
-      return NS_OK;
-    }
-
-    if (mView)
-      // Our new frame needs to initialise itself
-      return mTreeBody->GetView(aView);
-  }
-  if (!mView) {
-    nsCOMPtr<nsIDOMXULElement> xulele = do_QueryInterface(mContent);
-    if (xulele) {
-      // See if there is a XUL tree builder associated with the element
-      nsCOMPtr<nsIXULTemplateBuilder> builder;
-      xulele->GetBuilder(getter_AddRefs(builder));
-      mView = do_QueryInterface(builder);
-
-      if (!mView) {
-        // No tree builder, create a tree content view.
-        nsresult rv = NS_NewTreeContentView(getter_AddRefs(mView));
-        NS_ENSURE_SUCCESS(rv, rv);
-      }
-
-      // Initialise the frame and view
-      mTreeBody->SetView(mView);
-    }
-  }
-  NS_IF_ADDREF(*aView = mView);
-  return NS_OK;
-}
-
-static bool
-CanTrustView(nsISupports* aValue)
-{
-  // Untrusted content is only allowed to specify known-good views
-  if (nsContentUtils::IsCallerChrome())
-    return true;
-  nsCOMPtr<nsINativeTreeView> nativeTreeView = do_QueryInterface(aValue);
-  if (!nativeTreeView || NS_FAILED(nativeTreeView->EnsureNative())) {
-    // XXX ERRMSG need a good error here for developers
-    return false;
-  }
-  return true;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::SetView(nsITreeView * aView)
-{
-  if (!CanTrustView(aView))
-    return NS_ERROR_DOM_SECURITY_ERR;
-  
-  mView = aView;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    body->SetView(aView);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::GetFocused(bool* aFocused)
-{
-  *aFocused = false;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->GetFocused(aFocused);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::SetFocused(bool aFocused)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->SetFocused(aFocused);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::GetTreeBody(nsIDOMElement** aElement)
-{
-  *aElement = nullptr;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body) 
-    return body->GetTreeBody(aElement);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::GetColumns(nsITreeColumns** aColumns)
-{
-  *aColumns = nullptr;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body) 
-    *aColumns = body->Columns().take();
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::GetRowHeight(int32_t* aRowHeight)
-{
-  *aRowHeight = 0;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body) 
-    return body->GetRowHeight(aRowHeight);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::GetRowWidth(int32_t *aRowWidth)
-{
-  *aRowWidth = 0;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body) 
-    return body->GetRowWidth(aRowWidth);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::GetFirstVisibleRow(int32_t *aFirstVisibleRow)
-{
-  *aFirstVisibleRow = 0;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    *aFirstVisibleRow = body->FirstVisibleRow();
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::GetLastVisibleRow(int32_t *aLastVisibleRow)
-{
-  *aLastVisibleRow = 0;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    *aLastVisibleRow = body->LastVisibleRow();
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::GetHorizontalPosition(int32_t *aHorizontalPosition)
-{
-  *aHorizontalPosition = 0;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->GetHorizontalPosition(aHorizontalPosition);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::GetPageLength(int32_t *aPageLength)
-{
-  *aPageLength = 0;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    *aPageLength = body->PageLength();
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::GetSelectionRegion(nsIScriptableRegion **aRegion)
-{
- *aRegion = nullptr;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->GetSelectionRegion(aRegion);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTreeBoxObject::EnsureRowIsVisible(int32_t aRow)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->EnsureRowIsVisible(aRow);
-  return NS_OK;
-}
-
-NS_IMETHODIMP 
-nsTreeBoxObject::EnsureCellIsVisible(int32_t aRow, nsITreeColumn* aCol)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->EnsureCellIsVisible(aRow, aCol);
-  return NS_OK;
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsTreeBoxObject::ScrollToRow(int32_t aRow)
-{
-  nsTreeBodyFrame* body = GetTreeBody(true);
-  if (body)
-    return body->ScrollToRow(aRow);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTreeBoxObject::ScrollByLines(int32_t aNumLines)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->ScrollByLines(aNumLines);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTreeBoxObject::ScrollByPages(int32_t aNumPages)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->ScrollByPages(aNumPages);
-  return NS_OK;
-}
-
-NS_IMETHODIMP 
-nsTreeBoxObject::ScrollToCell(int32_t aRow, nsITreeColumn* aCol)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->ScrollToCell(aRow, aCol);
-  return NS_OK;
-}
-
-NS_IMETHODIMP 
-nsTreeBoxObject::ScrollToColumn(nsITreeColumn* aCol)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->ScrollToColumn(aCol);
-  return NS_OK;
-}
-
-NS_IMETHODIMP 
-nsTreeBoxObject::ScrollToHorizontalPosition(int32_t aHorizontalPosition)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->ScrollToHorizontalPosition(aHorizontalPosition);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::Invalidate()
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->Invalidate();
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::InvalidateColumn(nsITreeColumn* aCol)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->InvalidateColumn(aCol);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::InvalidateRow(int32_t aIndex)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->InvalidateRow(aIndex);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::InvalidateCell(int32_t aRow, nsITreeColumn* aCol)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->InvalidateCell(aRow, aCol);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::InvalidateRange(int32_t aStart, int32_t aEnd)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->InvalidateRange(aStart, aEnd);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::InvalidateColumnRange(int32_t aStart, int32_t aEnd, nsITreeColumn* aCol)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->InvalidateColumnRange(aStart, aEnd, aCol);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::GetRowAt(int32_t x, int32_t y, int32_t *aRow)
-{
-  *aRow = 0;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->GetRowAt(x, y, aRow);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::GetCellAt(int32_t aX, int32_t aY, int32_t *aRow, nsITreeColumn** aCol,
-                                         nsACString& aChildElt)
-{
-  *aRow = 0;
-  *aCol = nullptr;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->GetCellAt(aX, aY, aRow, aCol, aChildElt);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTreeBoxObject::GetCoordsForCellItem(int32_t aRow, nsITreeColumn* aCol, const nsACString& aElement, 
-                                      int32_t *aX, int32_t *aY, int32_t *aWidth, int32_t *aHeight)
-{
-  *aX = *aY = *aWidth = *aHeight = 0;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->GetCoordsForCellItem(aRow, aCol, aElement, aX, aY, aWidth, aHeight);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTreeBoxObject::IsCellCropped(int32_t aRow, nsITreeColumn* aCol, bool *aIsCropped)
-{  
-  *aIsCropped = false;
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->IsCellCropped(aRow, aCol, aIsCropped);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::RowCountChanged(int32_t aIndex, int32_t aDelta)
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->RowCountChanged(aIndex, aDelta);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::BeginUpdateBatch()
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->BeginUpdateBatch();
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::EndUpdateBatch()
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->EndUpdateBatch();
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsTreeBoxObject::ClearStyleAndImageCaches()
-{
-  nsTreeBodyFrame* body = GetTreeBody();
-  if (body)
-    return body->ClearStyleAndImageCaches();
-  return NS_OK;
-}
-
-void
-nsTreeBoxObject::ClearCachedValues()
-{
-  mTreeBody = nullptr;
-}    
-
-// Creation Routine ///////////////////////////////////////////////////////////////////////
-
-nsresult
-NS_NewTreeBoxObject(nsIBoxObject** aResult)
-{
-  *aResult = new nsTreeBoxObject;
-  if (!*aResult)
-    return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(*aResult);
-  return NS_OK;
-}
-
deleted file mode 100644
--- a/layout/xul/tree/nsTreeBoxObject.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* -*- 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 nsTreeBoxObject_h___
-#define nsTreeBoxObject_h___
-
-#include "mozilla/Attributes.h"
-#include "nsBoxObject.h"
-#include "nsITreeView.h"
-#include "nsITreeBoxObject.h"
-
-class nsTreeBodyFrame;
-
-class nsTreeBoxObject : public nsITreeBoxObject, public nsBoxObject
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsTreeBoxObject, nsBoxObject)
-  NS_DECL_NSITREEBOXOBJECT
-
-  nsTreeBoxObject();
-
-  nsTreeBodyFrame* GetTreeBody(bool aFlushLayout = false);
-  nsTreeBodyFrame* GetCachedTreeBody() { return mTreeBody; }
-
-  //NS_PIBOXOBJECT interfaces
-  virtual void Clear() MOZ_OVERRIDE;
-  virtual void ClearCachedValues() MOZ_OVERRIDE;
-
-protected:
-  ~nsTreeBoxObject();
-  nsTreeBodyFrame* mTreeBody;
-  nsCOMPtr<nsITreeView> mView;
-};
-
-#endif
--- a/layout/xul/tree/nsTreeColFrame.cpp
+++ b/layout/xul/tree/nsTreeColFrame.cpp
@@ -5,19 +5,18 @@
 
 #include "nsCOMPtr.h"
 #include "nsTreeColFrame.h"
 #include "nsGkAtoms.h"
 #include "nsIContent.h"
 #include "nsStyleContext.h"
 #include "nsNameSpaceManager.h"
 #include "nsIBoxObject.h"
-#include "nsTreeBoxObject.h"
+#include "mozilla/dom/TreeBoxObject.h"
 #include "nsIDOMElement.h"
-#include "nsITreeBoxObject.h"
 #include "nsITreeColumns.h"
 #include "nsIDOMXULTreeElement.h"
 #include "nsDisplayList.h"
 #include "nsTreeBodyFrame.h"
 
 //
 // NS_NewTreeColFrame
 //
@@ -183,17 +182,18 @@ nsTreeColFrame::InvalidateColumns(bool a
 {
   nsITreeBoxObject* treeBoxObject = GetTreeBoxObject();
   if (treeBoxObject) {
     nsCOMPtr<nsITreeColumns> columns;
 
     if (aCanWalkFrameTree) {
       treeBoxObject->GetColumns(getter_AddRefs(columns));
     } else {
-      nsTreeBodyFrame* body = static_cast<nsTreeBoxObject*>(treeBoxObject)->GetCachedTreeBody();
+      nsTreeBodyFrame* body = static_cast<mozilla::dom::TreeBoxObject*>
+        (treeBoxObject)->GetCachedTreeBodyFrame();
       if (body) {
         columns = body->Columns();
       }
     }
 
     if (columns)
       columns->InvalidateColumns();
   }
--- a/layout/xul/tree/nsTreeColumns.cpp
+++ b/layout/xul/tree/nsTreeColumns.cpp
@@ -9,16 +9,17 @@
 #include "nsIBoxObject.h"
 #include "nsTreeColumns.h"
 #include "nsTreeUtils.h"
 #include "nsStyleContext.h"
 #include "nsDOMClassInfoID.h"
 #include "nsContentUtils.h"
 #include "nsTreeBodyFrame.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/TreeBoxObject.h"
 #include "mozilla/dom/TreeColumnsBinding.h"
 
 using namespace mozilla;
 
 // Column class that caches all the info about our column.
 nsTreeColumn::nsTreeColumn(nsTreeColumns* aColumns, nsIContent* aContent)
   : mContent(aContent),
     mColumns(aColumns),
@@ -374,20 +375,20 @@ nsTreeColumns::GetParentObject() const
 }
 
 /* virtual */ JSObject*
 nsTreeColumns::WrapObject(JSContext* aCx)
 {
   return dom::TreeColumnsBinding::Wrap(aCx, this);
 }
 
-nsITreeBoxObject*
+dom::TreeBoxObject*
 nsTreeColumns::GetTree() const
 {
-  return mTree ? mTree->GetTreeBoxObject() : nullptr;
+  return mTree ? static_cast<mozilla::dom::TreeBoxObject*>(mTree->GetTreeBoxObject()) : nullptr;
 }
 
 NS_IMETHODIMP
 nsTreeColumns::GetTree(nsITreeBoxObject** _retval)
 {
   NS_IF_ADDREF(*_retval = GetTree());
   return NS_OK;
 }
--- a/layout/xul/tree/nsTreeColumns.h
+++ b/layout/xul/tree/nsTreeColumns.h
@@ -19,16 +19,17 @@ class nsTreeBodyFrame;
 class nsTreeColumns;
 class nsIFrame;
 class nsIContent;
 struct nsRect;
 
 namespace mozilla {
 namespace dom {
 class Element;
+class TreeBoxObject;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_TREECOLUMN_IMPL_CID                       \
 { /* 02cd1963-4b5d-4a6c-9223-814d3ade93a3 */         \
     0x02cd1963,                                      \
     0x4b5d,                                          \
     0x4a6c,                                          \
@@ -135,17 +136,17 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsTreeColumns)
   NS_DECL_NSITREECOLUMNS
 
   nsIContent* GetParentObject() const;
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   // WebIDL
-  nsITreeBoxObject* GetTree() const;
+  mozilla::dom::TreeBoxObject* GetTree() const;
   uint32_t Count();
   uint32_t Length()
   {
     return Count();
   }
 
   nsTreeColumn* GetFirstColumn() { EnsureColumns(); return mFirstColumn; }
   nsTreeColumn* GetLastColumn();
--- a/layout/xul/tree/nsTreeSelection.cpp
+++ b/layout/xul/tree/nsTreeSelection.cpp
@@ -260,17 +260,16 @@ nsTreeSelection::~nsTreeSelection()
 
 NS_IMPL_CYCLE_COLLECTION(nsTreeSelection, mTree, mCurrentColumn)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTreeSelection)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTreeSelection)
 
 DOMCI_DATA(TreeSelection, nsTreeSelection)
 
-// QueryInterface implementation for nsBoxObject
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTreeSelection)
   NS_INTERFACE_MAP_ENTRY(nsITreeSelection)
   NS_INTERFACE_MAP_ENTRY(nsINativeTreeSelection)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TreeSelection)
 NS_INTERFACE_MAP_END
 
 NS_IMETHODIMP nsTreeSelection::GetTree(nsITreeBoxObject * *aTree)
--- a/security/manager/pki/resources/content/certManager.js
+++ b/security/manager/pki/resources/content/certManager.js
@@ -52,42 +52,37 @@ function LoadCerts()
   certdb = Components.classes[nsX509CertDB].getService(nsIX509CertDB);
   var certcache = Components.classes[nsNSSCertCache].createInstance(nsINSSCertCache);
   
   certcache.cacheAllCerts();
 
   caTreeView = Components.classes[nsCertTree]
                     .createInstance(nsICertTree);
   caTreeView.loadCertsFromCache(certcache, nsIX509Cert.CA_CERT);
-  document.getElementById('ca-tree')
-   .treeBoxObject.view = caTreeView;
+  document.getElementById('ca-tree').view = caTreeView;
 
   serverTreeView = Components.classes[nsCertTree]
                         .createInstance(nsICertTree);
   serverTreeView.loadCertsFromCache(certcache, nsIX509Cert.SERVER_CERT);
-  document.getElementById('server-tree')
-   .treeBoxObject.view = serverTreeView;
+  document.getElementById('server-tree').view = serverTreeView;
 
   emailTreeView = Components.classes[nsCertTree]
                        .createInstance(nsICertTree);
   emailTreeView.loadCertsFromCache(certcache, nsIX509Cert.EMAIL_CERT);
-  document.getElementById('email-tree')
-   .treeBoxObject.view = emailTreeView; 
+  document.getElementById('email-tree').view = emailTreeView;
 
   userTreeView = Components.classes[nsCertTree]
                       .createInstance(nsICertTree);
   userTreeView.loadCertsFromCache(certcache, nsIX509Cert.USER_CERT);
-  document.getElementById('user-tree')
-   .treeBoxObject.view = userTreeView;
+  document.getElementById('user-tree').view = userTreeView;
 
   orphanTreeView = Components.classes[nsCertTree]
                       .createInstance(nsICertTree);
   orphanTreeView.loadCertsFromCache(certcache, nsIX509Cert.UNKNOWN_CERT);
-  document.getElementById('orphan-tree')
-   .treeBoxObject.view = orphanTreeView;
+  document.getElementById('orphan-tree').view = orphanTreeView;
 
   enableBackupAllButton();
 }
 
 function enableBackupAllButton()
 {
   var rowCnt = userTreeView.rowCount;
   var backupAllButton=document.getElementById('mine_backupAllButton');
--- a/security/manager/pki/resources/content/viewCertDetails.js
+++ b/security/manager/pki/resources/content/viewCertDetails.js
@@ -118,35 +118,34 @@ function addTreeItemToTreeChild(treeChil
     treeCell.setAttribute("display",value);
   treeRow.appendChild(treeCell);
   treeElem1.appendChild(treeRow);
   treeChild.appendChild(treeElem1);
   return treeElem1;
 }
 
 function displaySelected() {
-  var asn1Tree = document.getElementById('prettyDumpTree').
-                     treeBoxObject.view.QueryInterface(nsIASN1Tree);
+  var asn1Tree = document.getElementById('prettyDumpTree')
+          .view.QueryInterface(nsIASN1Tree);
   var items = asn1Tree.selection;
   var certDumpVal = document.getElementById('certDumpVal');
   if (items.currentIndex != -1) {
     var value = asn1Tree.getDisplayData(items.currentIndex);
     certDumpVal.value = value;
   } else {
     certDumpVal.value ="";
   }
 }
 
 function BuildPrettyPrint(cert)
 {
   var certDumpTree = Components.classes[nsASN1Tree].
                           createInstance(nsIASN1Tree);
   certDumpTree.loadASN1Structure(cert.ASN1Structure);
-  document.getElementById('prettyDumpTree').
-           treeBoxObject.view =  certDumpTree;
+  document.getElementById('prettyDumpTree').view = certDumpTree;
 }
 
 function addAttributeFromCert(nodeName, value)
 {
   var node = document.getElementById(nodeName);
   if (!value) {
     value = bundle.getString('notPresent');
   }
@@ -251,18 +250,18 @@ function DisplayGeneralDataFromCert(cert
   issuerOrgUnit = cert.issuerOrganizationUnit;
   addAttributeFromCert('issuercommonname', issuerCommonname);
   addAttributeFromCert('issuerorganization', issuerOrg);
   addAttributeFromCert('issuerorgunit', issuerOrgUnit);
 }
 
 function updateCertDump()
 {
-  var asn1Tree = document.getElementById('prettyDumpTree').
-                     treeBoxObject.view.QueryInterface(nsIASN1Tree);
+  var asn1Tree = document.getElementById('prettyDumpTree')
+          .view.QueryInterface(nsIASN1Tree);
 
   var tree = document.getElementById('treesetDump');
   if (tree.currentIndex < 0) {
     doPrompt("No items are selected."); //This should never happen.
   } else {
     var item = tree.contentView.getItemAtIndex(tree.currentIndex);
     var dbKey = item.firstChild.firstChild.getAttribute('display');
     //  Get the cert from the cert database
--- a/services/sync/tps/extensions/mozmill/resource/driver/mozelement.js
+++ b/services/sync/tps/extensions/mozmill/resource/driver/mozelement.js
@@ -1007,17 +1007,17 @@ MozMillDropList.prototype = Object.creat
                         getElementsByTagNameNS(NAMESPACE_XUL, "menupopup")[0].
                         getElementsByTagNameNS(NAMESPACE_XUL, "menuitem");
 
         var item = null;
 
         if (index != undefined) {
           if (index == -1) {
             this.dispatchEvent('focus', false);
-            this.element.boxObject.QueryInterface(Ci.nsIMenuBoxObject).activeChild = null;
+            this.element.boxObject.activeChild = null;
             this.dispatchEvent('change', true);
 
             broker.pass({'function':'MozMillDropList.select()'});
 
             return true;
           } else {
             item = menuitems[index];
           }
--- a/testing/mochitest/browser-harness.xul
+++ b/testing/mochitest/browser-harness.xul
@@ -303,17 +303,16 @@
     }
 
     function scrollTo(id) {
       var line = document.getElementById(id);
       if (!line)
         return;
 
       var boxObject = document.getElementById("results").parentNode.boxObject;
-      boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject);
       boxObject.scrollToElement(line);
     }
   ]]></script>
   <button id="runTestsButton" oncommand="runTests();" label="Run All Tests"/>
   <label id="status"/>
   <scrollbox flex="1" style="overflow: auto" align="stretch">
     <div id="results" xmlns="http://www.w3.org/1999/xhtml" flex="1"/>
   </scrollbox>
--- a/toolkit/components/filepicker/content/filepicker.js
+++ b/toolkit/components/filepicker/content/filepicker.js
@@ -3,17 +3,16 @@
 /* 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/. */
 
 const nsIFilePicker       = Components.interfaces.nsIFilePicker;
 const nsIProperties       = Components.interfaces.nsIProperties;
 const NS_DIRECTORYSERVICE_CONTRACTID = "@mozilla.org/file/directory_service;1";
 const NS_IOSERVICE_CONTRACTID = "@mozilla.org/network/io-service;1";
-const nsITreeBoxObject = Components.interfaces.nsITreeBoxObject;
 const nsIFileView = Components.interfaces.nsIFileView;
 const NS_FILEVIEW_CONTRACTID = "@mozilla.org/filepicker/fileview;1";
 const nsITreeView = Components.interfaces.nsITreeView;
 const nsILocalFile = Components.interfaces.nsILocalFile;
 const nsIFile = Components.interfaces.nsIFile;
 const NS_LOCAL_FILE_CONTRACTID = "@mozilla.org/file/local;1";
 const NS_PROMPTSERVICE_CONTRACTID = "@mozilla.org/embedcomp/prompt-service;1";
 
@@ -120,17 +119,17 @@ function filepickerLoad() {
 
   // setup the dialogOverlay.xul button handlers
   retvals.buttonStatus = nsIFilePicker.returnCancel;
 
   var tree = document.getElementById("directoryTree");
   if (filePickerMode == nsIFilePicker.modeOpenMultiple)
     tree.removeAttribute("seltype");
 
-  tree.treeBoxObject.view = treeView;
+  tree.view = treeView;
 
   // Start out with the ok button disabled since nothing will be
   // selected and nothing will be in the text field.
   okButton.disabled = filePickerMode != nsIFilePicker.modeGetFolder;
 
   // This allows the window to show onscreen before we begin
   // loading the file list
 
--- a/toolkit/components/passwordmgr/content/passwordManager.js
+++ b/toolkit/components/passwordmgr/content/passwordManager.js
@@ -93,17 +93,17 @@ function LoadSignons() {
     signons = passwordmanager.getAllLogins();
   } catch (e) {
     signons = [];
   }
   signons.forEach(login => login.QueryInterface(Components.interfaces.nsILoginMetaInfo));
   signonsTreeView.rowCount = signons.length;
 
   // sort and display the table
-  signonsTree.treeBoxObject.view = signonsTreeView;
+  signonsTree.view = signonsTreeView;
   // The sort column didn't change. SortTree (called by
   // SignonColumnSort) assumes we want to toggle the sort
   // direction but here we don't so we have to trick it
   lastSignonSortAscending = !lastSignonSortAscending;
   SignonColumnSort(lastSignonSortColumn);
 
   // disable "remove all signons" button if there are no signons
   var element = document.getElementById("removeAllSignons");
--- a/toolkit/components/passwordmgr/content/passwordManagerExceptions.js
+++ b/toolkit/components/passwordmgr/content/passwordManagerExceptions.js
@@ -43,17 +43,17 @@ function Reject(number, host) {
 }
 
 function LoadRejects() {
   var hosts = passwordmanager.getAllDisabledHosts();
   rejects = hosts.map(function(host, i) { return new Reject(i, host); });
   rejectsTreeView.rowCount = rejects.length;
 
   // sort and display the table
-  rejectsTree.treeBoxObject.view = rejectsTreeView;
+  rejectsTree.view = rejectsTreeView;
   RejectColumnSort(lastRejectSortColumn);
 
   var element = document.getElementById("removeAllRejects");
   if (rejects.length == 0) {
     element.setAttribute("disabled","true");
   } else {
     element.removeAttribute("disabled");
   }
--- a/toolkit/components/passwordmgr/test/browser/browser_passwordmgrdlg.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_passwordmgrdlg.js
@@ -44,17 +44,17 @@ function test() {
     SimpleTest.waitForFocus(doTest, pwmgrdlg);
 
     // the meat of the test
     function doTest() {
         let doc = pwmgrdlg.document;
         let win = doc.defaultView;
         let filter = doc.getElementById("filter");
         let tree = doc.getElementById("signonsTree");
-        let view = tree.treeBoxObject.view;
+        let view = tree.view;
 
         is(filter.value, "", "Filter box should initially be empty");
         is(view.rowCount, 10, "There should be 10 passwords initially");
 
         // Prepare a set of tests
         //   filter: the text entered in the filter search box
         //   count: the number of logins which should match the respective filter
         //   count2: the number of logins which should match the respective filter
--- a/toolkit/content/tests/chrome/popup_trigger.js
+++ b/toolkit/content/tests/chrome/popup_trigger.js
@@ -24,17 +24,17 @@ function runTests()
 {
   if (screen.height < 768) {
     ok(false, "popup tests are likely to fail for screen heights less than 768 pixels");
   }
 
   gMenuPopup = document.getElementById("thepopup");
   gTrigger = document.getElementById("trigger");
 
-  gIsMenu = gTrigger.boxObject instanceof Components.interfaces.nsIMenuBoxObject;
+  gIsMenu = gTrigger.boxObject instanceof MenuBoxObject;
 
   // a hacky way to get the screen position of the document. Cache the event
   // so that we can use it in calls to openPopup.
   gCachedEvent = cacheEvent({ shiftKey: true });
   gScreenX = gCachedEvent.screenX;
   gScreenY = gCachedEvent.screenY;
   gCachedEvent2 = cacheEvent({ altKey: true, ctrlKey: true, shiftKey: true, metaKey: true });
 
--- a/toolkit/content/tests/chrome/test_contextmenu_list.xul
+++ b/toolkit/content/tests/chrome/test_contextmenu_list.xul
@@ -101,17 +101,17 @@ function startTest()
 function menuTests()
 {
   gSelectionStep = 0;
   var element = $("menu");
   synthesizeMouse(element, 0, 0, { type : "contextmenu", button: 0 });
   is(gContextMenuFired, true, "context menu fired when menu open");
 
   gSelectionStep = 1;
-  $("menu").boxObject.QueryInterface(Components.interfaces.nsIMenuBoxObject).activeChild = $("menu2");
+  $("menu").boxObject.activeChild = $("menu2");
   synthesizeMouse(element, 0, 0, { type : "contextmenu", button: 0 });
 
   $("menu").open = false;
 }
 
 function nextTest()
 {
   gTestId++;
--- a/toolkit/content/tests/chrome/test_mousescroll.xul
+++ b/toolkit/content/tests/chrome/test_mousescroll.xul
@@ -138,16 +138,17 @@ function testRichListbox(id, andThen)
   var winUtils = SpecialPowers.getDOMWindowUtils(window);
   winUtils.advanceTimeAndRefresh(100);
 
   function helper()
   {
     var [aStart, aDelta, aIntDelta, aDeltaMode] = tests[0];
     tests.shift();
     listbox.scrollToIndex(aStart);
+
     synthesizeWheel(listbox, 10, 10,
                     { deltaMode: aDeltaMode, deltaY: aDelta,
                       lineOrPageDeltaY: aIntDelta });
 
     winUtils.advanceTimeAndRefresh(100);
 
     var change = listbox.getIndexOfFirstVisibleRow() - aStart;
     var direction = (change > 0) - (change < 0);
@@ -195,59 +196,59 @@ function testRichListbox(id, andThen)
 function testArrowScrollbox(id)
 {
   var scrollbox = document.getElementById(id);
   var scrollBoxObject = scrollbox.scrollBoxObject;
   var orient = scrollbox.getAttribute("orient");
 
   function helper(aStart, aDelta, aIntDelta, aDeltaMode, aExpected)
   {
-    var xpos = {};
-    var ypos = {};
     var orientIsHorizontal = (orient == "horizontal");
-    var pos = orientIsHorizontal ? xpos : ypos;
 
     scrollBoxObject.scrollTo(aStart, aStart);
 
     for (var i = orientIsHorizontal ? 2 : 0; i >= 0; i--) {
       synthesizeWheel(scrollbox, 5, 5,
                       { deltaMode: aDeltaMode, deltaY: aDelta,
                         lineOrPageDeltaY: aIntDelta });
-      scrollBoxObject.getPosition(xpos, ypos);
+
+      var pos = orientIsHorizontal ? scrollBoxObject.positionX :
+                                     scrollBoxObject.positionY;
+
       // Note, vertical mouse scrolling is allowed to scroll horizontal
       // arrowscrollboxes, because many users have no horizontal mouse scroll
       // capability
       let expected = !i ? aExpected : aStart;
-      is(pos.value, expected,
+      is(pos, expected,
          "testArrowScrollbox(" + id +  "): vertical, starting " + aStart +
            " delta " + aDelta + " lineOrPageDelta " + aIntDelta +
            " aDeltaMode " + aDeltaMode);
     }
 
     scrollBoxObject.scrollTo(aStart, aStart);
     for (var i = orientIsHorizontal ? 2 : 0; i >= 0; i--) {
       synthesizeWheel(scrollbox, 5, 5,
                       { deltaMode: aDeltaMode, deltaX: aDelta,
                         lineOrPageDeltaX: aIntDelta });
       // horizontal mouse scrolling is never allowed to scroll vertical
       // arrowscrollboxes
-      scrollBoxObject.getPosition(xpos, ypos);
+      var pos = orientIsHorizontal ? scrollBoxObject.positionX :
+                                     scrollBoxObject.positionY;
       let expected = (!i && orientIsHorizontal) ? aExpected : aStart;
-      is(pos.value, expected,
+      is(pos, expected,
          "testArrowScrollbox(" + id +  "): horizontal, starting " + aStart +
            " delta " + aDelta + " lineOrPageDelta " + aIntDelta +
            " aDeltaMode " + aDeltaMode);
     }
   }
 
-  var scrolledWidth = {};
-  var scrolledHeight = {};
-  scrollBoxObject.getScrolledSize(scrolledWidth, scrolledHeight);
-  var scrollMaxX = scrolledWidth.value - scrollBoxObject.width;
-  var scrollMaxY = scrolledHeight.value - scrollBoxObject.height;
+  var scrolledWidth = scrollBoxObject.scrolledWidth;
+  var scrolledHeight = scrollBoxObject.scrolledHeight;
+  var scrollMaxX = scrolledWidth - scrollBoxObject.width;
+  var scrollMaxY = scrolledHeight - scrollBoxObject.height;
   var scrollMax = orient == "horizontal" ? scrollMaxX : scrollMaxY;
 
   deltaModes.forEach(function(aDeltaMode) {
     // These lineOrPageDelta values are not realistic.  However, it's enough to
     // test if it's scrolled by the lineOrPageDelta value.
     let delta = (aDeltaMode == WheelEvent.DOM_DELTA_PIXEL) ? 5.0 : 0.3;
     helper(50, -delta, -100, aDeltaMode, 0);
     helper(50,  delta,  100, aDeltaMode, scrollMax);
--- a/toolkit/content/tests/chrome/test_popup_tree.xul
+++ b/toolkit/content/tests/chrome/test_popup_tree.xul
@@ -44,21 +44,20 @@ function runTests()
 
 function treeClick()
 {
   var tree = $("tree");
   is(tree.currentIndex, -1, "selectedIndex before click");
   synthesizeMouseExpectEvent($("treechildren"), 2, 2, { }, $("treechildren"), "click", "");
   is(tree.currentIndex, 0, "selectedIndex after click");
 
-  var x = { }, y = { }, width = { }, height = { };
-  tree.treeBoxObject.getCoordsForCellItem(1, tree.columns.address, "", x, y, width, height);
-  synthesizeMouseExpectEvent($("treechildren"), x.value, y.value + 2,
+  var rect = tree.treeBoxObject.getCoordsForCellItem(1, tree.columns.address, "");
+  synthesizeMouseExpectEvent($("treechildren"), rect.x, rect.y + 2,
                              { }, $("treechildren"), "click", "");
-  is(tree.currentIndex, 1, "selectedIndex after second click " + x.value + "," + y.value);
+  is(tree.currentIndex, 1, "selectedIndex after second click " + rect.x + "," + rect.y);
 
   $("panel").hidePopup();
 }
 
 ]]>
 </script>
 
 <body xmlns="http://www.w3.org/1999/xhtml">
--- a/toolkit/content/tests/chrome/test_position.xul
+++ b/toolkit/content/tests/chrome/test_position.xul
@@ -70,24 +70,24 @@ function runTest()
 
   var box2 = $("box2");
   checkPosition("box2", box2, 2, 46, winwidth, 96);
 
   // height is height(box1) = 46 + margin-top(box3) = 1 + margin-top(button1) = 5
   var button1 = $("button1");
   checkPosition("button1", button1, 9, 53, 99, 88);
 
-  var sbo = box2.boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject);
+  var sbo = box2.boxObject;
   sbo.scrollTo(7, 16);
 
   // clientRect height is offset from root so is 16 pixels vertically less
   checkPosition("button1 scrolled", button1, 9, 37, 99, 72);
 
   var box3 = $("box3");
-  sbo = box3.boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject);
+  sbo = box3.boxObject;
   sbo.scrollTo(1, 2);
 
   checkPosition("button1 scrolled", button1, 9, 35, 99, 70);
 
   $("menu").open = true;
 }
 
 function menuOpened()
--- a/toolkit/content/tests/chrome/window_largemenu.xul
+++ b/toolkit/content/tests/chrome/window_largemenu.xul
@@ -140,19 +140,17 @@ function popupShown()
     // down when we pass the fractional value to openPopupAtScreen above.
     is(Math.round(rect.top) + gScreenY, Math.floor(screen.height / 2),
                               gTests[gTestIndex] + " top");
     ok(Math.round(rect.bottom) + gScreenY < screen.height,
                                 gTests[gTestIndex] + " bottom");
     ok(!gOverflowed && gUnderflowed, gTests[gTestIndex] + " overflow")
   }
 
-  var sx = { }, sy = { };
-  sbo.getPosition(sx, sy);
-  is(sy.value, expectedScrollPos, "menu scroll position");
+  is(sbo.positionY, expectedScrollPos, "menu scroll position");
 
   hidePopup();
 }
 
 function is(l, r, n) { window.opener.wrappedJSObject.SimpleTest.is(l,r,n); }
 function ok(v, n) { window.opener.wrappedJSObject.SimpleTest.ok(v,n); }
 
 var oldx, oldy, waitSteps = 0;
--- a/toolkit/content/tests/fennec-tile-testapp/chrome/content/FooScript.js
+++ b/toolkit/content/tests/fennec-tile-testapp/chrome/content/FooScript.js
@@ -53,19 +53,17 @@ BrowserView.prototype = {
   //   _viewportRect
   //   _viewportInnerBoundsRect
   //
 
   get tileManager() { return this._tileManager; },
   get scrollbox() { return this._scrollbox; },
 
   init: function init() {
-    let scrollbox = document.getElementById("scrollbox")
-			.boxObject
-			.QueryInterface(Components.interfaces.nsIScrollBoxObject);
+    let scrollbox = document.getElementById("scrollbox").boxObject;
     this._scrollbox = scrollbox;
 
     let leftbar  = document.getElementById("left_sidebar");
     let rightbar = document.getElementById("right_sidebar");
     let topbar   = document.getElementById("top_urlbar");
     this._leftbar = leftbar;
     this._rightbar = rightbar;
     this._topbar = topbar;
@@ -123,20 +121,17 @@ BrowserView.prototype = {
     // way this function is used
     rect.x = (clip) ? Math.max(x, 0) : x;
     rect.y = (clip) ? Math.max(y, 0) : y;
 
     return rect;
   },
 
   getScrollboxPosition: function getScrollboxPosition() {
-    let x = {};
-    let y = {};
-    this._scrollbox.getPosition(x, y);
-    return [x.value, y.value];
+    return [this._scrollbox.positionX, this._scrollbox.positionY];
   },
 
   getViewportInnerBoundsRect: function getViewportInnerBoundsRect(dx, dy) {
     if (!dx) dx = 0;
     if (!dy) dy = 0;
 
     let w = window.innerWidth;
     let h = window.innerHeight;
@@ -308,36 +303,34 @@ function onMouseUp() {
 
   bv.tileManager.endPanning();
 }
 
 function onMouseMove(e) {
   if (window._isDragging) {
     let scrollbox = bv.scrollbox;
 
-    let x = {};
-    let y = {};
-    let w = {};
-    let h = {};
-    scrollbox.getPosition(x, y);
-    scrollbox.getScrolledSize(w, h);
+    let x = scrollbox.positionX;
+    let y = scrollbox.positionY;
+    let w = scrollbox.scrolledWidth;
+    let h = scrollbox.scrolledHeight;
 
     let dx = window._dragStart.x - e.clientX;
     let dy = window._dragStart.y - e.clientY;
 
     // XXX if max(x, 0) > scrollwidth we shouldn't do anything (same for y/height)
-    let newX = Math.max(x.value + dx, 0);
-    let newY = Math.max(y.value + dy, 0);
+    let newX = Math.max(x + dx, 0);
+    let newY = Math.max(y + dy, 0);
 
-    if (newX < w.value || newY < h.value) {
+    if (newX < w || newY < h) {
       // clip dx and dy to prevent us from going below 0
-      dx = Math.max(dx, -x.value);
-      dy = Math.max(dy, -y.value);
+      dx = Math.max(dx, -x);
+      dy = Math.max(dy, -y);
 
-      bv.onBeforeScroll(x.value, y.value, dx, dy);
+      bv.onBeforeScroll(x, y, dx, dy);
 
       /*dump("==========scroll==========" + endl);
       dump("delta: " + dx + "," + dy + endl);
       let xx = {};
       let yy = {};
       scrollbox.getPosition(xx, yy);
       dump(xx.value + "," + yy.value + endl);*/
 
--- a/toolkit/content/tests/fennec-tile-testapp/chrome/content/foo.xul
+++ b/toolkit/content/tests/fennec-tile-testapp/chrome/content/foo.xul
@@ -18,22 +18,20 @@
 // environment.  What could possibly go wrong? ...
 let bv        = null;
 let scrollbox = null;
 let leftbar   = null;
 let rightbar  = null;
 let topbar    = null;
 
 function debug() {
-  let w = {};
-  let h = {};
-  scrollbox.getScrolledSize(w, h);
+  let w = scrollbox.scrolledWidth;
+  let h = scrollbox.scrolledHeight;
   let container = document.getElementById("tile_container");
   let [x, y] = getScrollboxPosition();
-  let [w, h] = [w.value, h.value];
   if (bv) {
     dump('----------------------DEBUG!-------------------------\n');
     dump(bv._browserViewportState.toString() + endl);
 
     dump(endl);
 
     let cr = bv._tileManager._criticalRect;
     dump('criticalRect from BV: ' + (cr ? cr.toString() : null) + endl);
@@ -180,37 +178,35 @@ function onMouseDown(e) {
 
 function onMouseUp() {
   window._isDragging = false;
   bv.resumeRendering();
 }
 
 function onMouseMove(e) {
   if (window._isDragging) {
-    let x = {};
-    let y = {};
-    let w = {};
-    let h = {};
-    scrollbox.getPosition(x, y);
-    scrollbox.getScrolledSize(w, h);
+    let x = scrollbox.positionX;
+    let y = scrollbox.positionY;
+    let w = scrollbox.scrolledWidth;
+    let h = scrollbox.scrolledHeight;
 
     let dx = window._dragStart.x - e.clientX;
     let dy = window._dragStart.y - e.clientY;
 
     // XXX if max(x, 0) > scrollwidth we shouldn't do anything (same for y/height)
-    let newX = Math.max(x.value + dx, 0);
-    let newY = Math.max(y.value + dy, 0);
+    let newX = Math.max(x + dx, 0);
+    let newY = Math.max(y + dy, 0);
 
-    if (newX < w.value || newY < h.value) {
+    if (newX < w || newY < h) {
       // clip dx and dy to prevent us from going below 0
-      dx = Math.max(dx, -x.value);
-      dy = Math.max(dy, -y.value);
+      dx = Math.max(dx, -x);
+      dy = Math.max(dy, -y);
 
-      let oldx = x.value;
-      let oldy = y.value;
+      let oldx = x;
+      let oldy = y;
 
       bv.onBeforeVisibleMove(dx, dy);
 
       updateBars(oldx, oldy, dx, dy);
       scrollbox.scrollBy(dx, dy);
       
       let [newx, newy] = getScrollboxPosition();
       let realdx = newx - oldx;
@@ -226,19 +222,17 @@ function onMouseMove(e) {
 function onAlmostLoad() {
   window._isDragging = false;
   window.infoMode = false;
   window.setTimeout(onLoad, 1500);
 }
 
 function onLoad() {
   // ----------------------------------------------------
-  scrollbox = document.getElementById("scrollbox")
-		.boxObject
-		.QueryInterface(Components.interfaces.nsIScrollBoxObject);
+  scrollbox = document.getElementById("scrollbox").boxObject;
   leftbar  = document.getElementById("left_sidebar");
   rightbar = document.getElementById("right_sidebar");
   topbar   = document.getElementById("top_urlbar");
   // ----------------------------------------------------
 
   let initX = Math.round(leftbar.getBoundingClientRect().right);
   dump('scrolling to ' + initX + endl);
   scrollbox.scrollTo(initX, 0);
@@ -306,20 +300,17 @@ function scrollboxToViewportRect(rect) {
   let ytrans = -topbarcr.height;
 
   rect.translate(xtrans, ytrans);
 
   return rect;
 }
 
 function getScrollboxPosition() {
-  let x = {};
-  let y = {};
-  scrollbox.getPosition(x, y);
-  return [x.value, y.value];
+  return [scrollbox.positionX, scrollbox.positionY];
 }
 
 function getContentScrollValues(browser) {
   let cwu = getBrowserDOMWindowUtils(browser);
   let scrollX = {};
   let scrollY = {};
   cwu.getScrollXY(false, scrollX, scrollY);
 
--- a/toolkit/content/tests/widgets/popup_shared.js
+++ b/toolkit/content/tests/widgets/popup_shared.js
@@ -257,31 +257,31 @@ function goNextStepSync()
 
 function openMenu(menu)
 {
   if ("open" in menu) {
     menu.open = true;
   }
   else {
     var bo = menu.boxObject;
-    if (bo instanceof SpecialPowers.Ci.nsIMenuBoxObject)
+    if (bo instanceof MenuBoxObject)
       bo.openMenu(true);
     else
       synthesizeMouse(menu, 4, 4, { });
   }
 }
 
 function closeMenu(menu, popup)
 {
   if ("open" in menu) {
     menu.open = false;
   }
   else {
     var bo = menu.boxObject;
-    if (bo instanceof SpecialPowers.Ci.nsIMenuBoxObject)
+    if (bo instanceof MenuBoxObject)
       bo.openMenu(false);
     else
       popup.hidePopup();
   }
 }
 
 function checkActive(popup, id, testname)
 {
@@ -298,26 +298,26 @@ function checkActive(popup, id, testname
   ok(activeok, testname + " item " + (id ? id : "none") + " active");
 }
 
 function checkOpen(menuid, testname)
 {
   var menu = document.getElementById(menuid);
   if ("open" in menu)
     ok(menu.open, testname + " " + menuid + " menu is open");
-  else if (menu.boxObject instanceof SpecialPowers.Ci.nsIMenuBoxObject)
+  else if (menu.boxObject instanceof MenuBoxObject)
     ok(menu.getAttribute("open") == "true", testname + " " + menuid + " menu is open");
 }
 
 function checkClosed(menuid, testname)
 {
   var menu = document.getElementById(menuid);
   if ("open" in menu)
     ok(!menu.open, testname + " " + menuid + " menu is open");
-  else if (menu.boxObject instanceof SpecialPowers.Ci.nsIMenuBoxObject)
+  else if (menu.boxObject instanceof MenuBoxObject)
     ok(!menu.hasAttribute("open"), testname + " " + menuid + " menu is closed");
 }
 
 function convertPosition(anchor, align)
 {
   if (anchor == "topleft" && align == "topleft") return "overlap";
   if (anchor == "topleft" && align == "topright") return "start_before";
   if (anchor == "topleft" && align == "bottomleft") return "before_start";
--- a/toolkit/content/tests/widgets/tree_shared.js
+++ b/toolkit/content/tests/widgets/tree_shared.js
@@ -1287,20 +1287,19 @@ function checkColumns(aTree, aReference,
   columns.forEach(function(e) {
     ids.push(e.element.id);
   });
   is(compareArrays(ids, aReference), true, aMessage);
 }
 
 function mouseOnCell(tree, row, column, testname)
 {
-  var x = {}, y = {}, width = {}, height = {};
-  tree.boxObject.getCoordsForCellItem(row, column, "text", x, y, width, height);
+  var rect = tree.boxObject.getCoordsForCellItem(row, column, "text");
 
-  synthesizeMouseExpectEvent(tree.body, x.value, y.value, {}, tree, "select", testname);
+  synthesizeMouseExpectEvent(tree.body, rect.x, rect.y, {}, tree, "select", testname);
 }
 
 function mouseClickOnColumnHeader(aColumns, aColumnIndex, aButton, aClickCount)
 {
   var columnHeader = aColumns[aColumnIndex].element;
   var columnHeaderRect = columnHeader.getBoundingClientRect();
   var columnWidth = columnHeaderRect.right - columnHeaderRect.left;
   // For multiple click we send separate click events, with increasing
@@ -1316,20 +1315,19 @@ function mouseClickOnColumnHeader(aColum
 function mouseDblClickOnCell(tree, row, column, testname)
 {
   // select the row we will edit
   var selection = tree.view.selection;
   selection.select(row);
   tree.treeBoxObject.ensureRowIsVisible(row);
 
   // get cell coordinates
-  var x = {}, y = {}, width = {}, height = {};
-  tree.treeBoxObject.getCoordsForCellItem(row, column, "text", x, y, width, height);
+  var rect = tree.treeBoxObject.getCoordsForCellItem(row, column, "text");
 
-  synthesizeMouse(tree.body, x.value, y.value, { clickCount: 2 }, null);
+  synthesizeMouse(tree.body, rect.x, rect.y, { clickCount: 2 }, null);
 }
 
 function compareArrays(arr1, arr2)
 {
   if (arr1.length != arr2.length)
     return false;
 
   for (var i = 0; i < arr1.length; i++) {
--- a/toolkit/content/widgets/autocomplete.xml
+++ b/toolkit/content/widgets/autocomplete.xml
@@ -790,19 +790,17 @@
         document.getAnonymousElementByAttribute(this, "anonid", "treecols");
       </field>
 
       <property name="view"
                 onget="return this.mView;">
         <setter><![CDATA[
           // We must do this by hand because the tree binding may not be ready yet
           this.mView = val;
-          var bx = this.tree.boxObject;
-          bx = bx.QueryInterface(Components.interfaces.nsITreeBoxObject);
-          bx.view = val;
+          this.tree.boxObject.view = val;
         ]]></setter>
       </property>
 
     </implementation>
   </binding>
 
   <binding id="autocomplete-base-popup" role="none"
 extends="chrome://global/content/bindings/popup.xml#popup">
--- a/toolkit/content/widgets/button.xml
+++ b/toolkit/content/widgets/button.xml
@@ -20,18 +20,17 @@
                 onset="this.setAttribute('dlgtype', val); return val;"/>
 
       <property name="group"
                 onget="return this.getAttribute('group');"
                 onset="this.setAttribute('group', val); return val;"/>
 
       <property name="open" onget="return this.hasAttribute('open');">
         <setter><![CDATA[
-          if (this.boxObject instanceof
-              Components.interfaces.nsIMenuBoxObject) {
+          if (this.boxObject instanceof MenuBoxObject) {
             this.boxObject.openMenu(val);
           } else {
             // Fall back to just setting the attribute
             if (val) {
               this.setAttribute('open', 'true');
             } else {
               this.removeAttribute('open');
             }
@@ -142,17 +141,17 @@
            because any external oncommand handlers might get called before ours,
            and then they would see the incorrect value of checked. Additionally
            a command attribute would redirect the command events anyway.-->
       <handler event="click" button="0" action="this._handleClick();"/>
       <handler event="keypress" key=" " action="this._handleClick();"/>
 
       <handler event="keypress">
       <![CDATA[
-        if (this.boxObject instanceof Components.interfaces.nsIMenuBoxObject) {
+        if (this.boxObject instanceof MenuBoxObject) {
           if (this.open)
             return;
         } else {
           if (event.keyCode == KeyEvent.DOM_VK_UP ||
               (event.keyCode == KeyEvent.DOM_VK_LEFT &&
                 document.defaultView.getComputedStyle(this.parentNode, "")
                         .direction == "ltr") ||
               (event.keyCode == KeyEvent.DOM_VK_RIGHT &&
--- a/toolkit/content/widgets/datetimepicker.xml
+++ b/toolkit/content/widgets/datetimepicker.xml
@@ -1253,17 +1253,17 @@
         var grid = document.getAnonymousElementByAttribute(this, "anonid", "grid");
         this.attachedControl = grid;
         grid.attachedControl = this;
         grid._setValueNoSync(this._dateValue);
       </constructor>
       <property name="open" onget="return this.hasAttribute('open');">
         <setter>
           <![CDATA[
-            if (this.boxObject instanceof Components.interfaces.nsIMenuBoxObject)
+            if (this.boxObject instanceof MenuBoxObject)
               this.boxObject.openMenu(val);
             return val;
           ]]>
         </setter>
       </property>
       <property name="displayedMonth">
         <getter>
           return document.getAnonymousElementByAttribute(this, "anonid", "grid").displayedMonth;
--- a/toolkit/content/widgets/editor.xml
+++ b/toolkit/content/widgets/editor.xml
@@ -130,17 +130,17 @@
                 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"
-                onget="return this.boxObject.QueryInterface(Components.interfaces.nsIContainerBoxObject).docShell;"
+                onget="return this.boxObject.docShell;"
                 readonly="true"/>
       <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="webBrowserFind"
@@ -163,9 +163,8 @@
                 onset="this.markupDocumentViewer.textZoom = val;"/>
       <property name="isSyntheticDocument"
                 onget="return this.contentDocument.isSyntheticDocument;"
                 readonly="true"/>
     </implementation>
   </binding>
 
 </bindings>
-
--- a/toolkit/content/widgets/general.xml
+++ b/toolkit/content/widgets/general.xml
@@ -82,17 +82,17 @@
       ]]></destructor>
     </implementation>
   </binding>
 
   <binding id="iframe" role="outerdoc">
     <implementation>
       <property name="docShell"
                 readonly="true"
-                onget="return this.boxObject.QueryInterface(Components.interfaces.nsIContainerBoxObject).docShell"/>
+                onget="return this.boxObject.docShell"/>
       <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;"/>
--- a/toolkit/content/widgets/listbox.xml
+++ b/toolkit/content/widgets/listbox.xml
@@ -672,17 +672,17 @@
       </xul:listrows>
     </content>
 
     <implementation>
 
       <!-- ///////////////// public listbox members ///////////////// -->
 
       <property name="listBoxObject"
-                onget="return this.boxObject.QueryInterface(Components.interfaces.nsIListBoxObject);"
+                onget="return this.boxObject;"
                 readonly="true"/>
 
       <!-- ///////////////// private listbox members ///////////////// -->
 
       <method name="_fireOnSelect">
         <body>
         <![CDATA[
           if (!this._suppressOnSelect && !this.suppressOnSelect) {
@@ -1137,9 +1137,8 @@
     <content>
       <xul:image class="listheader-icon"/>
       <xul:label class="listheader-label" xbl:inherits="value=label,crop" flex="1" crop="right"/>
       <xul:image class="listheader-sortdirection" xbl:inherits="sortDirection"/>
     </content>
   </binding>
 
 </bindings>
-
--- a/toolkit/content/widgets/menu.xml
+++ b/toolkit/content/widgets/menu.xml
@@ -44,26 +44,24 @@
   </binding>
 
   <binding id="menu-base"
            extends="chrome://global/content/bindings/menu.xml#menuitem-base">
 
     <implementation implements="nsIDOMXULContainerElement">
       <property name="open" onget="return this.hasAttribute('open');">
         <setter><![CDATA[
-          this.boxObject.QueryInterface(Components.interfaces.nsIMenuBoxObject)
-              .openMenu(val);
+          this.boxObject.openMenu(val);
           return val;
         ]]></setter>
       </property>
 
       <property name="openedWithKey" readonly="true">
         <getter><![CDATA[
-          return this.boxObject.QueryInterface(Components.interfaces.nsIMenuBoxObject)
-              .openedWithKey;
+          return this.boxObject.openedWithKey;
         ]]></getter>
       </property>
 
       <!-- nsIDOMXULContainerElement interface -->
       <method name="appendItem">
         <parameter name="aLabel"/>
         <parameter name="aValue"/>
         <body>
--- a/toolkit/content/widgets/menulist.xml
+++ b/toolkit/content/widgets/menulist.xml
@@ -65,17 +65,17 @@
         ]]>
       </handler>
     </handlers>
 
     <implementation implements="nsIDOMXULMenuListElement, nsIDOMEventListener">
       <constructor>
         this.mInputField = null;
         this.mSelectedInternal = null;
-        this.menuBoxObject = this.boxObject.QueryInterface(Components.interfaces.nsIMenuBoxObject);
+        this.menuBoxObject = this.boxObject;
         this.setInitialSelection();
       </constructor>
 
       <method name="setInitialSelection">
         <body>
           <![CDATA[
             var popup = this.menupopup;
             if (popup) {
--- a/toolkit/content/widgets/popup.xml
+++ b/toolkit/content/widgets/popup.xml
@@ -16,17 +16,17 @@
 
     <implementation implements="nsIDOMXULPopupElement">
       <property name="label" onget="return this.getAttribute('label');"
                              onset="this.setAttribute('label', val); return val;"/>
       <property name="position" onget="return this.getAttribute('position');"
                                 onset="this.setAttribute('position', val); return val;"/>
       <property name="popupBoxObject">
         <getter>
-          return this.boxObject.QueryInterface(Components.interfaces.nsIPopupBoxObject);
+          return this.boxObject;
         </getter>
       </property>
 
       <property name="state" readonly="true"
                 onget="return this.popupBoxObject.popupState"/>
 
       <property name="triggerNode" readonly="true"
                 onget="return this.popupBoxObject.triggerNode"/>
@@ -82,39 +82,39 @@
           var popupBox = null;
           var menuBox = null;
           try {
             popupBox = this.popupBoxObject;
           } catch(e) {}
           try {
             menuBox = this.parentNode.boxObject;
           } catch(e) {}
-          if (menuBox instanceof Components.interfaces.nsIMenuBoxObject)
+          if (menuBox instanceof MenuBoxObject)
             menuBox.openMenu(true);
           else if (popupBox)
             popupBox.showPopup(element, this, xpos, ypos, popuptype, anchoralignment, popupalignment);
         ]]>
         </body>
       </method>
       
       <method name="hidePopup">
         <parameter name="cancel"/>
         <body>
         <![CDATA[
           var popupBox = null;
           var menuBox = null;
           try {
-            popupBox = this.boxObject.QueryInterface(Components.interfaces.nsIPopupBoxObject);
+            popupBox = this.popupBoxObject;
           } catch(e) {}
           try {
             menuBox = this.parentNode.boxObject;
           } catch(e) {}
-          if (menuBox instanceof Components.interfaces.nsIMenuBoxObject)
+          if (menuBox instanceof MenuBoxObject)
             menuBox.openMenu(false);
-          else if (popupBox)
+          else if (popupBox instanceof PopupBoxObject)
             popupBox.hidePopup(cancel);
         ]]>
         </body>
       </method>
 
       <property name="autoPosition">
         <getter>
         <![CDATA[
--- a/toolkit/content/widgets/richlistbox.xml
+++ b/toolkit/content/widgets/richlistbox.xml
@@ -23,17 +23,17 @@
       </xul:scrollbox>
     </content>
 
     <implementation>
       <field name="_scrollbox">
         document.getAnonymousElementByAttribute(this, "anonid", "main-box");
       </field>
       <field name="scrollBoxObject">
-        this._scrollbox.boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject);
+        this._scrollbox.boxObject;
       </field>
       <constructor>
         <![CDATA[
           // add a template build listener
           if (this.builder)
             this.builder.addListener(this._builderListener);
           else
             this._refreshSelection();
@@ -429,23 +429,21 @@
 
       <method name="_isItemVisible">
         <parameter name="aItem"/>
         <body>
           <![CDATA[
             if (!aItem)
               return false;
 
-            var y = {};
-            this.scrollBoxObject.getPosition({}, y);
-            y.value += this.scrollBoxObject.y;
+            var y = this.scrollBoxObject.positionY + this.scrollBoxObject.y;
 
             // Partially visible items are also considered visible
-            return (aItem.boxObject.y + aItem.boxObject.height > y.value) &&
-                   (aItem.boxObject.y < y.value + this.scrollBoxObject.height);
+            return (aItem.boxObject.y + aItem.boxObject.height > y) &&
+                   (aItem.boxObject.y < y + this.scrollBoxObject.height);
           ]]>
         </body>
       </method>
 
       <field name="_currentIndex">null</field>
 
       <!-- For backwards-compatibility and for convenience.
         Use getIndexOfItem instead. -->
@@ -580,9 +578,8 @@
               this.removeAttribute("searchlabel");
             return val;
           ]]>
         </setter>
       </property>
     </implementation>
   </binding>
 </bindings>
-
--- a/toolkit/content/widgets/scrollbox.xml
+++ b/toolkit/content/widgets/scrollbox.xml
@@ -115,19 +115,17 @@
           return val;
         ]]></setter>
       </property>
 
       <field name="_scrollBoxObject">null</field>
       <property name="scrollBoxObject" readonly="true">
         <getter><![CDATA[
           if (!this._scrollBoxObject) {
-            this._scrollBoxObject =
-              this._scrollbox.boxObject
-                             .QueryInterface(Components.interfaces.nsIScrollBoxObject);
+            this._scrollBoxObject = this._scrollbox.boxObject;
           }
           return this._scrollBoxObject;
         ]]></getter>
       </property>
 
       <property name="scrollClientRect" readonly="true">
         <getter><![CDATA[
           return this._scrollbox.getBoundingClientRect();
--- a/toolkit/content/widgets/tree.xml
+++ b/toolkit/content/widgets/tree.xml
@@ -51,17 +51,19 @@
     <implementation implements="nsIDOMXULTreeElement, nsIDOMXULMultiSelectControlElement">
 
       <!-- ///////////////// nsIDOMXULTreeElement ///////////////// -->
 
       <property name="columns"
                 onget="return this.treeBoxObject.columns;"/>
 
       <property name="view"
-                onget="return this.treeBoxObject.view;"
+                onget="return this.treeBoxObject.view ?
+                       this.treeBoxObject.view.QueryInterface(Components.interfaces.nsITreeView) :
+                       null;"
                 onset="return this.treeBoxObject.view = val;"/>
 
       <property name="body"
                 onget="return this.treeBoxObject.treeBody;"/>
 
       <property name="editable"
                 onget="return this.getAttribute('editable') == 'true';"
                 onset="if (val) this.setAttribute('editable', 'true');
@@ -75,17 +77,17 @@
                 onget="return this.getAttribute('seltype')"
                 onset="this.setAttribute('seltype', val); return val;"/>
 
       <property name="currentIndex"
                 onget="return this.view ? this.view.selection.currentIndex: - 1;"
                 onset="if (this.view) return this.view.selection.currentIndex = val; return val;"/>
 
       <property name="treeBoxObject"
-                onget="return this.boxObject.QueryInterface(Components.interfaces.nsITreeBoxObject);"
+                onget="return this.boxObject;"
                 readonly="true"/>
 # contentView is obsolete (see bug 202391)
       <property name="contentView"
                 onget="return this.view; /*.QueryInterface(Components.interfaces.nsITreeContentView)*/"
                 readonly="true"/>
 # builderView is obsolete (see bug 202393)
       <property name="builderView"
                 onget="return this.view; /*.QueryInterface(Components.interfaces.nsIXULTreeBuilder)*/"
@@ -237,16 +239,17 @@
         <parameter name="row"/>
         <!-- Optional parameter openState == true or false to set. 
              No openState param == toggle -->
         <parameter name="openState"/>
         <body><![CDATA[
           if (row < 0 || !this.view.isContainer(row)) {
             return false;
           }
+
           if (this.view.isContainerOpen(row) != openState) {
             this.view.toggleOpenState(row);
             if (row == this.currentIndex) {
               // Only fire event when current row is expanded or collapsed
               // because that's all the assistive technology really cares about.
               var event = document.createEvent('Events');
               event.initEvent('OpenStateChange', true, true);
               this.dispatchEvent(event);
@@ -347,46 +350,42 @@
               this.stopEditing();
 
             var input = this.inputField;
 
             var box = this.treeBoxObject;
             box.ensureCellIsVisible(row, column);
 
             // Get the coordinates of the text inside the cell.
-            var textx = {}, texty = {}, textwidth = {}, textheight = {};
-            var coords = box.getCoordsForCellItem(row, column, "text",
-                                                  textx, texty, textwidth, textheight);
+            var textRect = box.getCoordsForCellItem(row, column, "text");
 
             // Get the coordinates of the cell itself.
-            var cellx = {}, cellwidth = {};
-            coords = box.getCoordsForCellItem(row, column, "cell",
-                                              cellx, {}, c