Merge m-c to inbound.
authorMs2ger <ms2ger@gmail.com>
Fri, 02 Aug 2013 11:07:57 +0200
changeset 141440 ee108221c037013f93cf1568aed42419b083e61e
parent 141439 76a944fa6b251610d36d5c3465f1ee39326e9d8c (current diff)
parent 141414 7d582e8caa9676ae028ede34dcdf71184caa8543 (diff)
child 141441 9435e3497e306726f3b527c3b7fe5e1e418da50b
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
milestone25.0a1
Merge m-c to inbound.
configure.in
content/base/src/FragmentOrElement.cpp
content/base/src/nsDocument.cpp
content/base/src/nsGenericDOMDataNode.cpp
content/events/src/nsDOMEvent.cpp
content/events/src/nsDOMEventTargetHelper.cpp
dom/apps/src/moz.build
dom/base/nsJSEnvironment.cpp
dom/base/nsWrapperCache.h
dom/indexedDB/IDBIndex.cpp
dom/indexedDB/IDBKeyRange.cpp
dom/indexedDB/IDBWrapperCache.cpp
dom/interfaces/html/nsIDOMHTMLDListElement.idl
dom/interfaces/html/nsIDOMHTMLDataListElement.idl
dom/interfaces/html/nsIDOMHTMLFontElement.idl
dom/interfaces/html/nsIDOMHTMLLegendElement.idl
dom/interfaces/html/nsIDOMHTMLMeterElement.idl
dom/interfaces/html/nsIDOMHTMLModElement.idl
dom/interfaces/html/nsIDOMHTMLOutputElement.idl
dom/interfaces/html/nsIDOMHTMLParamElement.idl
dom/interfaces/html/nsIDOMHTMLProgressElement.idl
dom/interfaces/html/nsIDOMHTMLTableColElement.idl
dom/interfaces/html/nsIDOMHTMLTableRowElement.idl
dom/interfaces/html/nsIDOMHTMLTableSectionElement.idl
dom/interfaces/html/nsIDOMHTMLUnknownElement.idl
layout/style/StyleRule.cpp
layout/style/nsCSSRules.cpp
netwerk/base/src/nsIOThreadPool.cpp
netwerk/base/src/nsIOThreadPool.h
python/mozbuild/mozbuild/test/backend/test_recursivemake.py
security/patches/bug-658222-false-start.patch
widget/cocoa/nsChildView.mm
--- a/CLOBBER
+++ b/CLOBBER
@@ -13,9 +13,9 @@
 #          |               |
 #          O <-- Clobber   O  <-- Clobber
 #
 # Note: The description below will be part of the error message shown to users.
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
-Multiple WebIDL changes requiring a clobber on Windows due to bug 890744
+Removal of XPIDL for bug 893117 requires a clobber to make sure interfaces aren't generated.
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -43,16 +43,18 @@ NotificationController::~NotificationCon
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // NotificationCollector: AddRef/Release and cycle collection
 
 NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(NotificationController)
 NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(NotificationController)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(NotificationController)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(NotificationController)
   if (tmp->mDocument)
     tmp->Shutdown();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(NotificationController)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHangingChildDocuments)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContentInsertions)
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -98,16 +98,18 @@ DocAccessible::~DocAccessible()
 {
   NS_ASSERTION(!mPresShell, "LastRelease was never called!?!");
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(DocAccessible)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DocAccessible, Accessible)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotificationController)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVirtualCursor)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildDocuments)
   tmp->mDependentIDsHash.EnumerateRead(CycleCollectorTraverseDepIDsEntry, &cb);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAccessibleCache)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnchorJumpElm)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/browser/branding/official/configure.sh
+++ b/browser/branding/official/configure.sh
@@ -1,6 +1,5 @@
 # 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/.
 
 MOZ_APP_DISPLAYNAME=Firefox
-MOZ_UA_BUILDID=20100101
--- a/browser/metro/base/content/ContextUI.js
+++ b/browser/metro/base/content/ContextUI.js
@@ -176,17 +176,19 @@ var ContextUI = {
   // Display the tab tray
   displayTabs: function () {
     this._clearDelayedTimeout();
     this._setIsExpanded(true);
   },
 
   // Dismiss the navbar if visible.
   dismissNavbar: function dismissNavbar() {
-    Elements.navbar.dismiss();
+    if (!StartUI.isVisible) {
+      Elements.navbar.dismiss();
+    }
   },
 
   // Dismiss the tabstray if visible.
   dismissTabs: function dimissTabs() {
     this._clearDelayedTimeout();
     this._setIsExpanded(false);
   },
 
--- a/browser/metro/base/content/appbar.js
+++ b/browser/metro/base/content/appbar.js
@@ -143,16 +143,20 @@ var Appbar = {
                                    null, null);
       if (uri.schemeIs('http') || uri.schemeIs('https')) {
         MetroUtils.launchInDesktop(Browser.selectedBrowser.currentURI.spec, "");
       }
     } catch(ex) {
     }
   },
 
+  onAutocompleteCloseButton: function () {
+    Elements.autocomplete.closePopup();
+  },
+
   dispatchContextualAction: function(aActionName){
     let activeTileset = this.activeTileset;
     if (activeTileset && ('isBound' in this.activeTileset)) {
       // fire event on the richgrid, others can listen
       // but we keep coupling loose so grid doesn't need to know about appbar
       let event = document.createEvent("Events");
       event.action = aActionName;
       event.initEvent("context-action", true, true); // is cancelable
--- a/browser/metro/base/content/bindings/appbar.xml
+++ b/browser/metro/base/content/bindings/appbar.xml
@@ -1,14 +1,14 @@
-<?xml version="1.0"?>  
+<?xml version="1.0"?>
 
 <bindings xmlns="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-  <binding id="appbarBinding">  
-    <content> 
+  <binding id="appbarBinding">
+    <content>
       <xul:toolbar anonid="toolbar"><children/></xul:toolbar>
     </content>
 
     <implementation implements="nsIDOMEventListener">
       <field name="sticky">false</field>
       <field name="_toolbar" readonly="true">document.getAnonymousElementByAttribute(this, "anonid", "toolbar");</field>
 
       <property name="isShowing" readonly="true">
@@ -24,23 +24,30 @@
         <body>
           <![CDATA[
             let event = document.createEvent("Events");
             event.initEvent(aName, true, false);
             this.dispatchEvent(event);
           ]]>
         </body>
       </method>
-      
+
       <method name="dismiss">
         <body>
           <![CDATA[
             if (!this.isShowing)
               return;
 
+            let self = this;
+            this.setAttribute("hiding", "true");
+            this.addEventListener("transitionend", function appbar_transitionend() {
+              self.removeEventListener("transitionend", appbar_transitionend, false);
+              self.removeAttribute("hiding");
+            }, false);
+
             this._fire("MozAppbarDismissing");
             this.removeAttribute("visible");
           ]]>
         </body>
       </method>
 
       <method name="show">
         <body>
--- a/browser/metro/base/content/browser-ui.js
+++ b/browser/metro/base/content/browser-ui.js
@@ -40,16 +40,17 @@ let Elements = {};
   ["tabs",               "tabs-container"],
   ["controls",           "browser-controls"],
   ["panelUI",            "panel-container"],
   ["startUI",            "start-container"],
   ["tray",               "tray"],
   ["toolbar",            "toolbar"],
   ["browsers",           "browsers"],
   ["navbar",             "navbar"],
+  ["autocomplete",       "urlbar-autocomplete"],
   ["contextappbar",      "contextappbar"],
   ["findbar",            "findbar"],
   ["contentViewport",    "content-viewport"],
   ["progress",           "progress-control"],
   ["progressContainer",  "progress-container"],
 ].forEach(function (aElementGlobal) {
   let [name, id] = aElementGlobal;
   XPCOMUtils.defineLazyGetter(Elements, name, function() {
@@ -545,23 +546,22 @@ var BrowserUI = {
             break;
           case debugServerPortChanged:
             this.changeDebugPort(Services.prefs.getIntPref(aData));
             break;
         }
         break;
       case "metro_viewstate_changed":
         this._adjustDOMforViewState();
-        let autocomplete = document.getElementById("urlbar-autocomplete");
         if (aData == "snapped") {
           FlyoutPanelsUI.hide();
-          autocomplete.setAttribute("orient", "vertical");
+          Elements.autocomplete.setAttribute("orient", "vertical");
         }
         else {
-          autocomplete.setAttribute("orient", "horizontal");
+          Elements.autocomplete.setAttribute("orient", "horizontal");
         }
 
         break;
     }
   },
 
   /*********************************
    * Internal utils
--- a/browser/metro/base/content/browser.xul
+++ b/browser/metro/base/content/browser.xul
@@ -254,27 +254,24 @@
               observes="cmd_back"></html:div>
 
     <!-- Navigation bar -->
     <appbar id="navbar" mousethrough="never" observes="bcast_windowState">
       <hbox id="progress-container" layer="true">
         <hbox id="progress-control" />
       </hbox>
 
-      <vbox id="toolbar-autocomplete" flex="1">
+      <vbox id="toolbar-overlay" flex="1">
         <!-- Autocomplete -->
         <scrollbox flex="1">
           <hbox id="urlbar-autocomplete" observes="bcast_windowState"/>
         </scrollbox>
 
         <!-- Main toolbar -->
-        <toolbar id="toolbar" flex="1">
-          <observes element="bcast_windowState" attribute="*"/>
-          <observes element="bcast_urlbarState" attribute="*"/>
-
+        <toolbar id="toolbar" flex="1" observes="bcast_windowState">
           <toolbarbutton id="back-button" class="appbar-primary"
                          command="cmd_back"/>
           <toolbarbutton id="forward-button" class="appbar-primary"
                          command="cmd_forward"/>
 
           <hbox id="urlbar" flex="1" observes="bcast_urlbarState">
             <box id="identity-box" align="center" role="button">
               <image id="identity-icon"/>
@@ -291,24 +288,38 @@
             <toolbarbutton id="reload-button" class="urlbar-button"
                            oncommand="CommandUpdater.doCommand(
                                         event.shiftKey ? 'cmd_forceReload'
                                                        : 'cmd_reload');"/>
             <toolbarbutton id="stop-button" class="urlbar-button"
                            command="cmd_stop"/>
           </hbox>
 
-          <toolbarbutton id="download-button" class="appbar-secondary"
-                         oncommand="Appbar.onDownloadButton()"/>
-          <toolbarbutton id="star-button" class="appbar-primary" type="checkbox"
-                         oncommand="Appbar.onStarButton()"/>
-          <toolbarbutton id="pin-button" class="appbar-primary" type="checkbox"
-                         oncommand="Appbar.onPinButton()"/>
-          <toolbarbutton id="menu-button" class="appbar-primary"
-                         oncommand="Appbar.onMenuButton(event)"/>
+          <stack id="toolbar-contextual">
+            <observes element="bcast_windowState" attribute="*"/>
+            <observes element="bcast_urlbarState" attribute="*"/>
+
+            <hbox id="toolbar-context-page" pack="end">
+              <toolbarbutton id="download-button" class="appbar-secondary"
+                             oncommand="Appbar.onDownloadButton()"/>
+              <toolbarbutton id="star-button" class="appbar-primary"
+                             type="checkbox"
+                             oncommand="Appbar.onStarButton()"/>
+              <toolbarbutton id="pin-button" class="appbar-primary"
+                             type="checkbox"
+                             oncommand="Appbar.onPinButton()"/>
+              <toolbarbutton id="menu-button" class="appbar-primary"
+                             oncommand="Appbar.onMenuButton(event)"/>
+            </hbox>
+
+            <hbox id="toolbar-context-autocomplete" pack="end">
+              <toolbarbutton id="close-button" class="appbar-secondary"
+                             oncommand="Appbar.onAutocompleteCloseButton()"/>
+            </hbox>
+          </stack>
         </toolbar>
       </vbox>
     </appbar>
 
     <vbox id="panel-container" class="window-width window-height meta"
           hidden="true" observes="bcast_windowState">
       <hbox id="panel-header">
         <toolbarbutton id="panel-close-button" class="appbar-primary"
@@ -366,20 +377,26 @@
       </deck>
     </vbox>
 
     <!-- Find bar -->
     <appbar id="findbar" class="window-width" pack="start">
       <textbox id="findbar-textbox" type="search"
                oncommand="FindHelperUI.search(this.value)"
                oninput="FindHelperUI.updateCommands(this.value); "/>
-      <button class="previous-button" command="cmd_findPrevious"/>
-      <button class="next-button" command="cmd_findNext"/>
+
+      <toolbarbutton id="findbar-previous-button" class="appbar-secondary"
+                     command="cmd_findPrevious"/>
+      <toolbarbutton id="findbar-next-button" class="appbar-secondary"
+                     command="cmd_findNext"/>
+
       <spacer flex="1"/>
-      <button id="findbar-close" class="close-button" command="cmd_findClose"/>
+
+      <toolbarbutton id="findbar-close-button" class="appbar-secondary"
+                     command="cmd_findClose"/>
     </appbar>
 
     <!-- Context button bar -->
     <appbar id="contextappbar">
       <toolbar id="contextualactions-tray" labelled="true" flex="1">
         <toolbarbutton id="pin-selected-button" class="appbar-secondary"
                        label-uses-set-name="true" hidden="true" fade="true"
                        oncommand="Appbar.dispatchContextualAction('pin')"/>
--- a/browser/metro/base/content/helperui/FindHelperUI.js
+++ b/browser/metro/base/content/helperui/FindHelperUI.js
@@ -111,25 +111,26 @@ var FindHelperUI = {
       return;
 
     // Hide any menus
     ContextUI.dismiss();
 
     // Shutdown selection related ui
     SelectionHelperUI.closeEditSession();
 
-    this.search(this._textbox.value);
-    this._textbox.select();
-    this._textbox.focus();
-    this._open = true;
-
     let findbar = this._container;
     setTimeout(() => {
       Elements.browsers.setAttribute("findbar", true);
       findbar.show();
+
+      this.search(this._textbox.value);
+      this._textbox.select();
+      this._textbox.focus();
+
+      this._open = true;
     }, 0);
 
     // Prevent the view to scroll automatically while searching
     Browser.selectedBrowser.scrollSync = false;
   },
 
   hide: function findHelperHide() {
     if (!this._open)
--- a/browser/metro/base/tests/mochitest/browser_findbar.js
+++ b/browser/metro/base/tests/mochitest/browser_findbar.js
@@ -68,15 +68,15 @@ gTests.push({
     is(Elements.findbar.isShowing, false, "Find bar is hidden by default");
 
     yield showNavBar();
     EventUtils.sendMouseEvent({ type: "click" }, "menu-button");
     EventUtils.sendMouseEvent({ type: "click" }, "context-findinpage");
     yield waitForEvent(Elements.findbar, "transitionend");
     is(Elements.findbar.isShowing, true, "Show find bar with menu item");
 
-    EventUtils.synthesizeMouse(document.getElementById("findbar-close"), 1, 1, {});
+    EventUtils.synthesizeMouse(document.getElementById("findbar-close-button"), 1, 1, {});
     yield waitForEvent(Elements.findbar, "transitionend");
     is(Elements.findbar.isShowing, false, "Hide find bar with close button");
 
     Browser.closeTab(tab);
   }
 });
--- a/browser/metro/theme/browser.css
+++ b/browser/metro/theme/browser.css
@@ -439,20 +439,16 @@ documenttab[selected] .documenttab-selec
 #overlay-plus[mousedrag] {
   transition-property: left, right, transform, background-position,
                        background-color, background-size, border-color,
                        visibility, box-shadow;
 }
 
 /* Navigation bar ========================================================== */
 
-#navbar[startpage] {
-  transform: none;
-}
-
 /* Progress meter ---------------------------------------------------------- */
 
 #progress-container {
   display: block;
   position: absolute;
   top: -@progress_height@;
   height: @progress_height@;
   width: 100%;
@@ -478,20 +474,22 @@ documenttab[selected] .documenttab-selec
 
 #progress-control[fade] {
   opacity: 0;
   transition: width .3s ease-in, .5s opacity ease-in;
 }
 
 /* Toolbar ----------------------------------------------------------------- */
 
-#toolbar-autocomplete {
+#toolbar-overlay {
   background-color: @panel_light_color@;
 }
 
+/* Combined back/forward buttons */
+
 #back-button {
   list-style-image: url(chrome://browser/skin/images/navbar-back.png);
   position: relative;
   z-index: 1;
   transition: opacity @forward_transition_length@ ease-out;
 }
 
 #back-button[disabled] {
@@ -579,16 +577,17 @@ documenttab[selected] .documenttab-selec
 #urlbar-edit > hbox > .textbox-input-box > .textbox-input:invalid {
   /* Hide error glow around the address bar that shows by default
    * when URLs are made invalid by trmming. */
   box-shadow: none !important;
 }
 
 /* Combined stop-reload button */
 .urlbar-button {
+  margin: 0;
   -moz-image-region: rect(0px, 30px, 30px, 0px);
 }
 
 .urlbar-button:hover:not(:active) {
   -moz-image-region: rect(0px, 60px, 30px, 30px);
   background-color: #dedfdf;
 }
 
@@ -668,30 +667,43 @@ documenttab[selected] .documenttab-selec
 
 #urlbar:-moz-any([mode="loading"], [mode="view"]) > #go-button,
 #urlbar:-moz-any([mode="edit"], [mode="loading"]) > #reload-button,
 #urlbar:-moz-any([mode="edit"], [mode="view"]) > #stop-button,
 #toolbar[viewstate="snapped"] > #urlbar ~ toolbarbutton {
   visibility: collapse;
 }
 
-/* Application-Specific */
+/* Contextual toolbar controls */
+
+#toolbar-context-autocomplete,
+#toolbar-context-page {
+  transition-property: opacity, visibility;
+  transition-duration: @forward_transition_length@;
+  transition-timing-function: @metro_animation_easing@;
+}
+
+#toolbar-contextual:not([autocomplete]) #toolbar-context-autocomplete,
+#toolbar-contextual[startpage] #toolbar-context-page,
+#toolbar-contextual[autocomplete] #toolbar-context-page {
+  opacity: 0;
+  visibility: hidden;
+  pointer-events: none;
+}
 
 #download-button {
   -moz-image-region: rect(0px, 40px, 40px, 0px) !important;
 }
-#download-button:hover {
+#download-button:hover:not(:active) {
   -moz-image-region: rect(40px, 40px, 80px, 0px) !important;
 }
 #download-button:active {
   -moz-image-region: rect(80px, 40px, 120px, 0px) !important;
 }
 
-/* Page-Specific */
-
 #pin-button {
   list-style-image: url(chrome://browser/skin/images/navbar-pin.png);
 }
 
 #star-button {
   list-style-image: url(chrome://browser/skin/images/navbar-star.png);
 }
 
@@ -722,16 +734,28 @@ documenttab[selected] .documenttab-selec
     list-style-image: url(chrome://browser/skin/images/navbar-star@1.8x.png);
   }
 
   #menu-button {
     list-style-image: url(chrome://browser/skin/images/navbar-menu@1.8x.png);
   }
 }
 
+#close-button {
+  -moz-image-region: rect(0px, 480px, 40px, 440px);
+}
+
+#close-button:hover:not(:active) {
+  -moz-image-region: rect(40px, 480px, 80px, 440px);
+}
+
+#close-button:active {
+  -moz-image-region: rect(80px, 480px, 120px, 440px);
+}
+
 /* Panel UI ================================================================ */
 
 #panel-container {
   padding: 60px 40px;
 }
 
 #panel-container[viewstate="snapped"] .canSnapTiles .richgrid-item-content {
   -moz-box-orient: horizontal;
@@ -797,106 +821,82 @@ documenttab[selected] .documenttab-selec
   white-space: pre-wrap;
 }
 
 /* Find bar ================================================================ */
 
 #findbar {
   background-color: @metro_orange@;
   padding: 0;
-  pointer-events: none;
 }
 
 #findbar > toolbar {
   min-height: @findbar_height@ !important;
 }
 
-#findbar > .previous-button,
-#findbar > .next-button,
-#findbar > .close-button {
-  list-style-image: url(chrome://browser/skin/images/appbar-icons.png);
-  min-width: @touch_button_small@ !important; /* button size */
-  min-height: @touch_button_small@ !important; /* button size */
-  border: none !important;
-  background-image: none !important;
-  background-color: inherit !important;
-  pointer-events: auto;
-  -moz-user-focus: ignore !important;
-  margin: 0 @margin_normal@ !important;
-}
-
-#findbar > .close-button {
-  -moz-margin-start: 0;
-  -moz-image-region: rect(0px, 480px, 40px, 440px);
-}
-
-#findbar > .close-button:hover {
-  -moz-image-region: rect(40px, 480px, 80px, 440px);
-}
-
-#findbar > .close-button:active {
-  -moz-image-region: rect(80px, 480px, 120px, 440px);
-}
-
-#findbar > .previous-button {
-  -moz-margin-end: 0;
-  -moz-image-region: rect(0px, 400px, 40px, 360px);
-}
-
-#findbar > .previous-button:hover {
-  -moz-image-region: rect(40px, 400px, 80px, 360px);
-}
-
-#findbar > .previous-button:active{
-  -moz-image-region: rect(80px, 400px, 120px, 360px);
-}
-
-#findbar > .next-button {
-  -moz-margin-start: 0;
-  -moz-image-region: rect(0px, 440px, 40px, 400px);
-}
-
-#findbar > .next-button:hover {
-  -moz-image-region: rect(40px, 440px, 80px, 400px);
-}
-
-#findbar > .next-button:active {
-  -moz-image-region: rect(80px, 440px, 120px, 400px);
-}
-
 #findbar-textbox {
-  pointer-events: auto;
-  -moz-margin-end: 0;
   border: none !important;
   width: 20em;
 }
 
-.textbox-search-icon {
-  list-style-image: url("chrome://browser/skin/images/search-glass-30.png");
-  -moz-image-region: auto;
-}
-
 /* Override the default box ordering and make the find textbox appear to the
    right of the icon */
 #findbar-textbox input {
   -moz-box-ordinal-group: 2
 }
 
-#findbar-textbox deck {
-  margin-right: @margin_normal@;
-}
-
 #findbar-textbox[status="1"] { /* Ci.nsITypeAheadFind.FIND_NOTFOUND */
   background: rgb(255,200,200);
 }
 
 #findbar-textbox:hover:active {
   background: #8db8d8;
 }
 
+.textbox-search-icon {
+  list-style-image: url("chrome://browser/skin/images/search-glass-30.png");
+  -moz-image-region: auto;
+}
+
+#findbar-previous-button {
+  -moz-image-region: rect(0px, 400px, 40px, 360px);
+}
+
+#findbar-previous-button:hover:not(:active) {
+  -moz-image-region: rect(40px, 400px, 80px, 360px);
+}
+
+#findbar-previous-button:active {
+  -moz-image-region: rect(80px, 400px, 120px, 360px);
+}
+
+#findbar-next-button {
+  -moz-image-region: rect(0px, 440px, 40px, 400px);
+}
+
+#findbar-next-button:hover:not(:active) {
+  -moz-image-region: rect(40px, 440px, 80px, 400px);
+}
+
+#findbar-next-button:active {
+  -moz-image-region: rect(80px, 440px, 120px, 400px);
+}
+
+#findbar-close-button {
+  -moz-image-region: rect(0px, 480px, 40px, 440px);
+}
+
+#findbar-close-button:hover:not(:active) {
+  -moz-image-region: rect(40px, 480px, 80px, 440px);
+}
+
+#findbar-close-button:active {
+  -moz-image-region: rect(80px, 480px, 120px, 440px);
+}
+
 /* Contextual appbar ======================================================= */
 
 #contextualactions-tray {
   background-color: @metro_orange@;
 }
 
 #contextualactions-tray > toolbarbutton {
   opacity: 1;
--- a/browser/metro/theme/platform.css
+++ b/browser/metro/theme/platform.css
@@ -674,67 +674,75 @@ arrowbox {
   content: ">";
 }
 
 .meta-section:not([expanded]) > .meta-section-title.narrow-title:-moz-locale-dir(rtl):before {
   content: "<";
 }
 
 /* App bars ----------------------------------------------------------------- */
+
 appbar {
   display: block;
   position: fixed;
   bottom: 0;
   width: 100%;
   transform: translateY(100%);
   transition: transform @metro_animation_duration@ @metro_animation_easing@;
   font-size: 0;
+  visibility: hidden;
 }
 
-appbar toolbar {
-  -moz-appearance: none;
-  -moz-box-align: center;
-  border: 0;
-  width: 100%;
-  min-height: @toolbar_height@;
-  font-size: 1rem;
+appbar[hiding],
+appbar[visible] {
+  visibility: visible;
 }
 
 appbar[visible] {
   transform: none;
 }
 
 #stack[keyboardVisible] > appbar {
   /* Slow the bottom up transition since it's impossible to match the system's
      soft keyboard movement. */
   transition: transform @metro_animation_duration@ @metro_animation_easing@,
               bottom @appbar_keyboard_slideup_duration@ @metro_animation_easing@;
 }
 
-appbar toolbar > toolbarbutton {
+
+appbar toolbar {
+  -moz-appearance: none;
+  -moz-box-align: center;
+  border: 0;
+  width: 100%;
+  min-height: @toolbar_height@;
+  font-size: 1rem;
+}
+
+appbar toolbar toolbarbutton {
   border: 0;
   margin: 0 @toolbar_horizontal_spacing@;
   padding: 0;
   /* Don't inherit background-color from toolbarbutton[checked="true"] */
   background-color: transparent;
 }
 
-appbar toolbar > toolbarbutton[disabled] {
+appbar toolbar toolbarbutton[disabled] {
   visibility: collapse;
 }
 
 appbar toolbar[labelled] {
   min-height: @labelled_toolbar_height@;
 }
 
-appbar toolbar[labelled] > toolbarbutton {
+appbar toolbar[labelled] toolbarbutton {
   -moz-box-orient: vertical;
 }
 
-appbar toolbar[labelled] > toolbarbutton > .toolbarbutton-text {
+appbar toolbar[labelled] toolbarbutton > .toolbarbutton-text {
   display: block;
   padding-top: @metro_spacing_small@;
   font-size: 0.75rem;
 }
 
 /* Sprites */
 
 .appbar-primary > .toolbarbutton-icon,
--- a/browser/modules/webappsUI.jsm
+++ b/browser/modules/webappsUI.jsm
@@ -101,33 +101,40 @@ this.webappsUI = {
 
   doInstall: function(aData, aBrowser, aWindow) {
     let bundle = aWindow.gNavigatorBundle;
 
     let mainAction = {
       label: bundle.getString("webapps.install"),
       accessKey: bundle.getString("webapps.install.accesskey"),
       callback: function() {
-        let app = WebappsInstaller.install(aData);
+        let app = WebappsInstaller.init(aData);
+
         if (app) {
           let localDir = null;
           if (app.appProfile) {
             localDir = app.appProfile.localDir;
           }
 
-          DOMApplicationRegistry.confirmInstall(aData, false, localDir);
-          installationSuccessNotification(aData, app, aWindow);
+          DOMApplicationRegistry.confirmInstall(aData, false, localDir, null,
+            function (aManifest) {
+              if (WebappsInstaller.install(aData, aManifest)) {
+                installationSuccessNotification(aData, app, aWindow);
+              }
+            }
+          );
         } else {
           DOMApplicationRegistry.denyInstall(aData);
         }
       }
     };
 
     let requestingURI = aWindow.makeURI(aData.from);
-    let manifest = new ManifestHelper(aData.app.manifest, aData.app.origin);
+    let jsonManifest = aData.isPackage ? aData.app.updateManifest : aData.app.manifest;
+    let manifest = new ManifestHelper(jsonManifest, aData.app.origin);
 
     let host;
     try {
       host = requestingURI.host;
     } catch(e) {
       host = requestingURI.spec;
     }
 
--- a/build/autoconf/android.m4
+++ b/build/autoconf/android.m4
@@ -292,17 +292,17 @@ case "$target" in
     android_tools="$android_sdk"/../../tools
     android_platform_tools="$android_sdk"/../../platform-tools
     if test ! -d "$android_platform_tools" ; then
         android_platform_tools="$android_sdk"/tools # SDK Tools < r8
     fi
     # The build tools got moved around to different directories in
     # SDK Tools r22.  Try to locate them.
     android_build_tools=""
-    for suffix in 18.0.0 17.0.0 android-4.2.2; do
+    for suffix in 18.0.1 18.0.0 17.0.0 android-4.2.2; do
         tools_directory="$android_sdk/../../build-tools/$suffix"
         if test -d "$tools_directory" ; then
             android_build_tools="$tools_directory"
             break
         fi
     done
     if test -z "$android_build_tools" ; then
         android_build_tools="$android_platform_tools" # SDK Tools < r22
--- a/build/autoconf/toolchain.m4
+++ b/build/autoconf/toolchain.m4
@@ -212,11 +212,13 @@ EOF
             HOST_CXXFLAGS="$CXXFLAGS"
         elif test "$ac_cv_host_cxx0x_headers_bug" = "yes"; then
             AC_MSG_ERROR([Your host toolchain does not support C++0x/C++11 mode properly. Please upgrade your toolchain])
         fi
         CXXFLAGS="$_SAVE_CXXFLAGS"
         CPPFLAGS="$_SAVE_CPPFLAGS"
         CXX="$_SAVE_CXX"
     fi
+elif test "$GNU_CXX"; then
+    HOST_CXXFLAGS="$HOST_CXXFLAGS -std=gnu++0x"
 fi
 AC_LANG_C
 ])
--- a/build/pymake/pymake/process.py
+++ b/build/pymake/pymake/process.py
@@ -28,17 +28,17 @@ def tokens2re(tokens):
     # The group names and patterns come are given as a dict in the function
     # argument.
     nonescaped = r'(?<!\\)(?:%s)' % '|'.join('(?P<%s>%s)' % (name, value) for name, value in tokens.iteritems())
     # The final pattern matches either the above pattern, or an escaped
     # backslash, captured in the "escape" match group.
     return re.compile('(?:%s|%s)' % (nonescaped, r'(?P<escape>\\\\)'))
 
 _unquoted_tokens = tokens2re({
-  'whitespace': r'[\t\r\n ]',
+  'whitespace': r'[\t\r\n ]+',
   'quote': r'[\'"]',
   'comment': '#',
   'special': r'[<>&|`~(){}$;]',
   'backslashed': r'\\[^\\]',
   'glob': r'[\*\?]',
 })
 
 _doubly_quoted_tokens = tokens2re({
@@ -54,66 +54,69 @@ class MetaCharacterException(Exception):
 
 class ClineSplitter(list):
     """
     Parses a given command line string and creates a list of command
     and arguments, with wildcard expansion.
     """
     def __init__(self, cline, cwd):
         self.cwd = cwd
-        self.arg = ''
+        self.arg = None
         self.cline = cline
         self.glob = False
         self._parse_unquoted()
 
     def _push(self, str):
         """
         Push the given string as part of the current argument
         """
+        if self.arg is None:
+            self.arg = ''
         self.arg += str
 
     def _next(self):
         """
         Finalize current argument, effectively adding it to the list.
         Perform globbing if needed.
         """
-        if not self.arg:
+        if self.arg is None:
             return
         if self.glob:
             if os.path.isabs(self.arg):
                 path = self.arg
             else:
                 path = os.path.join(self.cwd, self.arg)
             globbed = glob.glob(path)
             if not globbed:
                 # If globbing doesn't find anything, the literal string is
                 # used.
                 self.append(self.arg)
             else:
                 self.extend(f[len(path)-len(self.arg):] for f in globbed)
             self.glob = False
         else:
             self.append(self.arg)
-        self.arg = ''
+        self.arg = None
 
     def _parse_unquoted(self):
         """
         Parse command line remainder in the context of an unquoted string.
         """
         while self.cline:
             # Find the next token
             m = _unquoted_tokens.search(self.cline)
             # If we find none, the remainder of the string can be pushed to
             # the current argument and the argument finalized
             if not m:
                 self._push(self.cline)
                 break
             # The beginning of the string, up to the found token, is part of
             # the current argument
-            self._push(self.cline[:m.start()])
+            if m.start():
+                self._push(self.cline[:m.start()])
             self.cline = self.cline[m.end():]
 
             match = dict([(name, value) for name, value in m.groupdict().items() if value])
             if 'quote' in match:
                 # " or ' start a quoted string
                 if match['quote'] == '"':
                     self._parse_doubly_quoted()
                 else:
@@ -137,17 +140,18 @@ class ClineSplitter(list):
                 # e.g. echo \a -> a
                 self._push(match['backslashed'][1])
             elif 'glob' in match:
                 # ? or * will need globbing
                 self.glob = True
                 self._push(m.group(0))
             else:
                 raise Exception, "Shouldn't reach here"
-        self._next()
+        if self.arg:
+            self._next()
 
     def _parse_quoted(self):
         # Single quoted strings are preserved, except for the final quote
         index = self.cline.find("'")
         if index == -1:
             raise Exception, 'Unterminated quoted string in command'
         self._push(self.cline[:index])
         self.cline = self.cline[index+1:]
new file mode 100644
--- /dev/null
+++ b/build/pymake/tests/empty-arg.mk
@@ -0,0 +1,2 @@
+all:
+	@  sh -c 'if [ $$# = 3 ] ; then echo TEST-PASS; else echo TEST-FAIL; fi' -- a "" b  
--- a/configure.in
+++ b/configure.in
@@ -8748,18 +8748,16 @@ AC_DEFINE_UNQUOTED(MOZ_APP_UA_VERSION, "
 AC_SUBST(MOZ_APP_VERSION)
 AC_SUBST(MOZ_APP_MAXVERSION)
 AC_DEFINE_UNQUOTED(FIREFOX_VERSION,$FIREFOX_VERSION)
 AC_SUBST(FIREFOX_VERSION)
 AC_SUBST(MOZ_UA_OS_AGNOSTIC)
 if test -n "$MOZ_UA_OS_AGNOSTIC"; then
   AC_DEFINE(MOZ_UA_OS_AGNOSTIC)
 fi
-AC_DEFINE_UNQUOTED(MOZ_UA_BUILDID, "$MOZ_UA_BUILDID")
-AC_SUBST(MOZ_UA_BUILDID)
 
 AC_SUBST(MOZ_APP_STATIC_INI)
 
 AC_SUBST(MOZ_PKG_SPECIAL)
 
 AC_SUBST(MOZILLA_OFFICIAL)
 
 AC_DEFINE_UNQUOTED(MOZ_TELEMETRY_DISPLAY_REV, 2)
--- a/content/base/src/Attr.cpp
+++ b/content/base/src/Attr.cpp
@@ -52,16 +52,18 @@ Attr::Attr(nsDOMAttributeMap *aAttrMap,
                     "Wrong nodeType");
 
   // We don't add a reference to our content. It will tell us
   // to drop our reference when it goes away.
 
   SetIsDOMBinding();
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(Attr)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Attr)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 
   if (!nsINode::Traverse(tmp, cb)) {
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAttrMap)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/content/base/src/EventSource.cpp
+++ b/content/base/src/EventSource.cpp
@@ -75,16 +75,18 @@ EventSource::~EventSource()
 {
   Close();
 }
 
 //-----------------------------------------------------------------------------
 // EventSource::nsISupports
 //-----------------------------------------------------------------------------
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(EventSource)
+
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(EventSource)
   bool isBlack = tmp->IsBlack();
   if (isBlack || tmp->mWaitingForOnStopRequest) {
     if (tmp->mListenerManager) {
       tmp->mListenerManager->MarkForCC();
     }
     if (!isBlack && tmp->PreservingWrapper()) {
       xpc_UnmarkGrayObject(tmp->GetWrapperPreserveColor());
--- a/content/base/src/FileIOObject.cpp
+++ b/content/base/src/FileIOObject.cpp
@@ -24,16 +24,18 @@ NS_IMPL_ADDREF_INHERITED(FileIOObject, n
 NS_IMPL_RELEASE_INHERITED(FileIOObject, nsDOMEventTargetHelper)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FileIOObject)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
   NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(FileIOObject)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FileIOObject,
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mProgressNotifier)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
   // Can't traverse mChannel because it's a multithreaded object.
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FileIOObject,
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -1143,16 +1143,18 @@ private:
 ContentUnbinder* ContentUnbinder::sContentUnbinder = nullptr;
 
 void
 FragmentOrElement::ClearContentUnbinder()
 {
   ContentUnbinder::UnbindAll();
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(FragmentOrElement)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
   nsINode::Unlink(tmp);
 
   if (tmp->HasProperties()) {
     if (tmp->IsHTML()) {
       tmp->DeleteProperty(nsGkAtoms::microdataProperties);
       tmp->DeleteProperty(nsGkAtoms::itemtype);
       tmp->DeleteProperty(nsGkAtoms::itemref);
--- a/content/base/src/NodeIterator.cpp
+++ b/content/base/src/NodeIterator.cpp
@@ -151,16 +151,18 @@ NodeIterator::~NodeIterator()
     if (mRoot)
         mRoot->RemoveMutationObserver(this);
 }
 
 /*
  * nsISupports and cycle collection stuff
  */
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(NodeIterator)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(NodeIterator)
     if (tmp->mRoot)
         tmp->mRoot->RemoveMutationObserver(tmp);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFilter)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(NodeIterator)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
--- a/content/base/src/WebSocket.cpp
+++ b/content/base/src/WebSocket.cpp
@@ -572,16 +572,18 @@ WebSocket::Constructor(const GlobalObjec
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
   return webSocket.forget();
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(WebSocket)
+
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(WebSocket)
   bool isBlack = tmp->IsBlack();
   if (isBlack|| tmp->mKeepingAlive) {
     if (tmp->mListenerManager) {
       tmp->mListenerManager->MarkForCC();
     }
     if (!isBlack && tmp->PreservingWrapper()) {
       xpc_UnmarkGrayObject(tmp->GetWrapperPreserveColor());
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -61,16 +61,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocumentObserver)
 NS_INTERFACE_MAP_END
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsContentSink)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsContentSink)
   if (tmp->mDocument) {
     tmp->mDocument->RemoveObserver(tmp);
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParser)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNodeInfoManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mScriptLoader)
--- a/content/base/src/nsDOMAttributeMap.cpp
+++ b/content/base/src/nsDOMAttributeMap.cpp
@@ -56,16 +56,18 @@ nsDOMAttributeMap::~nsDOMAttributeMap()
 
 void
 nsDOMAttributeMap::DropReference()
 {
   mAttributeCache.Enumerate(RemoveMapRef, nullptr);
   mContent = nullptr;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMAttributeMap)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMAttributeMap)
   tmp->DropReference();
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContent)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
 PLDHashOperator
--- a/content/base/src/nsDOMDataChannel.cpp
+++ b/content/base/src/nsDOMDataChannel.cpp
@@ -51,16 +51,18 @@ nsDOMDataChannel::~nsDOMDataChannel()
 }
 
 /* virtual */ JSObject*
 nsDOMDataChannel::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return DataChannelBinding::Wrap(aCx, aScope, this);
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDataChannel)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDataChannel,
                                                   nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMDataChannel,
                                                 nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -446,16 +446,18 @@ NS_INTERFACE_MAP_END
 
 // Threadsafe when GetMutable() == false
 NS_IMPL_ADDREF(nsDOMFile)
 NS_IMPL_RELEASE(nsDOMFile)
 
 ////////////////////////////////////////////////////////////////////////////
 // nsDOMFileCC implementation
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileCC)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsDOMFileCC)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMFileCC)
   // We don't have anything to traverse, but some of our subclasses do.
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMFileCC)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFile)
   NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -49,16 +49,18 @@
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #define LOAD_STR "load"
 #define LOADSTART_STR "loadstart"
 #define LOADEND_STR "loadend"
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileReader)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMFileReader,
                                                   FileIOObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFile)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrincipal)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMFileReader,
                                                 FileIOObject)
--- a/content/base/src/nsDOMMutationObserver.cpp
+++ b/content/base/src/nsDOMMutationObserver.cpp
@@ -321,16 +321,18 @@ void nsMutationReceiver::NodeWillBeDestr
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMMutationObserver)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMMutationObserver)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMMutationObserver)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMutationObserver)
+
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMMutationObserver)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMMutationObserver)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
   for (int32_t i = 0; i < tmp->mReceivers.Count(); ++i) {
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1833,16 +1833,17 @@ static PLDHashOperator
 CustomPrototypeTrace(const nsAString& aName, JS::Heap<JSObject*>& aObject, void *aArg)
 {
   CustomPrototypeTraceArgs* traceArgs = static_cast<CustomPrototypeTraceArgs*>(aArg);
   MOZ_ASSERT(aObject, "Protocol object value must not be null");
   traceArgs->callbacks.Trace(&aObject, "mCustomPrototypes entry", traceArgs->closure);
   return PL_DHASH_NEXT;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument)
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDocument)
   CustomPrototypeTraceArgs customPrototypeArgs = { aCallbacks, aClosure };
   tmp->mCustomPrototypes.Enumerate(CustomPrototypeTrace, &customPrototypeArgs);
   if (tmp->PreservingWrapper()) {
     NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mExpandoAndGeneration.expando);
   }
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -41,16 +41,18 @@
 #ifdef XP_WIN
 #include <windows.h>
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::dom::ipc;
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameMessageManager)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameMessageManager)
   uint32_t count = tmp->mListeners.Length();
   for (uint32_t i = 0; i < count; i++) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mListeners[i] mListener");
     cb.NoteXPCOMChild(tmp->mListeners[i].mListener.get());
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildManagers)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -58,16 +58,18 @@ nsGenericDOMDataNode::~nsGenericDOMDataN
 {
   NS_PRECONDITION(!IsInDoc(),
                   "Please remove this from the document properly");
   if (GetParent()) {
     NS_RELEASE(mParent);
   }
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericDOMDataNode)
+
 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsGenericDOMDataNode)
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGenericDOMDataNode)
   return Element::CanSkip(tmp, aRemovingAllowed);
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGenericDOMDataNode)
   return Element::CanSkipInCC(tmp);
--- a/content/base/src/nsNodeInfo.cpp
+++ b/content/base/src/nsNodeInfo.cpp
@@ -106,16 +106,18 @@ nsNodeInfo::nsNodeInfo(nsIAtom *aName, n
       NS_ABORT_IF_FALSE(aNodeType == UINT16_MAX,
                         "Unknown node type");
   }
 }
 
 
 // nsISupports
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeInfo)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsNodeInfo)
 
 static const char* kNSURIs[] = {
   " ([none])",
   " (xmlns)",
   " (xml)",
   " (xhtml)",
   " (XLink)",
--- a/content/base/src/nsNodeInfoManager.cpp
+++ b/content/base/src/nsNodeInfoManager.cpp
@@ -154,16 +154,18 @@ nsNodeInfoManager::~nsNodeInfoManager()
   if (gNodeInfoManagerLeakPRLog)
     PR_LOG(gNodeInfoManagerLeakPRLog, PR_LOG_DEBUG,
            ("NODEINFOMANAGER %p destroyed", this));
 #endif
 
   nsLayoutStatics::Release();
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeInfoManager)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsNodeInfoManager)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsNodeInfoManager)
   if (tmp->mDocument &&
       nsCCUncollectableMarker::InGeneration(cb,
                                             tmp->mDocument->GetMarkedCCGeneration())) {
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
   if (tmp->mNonDocumentNodeInfos) {
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -275,16 +275,18 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LA
 // QueryInterface implementation for nsRange
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsRange)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMRange)
   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMRange)
 NS_INTERFACE_MAP_END
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsRange)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsRange)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner);
   tmp->Reset();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsRange)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -239,16 +239,18 @@ XMLHttpRequestAuthPrompt::PromptPassword
                                          bool* aRetval)
 {
   *aRetval = false;
   return NS_OK;
 }
 
 /////////////////////////////////////////////
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXHREventTarget)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXHREventTarget,
                                                   nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXHREventTarget,
                                                 nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
@@ -443,16 +445,18 @@ nsXMLHttpRequest::ResetResponse()
 }
 
 void
 nsXMLHttpRequest::SetRequestObserver(nsIRequestObserver* aObserver)
 {
   mRequestObserver = aObserver;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequest)
+
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsXMLHttpRequest)
   bool isBlack = tmp->IsBlack();
   if (isBlack || tmp->mWaitingForOnStopRequest) {
     if (tmp->mListenerManager) {
       tmp->mListenerManager->MarkForCC();
     }
     if (!isBlack && tmp->PreservingWrapper()) {
       xpc_UnmarkGrayObject(tmp->GetWrapperPreserveColor());
@@ -3803,16 +3807,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamListener)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXMLHttpRequestXPCOMifier)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXMLHttpRequestXPCOMifier)
 
 // Can't NS_IMPL_CYCLE_COLLECTION_1 because mXHR has ambiguous
 // inheritance from nsISupports.
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequestXPCOMifier)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXMLHttpRequestXPCOMifier)
 if (tmp->mXHR) {
   tmp->mXHR->mXPCOMifier = nullptr;
 }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mXHR)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXMLHttpRequestXPCOMifier)
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -683,18 +683,17 @@ protected:
 };
 
 // A shim class designed to expose the non-DOM interfaces of
 // XMLHttpRequest via XPCOM stuff.
 class nsXMLHttpRequestXPCOMifier MOZ_FINAL : public nsIStreamListener,
                                              public nsIChannelEventSink,
                                              public nsIProgressEventSink,
                                              public nsIInterfaceRequestor,
-                                             public nsITimerCallback,
-                                             public nsCycleCollectionParticipant
+                                             public nsITimerCallback
 {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier,
                                            nsIStreamListener)
 
   nsXMLHttpRequestXPCOMifier(nsXMLHttpRequest* aXHR) :
     mXHR(aXHR)
   {
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -467,16 +467,18 @@ public:
 
 private:
   CanvasRenderingContext2D *mContext;
 };
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(CanvasRenderingContext2D)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(CanvasRenderingContext2D)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(CanvasRenderingContext2D)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CanvasRenderingContext2D)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCanvasElement)
   for (uint32_t i = 0; i < tmp->mStyleStack.Length(); i++) {
     ImplCycleCollectionUnlink(tmp->mStyleStack[i].patternStyles[STYLE_STROKE]);
     ImplCycleCollectionUnlink(tmp->mStyleStack[i].patternStyles[STYLE_FILL]);
     ImplCycleCollectionUnlink(tmp->mStyleStack[i].gradientStyles[STYLE_STROKE]);
     ImplCycleCollectionUnlink(tmp->mStyleStack[i].gradientStyles[STYLE_FILL]);
   }
--- a/content/canvas/src/ImageData.cpp
+++ b/content/canvas/src/ImageData.cpp
@@ -13,16 +13,18 @@
 #include "jsapi.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(ImageData)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(ImageData)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(ImageData)
+
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ImageData)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ImageData)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mData)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -1017,17 +1017,17 @@ bool WebGLContext::IsExtensionSupported(
                 return true;
             }
             return false;
         default:
             // For warnings-as-errors.
             break;
     }
 
-    if (Preferences::GetBool("webgl.enable-draft-extensions", false)) {
+    if (Preferences::GetBool("webgl.enable-draft-extensions", false) || IsWebGL2()) {
         switch (ext) {
             case WEBGL_draw_buffers:
                 return WebGLExtensionDrawBuffers::IsSupported(this);
             default:
                 // For warnings-as-errors.
                 break;
         }
     }
--- a/content/events/public/nsEventStates.h
+++ b/content/events/public/nsEventStates.h
@@ -1,65 +1,66 @@
 /* -*- 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 nsEventStates_h__
 #define nsEventStates_h__
 
+#include "mozilla/Attributes.h"
 #include "nsDebug.h"
 
 /**
  * nsEventStates is the class used to represent the event states of nsIContent
  * instances. These states are calculated by IntrinsicState() and
  * ContentStatesChanged() has to be called when one of them changes thus
  * informing the layout/style engine of the change.
  * Event states are associated with pseudo-classes.
  */
 class nsEventStates
 {
 public:
   typedef uint64_t InternalType;
 
-  nsEventStates()
+  MOZ_CONSTEXPR nsEventStates()
     : mStates(0)
   { }
 
   // NOTE: the ideal scenario would be to have the default constructor public
   // setting mStates to 0 and this constructor (without = 0) private.
   // In that case, we could be sure that only macros at the end were creating
   // nsEventStates instances with mStates set to something else than 0.
   // Unfortunately, this constructor is needed at at least two places now.
-  explicit nsEventStates(InternalType aStates)
+  explicit MOZ_CONSTEXPR nsEventStates(InternalType aStates)
     : mStates(aStates)
   { }
 
-  nsEventStates(const nsEventStates& aEventStates) {
-    mStates = aEventStates.mStates;
+  MOZ_CONSTEXPR nsEventStates(const nsEventStates& aEventStates)
+    : mStates(aEventStates.mStates) {
   }
 
   nsEventStates& operator=(const nsEventStates& aEventStates) {
     mStates = aEventStates.mStates;
     return *this;
   }
 
-  nsEventStates operator|(const nsEventStates& aEventStates) const {
+  nsEventStates MOZ_CONSTEXPR operator|(const nsEventStates& aEventStates) const {
     return nsEventStates(mStates | aEventStates.mStates);
   }
 
   nsEventStates& operator|=(const nsEventStates& aEventStates) {
     mStates |= aEventStates.mStates;
     return *this;
   }
 
   // NOTE: calling if (eventStates1 & eventStates2) will not build.
   // This might work correctly if operator bool() is defined
   // but using HasState, HasAllStates or HasAtLeastOneOfStates is recommended.
-  nsEventStates operator&(const nsEventStates& aEventStates) const {
+  nsEventStates MOZ_CONSTEXPR operator&(const nsEventStates& aEventStates) const {
     return nsEventStates(mStates & aEventStates.mStates);
   }
 
   nsEventStates& operator&=(const nsEventStates& aEventStates) {
     mStates &= aEventStates.mStates;
     return *this;
   }
 
--- a/content/events/src/nsDOMDataContainerEvent.cpp
+++ b/content/events/src/nsDOMDataContainerEvent.cpp
@@ -11,16 +11,18 @@ nsDOMDataContainerEvent::nsDOMDataContai
                                              mozilla::dom::EventTarget* aOwner,
                                              nsPresContext* aPresContext,
                                              nsEvent* aEvent)
   : nsDOMEvent(aOwner, aPresContext, aEvent)
 {
   mData.Init();
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDataContainerEvent)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMDataContainerEvent,
                                                 nsDOMEvent)
   if (tmp->mData.IsInitialized())
     tmp->mData.Clear();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDataContainerEvent,
                                                   nsDOMEvent)
--- a/content/events/src/nsDOMDataTransfer.cpp
+++ b/content/events/src/nsDOMDataTransfer.cpp
@@ -26,16 +26,18 @@
 #include "nsCRT.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIWebNavigation.h"
 #include "nsIScriptContext.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDataTransfer)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMDataTransfer)
   if (tmp->mFiles) {
     tmp->mFiles->Disconnect();
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mFiles)
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDragTarget)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDragImage)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -126,16 +126,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEvent)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMEvent)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMEvent)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEvent)
+
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMEvent)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEvent)
   if (tmp->mEventIsInternal) {
     tmp->mEvent->target = nullptr;
     tmp->mEvent->currentTarget = nullptr;
--- a/content/events/src/nsDOMEventTargetHelper.cpp
+++ b/content/events/src/nsDOMEventTargetHelper.cpp
@@ -12,16 +12,18 @@
 #include "prprf.h"
 #include "nsGlobalWindow.h"
 #include "nsDOMEvent.h"
 #include "mozilla/Likely.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEventTargetHelper)
+
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDOMEventTargetHelper)
   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
     char name[512];
     nsAutoString uri;
--- a/content/events/src/nsDOMMessageEvent.cpp
+++ b/content/events/src/nsDOMMessageEvent.cpp
@@ -5,16 +5,18 @@
 
 #include "nsDOMMessageEvent.h"
 #include "nsContentUtils.h"
 #include "jsapi.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMessageEvent)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMMessageEvent, nsDOMEvent)
   tmp->mData = JSVAL_VOID;
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSource)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMMessageEvent, nsDOMEvent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSource)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp
+++ b/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp
@@ -30,16 +30,18 @@ nsDOMNotifyAudioAvailableEvent::nsDOMNot
   if (mEvent) {
     mEvent->message = aEventType;
   }
 }
 
 NS_IMPL_ADDREF_INHERITED(nsDOMNotifyAudioAvailableEvent, nsDOMEvent)
 NS_IMPL_RELEASE_INHERITED(nsDOMNotifyAudioAvailableEvent, nsDOMEvent)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMNotifyAudioAvailableEvent)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMNotifyAudioAvailableEvent, nsDOMEvent)
   if (tmp->mCachedArray) {
     tmp->mCachedArray = nullptr;
     NS_DROP_JS_OBJECTS(tmp, nsDOMNotifyAudioAvailableEvent);
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMNotifyAudioAvailableEvent, nsDOMEvent)
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -176,16 +176,18 @@ ImplCycleCollectionTraverse(nsCycleColle
     CycleCollectionNoteChild(aCallback, aField.mListener.GetISupports(), name.get(),
                              aFlags);
   } else {
     CycleCollectionNoteChild(aCallback, aField.mListener.GetISupports(), aName,
                              aFlags);
   }
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsEventListenerManager)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEventListenerManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListeners)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsEventListenerManager)
   tmp->Disconnect();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
--- a/content/html/content/src/HTMLButtonElement.cpp
+++ b/content/html/content/src/HTMLButtonElement.cpp
@@ -49,17 +49,17 @@ static const nsAttrValue::EnumTable kBut
 
 // Default type is 'submit'.
 static const nsAttrValue::EnumTable* kButtonDefaultType = &kButtonTypeTable[2];
 
 
 // Construction, destruction
 HTMLButtonElement::HTMLButtonElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                                      FromParser aFromParser)
-  : nsGenericHTMLFormElement(aNodeInfo),
+  : nsGenericHTMLFormElementWithState(aNodeInfo),
     mType(kButtonDefaultType->value),
     mDisabledChanged(false),
     mInInternalActivate(false),
     mInhibitStateRestoration(!!(aFromParser & FROM_PARSER_FRAGMENT))
 {
   // <button> is always barred from constraint validation.
   SetBarredFromConstraintValidation(true);
 
@@ -68,26 +68,27 @@ HTMLButtonElement::HTMLButtonElement(alr
 }
 
 HTMLButtonElement::~HTMLButtonElement()
 {
 }
 
 // nsISupports
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED_1(HTMLButtonElement, nsGenericHTMLFormElement,
+NS_IMPL_CYCLE_COLLECTION_INHERITED_1(HTMLButtonElement,
+                                     nsGenericHTMLFormElementWithState,
                                      mValidity)
 
 NS_IMPL_ADDREF_INHERITED(HTMLButtonElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLButtonElement, Element)
 
 
 // QueryInterface implementation for HTMLButtonElement
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLButtonElement)
-  NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElement)
+  NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElementWithState)
   NS_INTERFACE_TABLE_INHERITED2(HTMLButtonElement,
                                 nsIDOMHTMLButtonElement,
                                 nsIConstraintValidation)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 // nsIConstraintValidation
 NS_IMPL_NSICONSTRAINTVALIDATION(HTMLButtonElement)
@@ -98,17 +99,17 @@ NS_IMPL_NSICONSTRAINTVALIDATION(HTMLButt
 NS_IMPL_ELEMENT_CLONE(HTMLButtonElement)
 
 
 // nsIDOMHTMLButtonElement
 
 NS_IMETHODIMP
 HTMLButtonElement::GetForm(nsIDOMHTMLFormElement** aForm)
 {
-  return nsGenericHTMLFormElement::GetForm(aForm);
+  return nsGenericHTMLFormElementWithState::GetForm(aForm);
 }
 
 NS_IMPL_BOOL_ATTR(HTMLButtonElement, Autofocus, autofocus)
 NS_IMPL_BOOL_ATTR(HTMLButtonElement, Disabled, disabled)
 NS_IMPL_ACTION_ATTR(HTMLButtonElement, FormAction, formaction)
 NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES(HTMLButtonElement, FormEnctype, formenctype,
                                                  "", kFormDefaultEnctype->tag)
 NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES(HTMLButtonElement, FormMethod, formmethod,
@@ -124,17 +125,17 @@ int32_t
 HTMLButtonElement::TabIndexDefault()
 {
   return 0;
 }
 
 bool
 HTMLButtonElement::IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex)
 {
-  if (nsGenericHTMLFormElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
+  if (nsGenericHTMLFormElementWithState::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
     return true;
   }
 
   *aIsFocusable = 
 #ifdef XP_MACOSX
     (!aWithMouse || nsFocusManager::sMouseFocusesFormControl) &&
 #endif
     !IsDisabled();
@@ -387,31 +388,31 @@ HTMLButtonElement::PostHandleEvent(nsEve
   return rv;
 }
 
 nsresult
 HTMLButtonElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers)
 {
-  nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
-                                                     aBindingParent,
-                                                     aCompileEventHandlers);
+  nsresult rv =
+    nsGenericHTMLFormElementWithState::BindToTree(aDocument, aParent, aBindingParent,
+                                                  aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Update our state; we may now be the default submit element
   UpdateState(false);
 
   return NS_OK;
 }
 
 void
 HTMLButtonElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
-  nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
+  nsGenericHTMLFormElementWithState::UnbindFromTree(aDeep, aNullParent);
 
   // Update our state; we may no longer be the default submit element
   UpdateState(false);
 }
 
 NS_IMETHODIMP
 HTMLButtonElement::Reset()
 {
@@ -456,51 +457,53 @@ HTMLButtonElement::SubmitNamesValues(nsF
   //
   return aFormSubmission->AddNameValuePair(name, value);
 }
 
 void
 HTMLButtonElement::DoneCreatingElement()
 {
   if (!mInhibitStateRestoration) {
-    // Restore state as needed.
-    RestoreFormControlState(this, this);
+    nsresult rv = GenerateStateKey();
+    if (NS_SUCCEEDED(rv)) {
+      RestoreFormControlState();
+    }
   }
 }
 
 nsresult
 HTMLButtonElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify)
 {
   if (aNotify && aName == nsGkAtoms::disabled &&
       aNameSpaceID == kNameSpaceID_None) {
     mDisabledChanged = true;
   }
 
-  return nsGenericHTMLFormElement::BeforeSetAttr(aNameSpaceID, aName,
-                                                 aValue, aNotify);
+  return nsGenericHTMLFormElementWithState::BeforeSetAttr(aNameSpaceID, aName,
+                                                          aValue, aNotify);
 }
 
 nsresult
 HTMLButtonElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue, bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::type) {
       if (!aValue) {
         mType = kButtonDefaultType->value;
       }
 
       UpdateState(aNotify);
     }
   }
 
-  return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
-                                                aValue, aNotify);
+  return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
+                                                         aValue, aNotify);
 }
 
 NS_IMETHODIMP
 HTMLButtonElement::SaveState()
 {
   if (!mDisabledChanged) {
     return NS_OK;
   }
@@ -523,17 +526,17 @@ HTMLButtonElement::RestoreState(nsPresSt
   }
 
   return false;
 }
 
 nsEventStates
 HTMLButtonElement::IntrinsicState() const
 {
-  nsEventStates state = nsGenericHTMLFormElement::IntrinsicState();
+  nsEventStates state = nsGenericHTMLFormElementWithState::IntrinsicState();
 
   if (mForm && !mForm->GetValidity() && IsSubmitControl()) {
     state |= NS_EVENT_STATE_MOZ_SUBMITINVALID;
   }
 
   return state;
 }
 
--- a/content/html/content/src/HTMLButtonElement.h
+++ b/content/html/content/src/HTMLButtonElement.h
@@ -9,29 +9,29 @@
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMHTMLButtonElement.h"
 #include "nsIConstraintValidation.h"
 
 namespace mozilla {
 namespace dom {
 
-class HTMLButtonElement MOZ_FINAL : public nsGenericHTMLFormElement,
+class HTMLButtonElement MOZ_FINAL : public nsGenericHTMLFormElementWithState,
                                     public nsIDOMHTMLButtonElement,
                                     public nsIConstraintValidation
 {
 public:
   using nsIConstraintValidation::GetValidationMessage;
 
   HTMLButtonElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                       FromParser aFromParser = NOT_FROM_PARSER);
   virtual ~HTMLButtonElement();
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLButtonElement,
-                                           nsGenericHTMLFormElement)
+                                           nsGenericHTMLFormElementWithState)
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
--- a/content/html/content/src/HTMLDataListElement.cpp
+++ b/content/html/content/src/HTMLDataListElement.cpp
@@ -22,36 +22,25 @@ HTMLDataListElement::WrapNode(JSContext 
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED_1(HTMLDataListElement, nsGenericHTMLElement,
                                      mOptions)
 
 NS_IMPL_ADDREF_INHERITED(HTMLDataListElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLDataListElement, Element)
 
-NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLDataListElement)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLDataListElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
-  NS_INTERFACE_TABLE_INHERITED1(HTMLDataListElement,
-                                nsIDOMHTMLDataListElement)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLDataListElement)
 
 bool
 HTMLDataListElement::MatchOptions(nsIContent* aContent, int32_t aNamespaceID,
                                   nsIAtom* aAtom, void* aData)
 {
   return aContent->NodeInfo()->Equals(nsGkAtoms::option, kNameSpaceID_XHTML) &&
          !aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
 }
 
-NS_IMETHODIMP
-HTMLDataListElement::GetOptions(nsIDOMHTMLCollection** aOptions)
-{
-  NS_ADDREF(*aOptions = Options());
-
-  return NS_OK;
-}
-
 } // namespace dom
 } // namespace mozilla
--- a/content/html/content/src/HTMLDataListElement.h
+++ b/content/html/content/src/HTMLDataListElement.h
@@ -2,24 +2,23 @@
 /* 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 HTMLDataListElement_h___
 #define HTMLDataListElement_h___
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
-#include "nsIDOMHTMLDataListElement.h"
 #include "nsContentList.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLDataListElement MOZ_FINAL : public nsGenericHTMLElement,
-                                      public nsIDOMHTMLDataListElement
+                                      public nsIDOMHTMLElement
 {
 public:
   HTMLDataListElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLDataListElement();
 
@@ -30,19 +29,16 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
-  // nsIDOMHTMLDataListElement
-  NS_DECL_NSIDOMHTMLDATALISTELEMENT
-
   nsContentList* Options()
   {
     if (!mOptions) {
       mOptions = new nsContentList(this, MatchOptions, nullptr, nullptr, true);
     }
 
     return mOptions;
   }
--- a/content/html/content/src/HTMLFontElement.cpp
+++ b/content/html/content/src/HTMLFontElement.cpp
@@ -26,76 +26,23 @@ HTMLFontElement::WrapNode(JSContext *aCx
 {
   return HTMLFontElementBinding::Wrap(aCx, aScope, this);
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLFontElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLFontElement, Element)
 
 // QueryInterface implementation for HTMLFontElement
-NS_INTERFACE_TABLE_HEAD(HTMLFontElement)
+NS_INTERFACE_MAP_BEGIN(HTMLFontElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
-  NS_INTERFACE_TABLE_INHERITED1(HTMLFontElement, nsIDOMHTMLFontElement)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLFontElement)
 
-NS_IMETHODIMP
-HTMLFontElement::GetColor(nsAString& aColor)
-{
-  nsString color;
-  GetColor(color);
-  aColor = color;
-  return NS_OK;
-}
-
-NS_IMETHODIMP 
-HTMLFontElement::SetColor(const nsAString& aColor)
-{
-  ErrorResult rv;
-  SetColor(aColor, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLFontElement::GetFace(nsAString& aFace)
-{
-  nsString face;
-  GetFace(face);
-  aFace = face;
-  return NS_OK;
-}
-
-NS_IMETHODIMP 
-HTMLFontElement::SetFace(const nsAString& aFace)
-{
-  ErrorResult rv;
-  SetFace(aFace, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLFontElement::GetSize(nsAString& aSize)
-{
-  nsString size;
-  GetSize(size);
-  aSize = size;
-  return NS_OK;
-}
-
-NS_IMETHODIMP 
-HTMLFontElement::SetSize(const nsAString& aSize)
-{
-  ErrorResult rv;
-  SetSize(aSize, rv);
-  return rv.ErrorCode();
-}
-
 bool
 HTMLFontElement::ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::size) {
--- a/content/html/content/src/HTMLFontElement.h
+++ b/content/html/content/src/HTMLFontElement.h
@@ -2,23 +2,22 @@
 /* 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 HTMLFontElement_h___
 #define HTMLFontElement_h___
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
-#include "nsIDOMHTMLFontElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLFontElement MOZ_FINAL : public nsGenericHTMLElement,
-                                  public nsIDOMHTMLFontElement
+                                  public nsIDOMHTMLElement
 {
 public:
   HTMLFontElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLFontElement();
 
@@ -29,19 +28,16 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
-  // nsIDOMHTMLFontElement
-  NS_DECL_NSIDOMHTMLFONTELEMENT
-
   void GetColor(nsString& aColor)
   {
     GetHTMLAttr(nsGkAtoms::color, aColor);
   }
   void SetColor(const nsAString& aColor, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::color, aColor, aError);
   }
--- a/content/html/content/src/HTMLFormElement.cpp
+++ b/content/html/content/src/HTMLFormElement.cpp
@@ -294,16 +294,18 @@ ElementTraverser(const nsAString& key, n
 {
   nsCycleCollectionTraversalCallback *cb = 
     static_cast<nsCycleCollectionTraversalCallback*>(userArg);
  
   cb->NoteXPCOMChild(element);
   return PL_DHASH_NEXT;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLFormElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLFormElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControls)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImageNameLookupTable)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPastNameLookupTable)
   tmp->mSelectedRadioButtons.EnumerateRead(ElementTraverser, &cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
@@ -2410,16 +2412,18 @@ nsFormControlList::FlushPendingNotificat
   if (mForm) {
     nsIDocument* doc = mForm->GetCurrentDoc();
     if (doc) {
       doc->FlushPendingNotifications(Flush_Content);
     }
   }
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsFormControlList)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFormControlList)
   tmp->Clear();
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFormControlList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNameLookupTable)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -765,17 +765,17 @@ static nsresult FireEventForAccessibilit
 #endif
 
 //
 // construction, destruction
 //
 
 HTMLInputElement::HTMLInputElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                                    FromParser aFromParser)
-  : nsGenericHTMLFormElement(aNodeInfo)
+  : nsGenericHTMLFormElementWithState(aNodeInfo)
   , mType(kInputDefaultType->value)
   , mDisabledChanged(false)
   , mValueChanged(false)
   , mCheckedChanged(false)
   , mChecked(false)
   , mHandlingSelectEvent(false)
   , mShouldInitChecked(false)
   , mParserCreating(aFromParser != NOT_FROM_PARSER)
@@ -837,29 +837,31 @@ HTMLInputElement::GetEditorState() const
                                 " associated with them");
 
   return mInputData.mState;
 }
 
 
 // nsISupports
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLInputElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLInputElement,
-                                                  nsGenericHTMLFormElement)
+                                                  nsGenericHTMLFormElementWithState)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)
   if (tmp->IsSingleLineTextControl(false)) {
     tmp->mInputData.mState->Traverse(cb);
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFiles)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFileList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLInputElement,
-                                                  nsGenericHTMLFormElement)
+                                                nsGenericHTMLFormElementWithState)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFiles)
   if (tmp->mFileList) {
     tmp->mFileList->Disconnect();
     tmp->mFileList = nullptr;
   }
   if (tmp->IsSingleLineTextControl(false)) {
@@ -868,17 +870,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
   //XXX should unlink more?
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLInputElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLInputElement, Element)
 
 // QueryInterface implementation for HTMLInputElement
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLInputElement)
-  NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElement)
+  NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElementWithState)
   NS_INTERFACE_TABLE_INHERITED8(HTMLInputElement,
                                 nsIDOMHTMLInputElement,
                                 nsITextControlElement,
                                 nsIPhonetic,
                                 imgINotificationObserver,
                                 nsIImageLoadingContent,
                                 imgIOnloadBlocker,
                                 nsIDOMNSEditableElement,
@@ -970,18 +972,18 @@ HTMLInputElement::BeforeSetAttr(int32_t 
       mDisabledChanged = true;
     } else if (aName == nsGkAtoms::dir &&
                AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir,
                            nsGkAtoms::_auto, eIgnoreCase)) {
       SetDirectionIfAuto(false, aNotify);
     }
   }
 
-  return nsGenericHTMLFormElement::BeforeSetAttr(aNameSpaceID, aName,
-                                                 aValue, aNotify);
+  return nsGenericHTMLFormElementWithState::BeforeSetAttr(aNameSpaceID, aName,
+                                                          aValue, aNotify);
 }
 
 nsresult
 HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                const nsAttrValue* aValue, bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     //
@@ -1115,26 +1117,26 @@ HTMLInputElement::AfterSetAttr(int32_t a
     } else if (aName == nsGkAtoms::dir &&
                aValue && aValue->Equals(nsGkAtoms::_auto, eIgnoreCase)) {
       SetDirectionIfAuto(true, aNotify);
     }
 
     UpdateState(aNotify);
   }
 
-  return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
-                                                aValue, aNotify);
+  return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
+                                                         aValue, aNotify);
 }
 
 // nsIDOMHTMLInputElement
 
 NS_IMETHODIMP
 HTMLInputElement::GetForm(nsIDOMHTMLFormElement** aForm)
 {
-  return nsGenericHTMLFormElement::GetForm(aForm);
+  return nsGenericHTMLFormElementWithState::GetForm(aForm);
 }
 
 NS_IMPL_STRING_ATTR(HTMLInputElement, DefaultValue, value)
 NS_IMPL_BOOL_ATTR(HTMLInputElement, DefaultChecked, checked)
 NS_IMPL_STRING_ATTR(HTMLInputElement, Accept, accept)
 NS_IMPL_STRING_ATTR(HTMLInputElement, Align, align)
 NS_IMPL_STRING_ATTR(HTMLInputElement, Alt, alt)
 NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLInputElement, Autocomplete, autocomplete,
@@ -2249,19 +2251,19 @@ HTMLInputElement::SetValueInternal(const
       // the meaning of ValueChanged just a teensy bit to save a measly byte of
       // storage space in HTMLInputElement.  Yes, you are free to make a new flag,
       // NEED_TO_SAVE_VALUE, at such time as mBitField becomes a 16-bit value.
       if (mType == NS_FORM_INPUT_HIDDEN) {
         SetValueChanged(true);
       }
 
       // Treat value == defaultValue for other input elements.
-      return nsGenericHTMLFormElement::SetAttr(kNameSpaceID_None,
-                                               nsGkAtoms::value, aValue,
-                                               true);
+      return nsGenericHTMLFormElementWithState::SetAttr(kNameSpaceID_None,
+                                                        nsGkAtoms::value, aValue,
+                                                        true);
 
     case VALUE_MODE_FILENAME:
       return NS_ERROR_UNEXPECTED;
   }
 
   // This return statement is required for some compilers.
   return NS_OK;
 }
@@ -2760,25 +2762,25 @@ HTMLInputElement::PreHandleEvent(nsEvent
       SetValueInternal(aValue, false, false);
     }
     FireChangeEventIfNeeded();
   }
 
   if (mType == NS_FORM_INPUT_RANGE &&
       (aVisitor.mEvent->message == NS_FOCUS_CONTENT ||
        aVisitor.mEvent->message == NS_BLUR_CONTENT)) {
-    // Just as nsGenericHTMLFormElement::PreHandleEvent calls
+    // Just as nsGenericHTMLFormElementWithState::PreHandleEvent calls
     // nsIFormControlFrame::SetFocus, we handle focus here.
     nsIFrame* frame = GetPrimaryFrame();
     if (frame) {
       frame->InvalidateFrameSubtree();
     }
   }
 
-  return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
+  return nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor);
 }
 
 void
 HTMLInputElement::StartRangeThumbDrag(nsGUIEvent* aEvent)
 {
   mIsDraggingRange = true;
   mRangeThumbDragStartValue = GetValueAsDecimal();
   nsIPresShell::SetCapturingContent(this, CAPTURE_IGNOREALLOWED |
@@ -3446,19 +3448,19 @@ HTMLInputElement::MaybeLoadImage()
   }
 }
 
 nsresult
 HTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                              nsIContent* aBindingParent,
                              bool aCompileEventHandlers)
 {
-  nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
-                                                     aBindingParent,
-                                                     aCompileEventHandlers);
+  nsresult rv = nsGenericHTMLFormElementWithState::BindToTree(aDocument, aParent,
+                                                              aBindingParent,
+                                                              aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
                                     aCompileEventHandlers);
 
   if (mType == NS_FORM_INPUT_IMAGE) {
     // Our base URI may have changed; claim that our URI changed, and the
     // nsImageLoadingContent will decide whether a new image load is warranted.
@@ -3495,26 +3497,26 @@ HTMLInputElement::BindToTree(nsIDocument
 
   return rv;
 }
 
 void
 HTMLInputElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   // If we have a form and are unbound from it,
-  // nsGenericHTMLFormElement::UnbindFromTree() will unset the form and
+  // nsGenericHTMLFormElementWithState::UnbindFromTree() will unset the form and
   // that takes care of form's WillRemove so we just have to take care
   // of the case where we're removing from the document and we don't
   // have a form
   if (!mForm && mType == NS_FORM_INPUT_RADIO) {
     WillRemoveFromRadioGroup();
   }
 
   nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
-  nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
+  nsGenericHTMLFormElementWithState::UnbindFromTree(aDeep, aNullParent);
 
   // GetCurrentDoc is returning nullptr so we can update the value
   // missing validity state to reflect we are no longer into a doc.
   UpdateValueMissingValidityState();
   // We might be no longer disabled because of parent chain changed.
   UpdateBarredFromConstraintValidation();
 
   // And now make sure our state is up to date
@@ -4020,32 +4022,32 @@ HTMLInputElement::ParseAttribute(int32_t
 
 static void
 MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                       nsRuleData* aData)
 {
   const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
   if (value && value->Type() == nsAttrValue::eEnum &&
       value->GetEnumValue() == NS_FORM_INPUT_IMAGE) {
-    nsGenericHTMLFormElement::MapImageBorderAttributeInto(aAttributes, aData);
-    nsGenericHTMLFormElement::MapImageMarginAttributeInto(aAttributes, aData);
-    nsGenericHTMLFormElement::MapImageSizeAttributesInto(aAttributes, aData);
+    nsGenericHTMLFormElementWithState::MapImageBorderAttributeInto(aAttributes, aData);
+    nsGenericHTMLFormElementWithState::MapImageMarginAttributeInto(aAttributes, aData);
+    nsGenericHTMLFormElementWithState::MapImageSizeAttributesInto(aAttributes, aData);
     // Images treat align as "float"
-    nsGenericHTMLFormElement::MapImageAlignAttributeInto(aAttributes, aData);
-  }
-
-  nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aData);
+    nsGenericHTMLFormElementWithState::MapImageAlignAttributeInto(aAttributes, aData);
+  }
+
+  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
 }
 
 nsChangeHint
 HTMLInputElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                          int32_t aModType) const
 {
   nsChangeHint retval =
-    nsGenericHTMLFormElement::GetAttributeChangeHint(aAttribute, aModType);
+    nsGenericHTMLFormElementWithState::GetAttributeChangeHint(aAttribute, aModType);
   if (aAttribute == nsGkAtoms::type) {
     NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
   } else if (mType == NS_FORM_INPUT_IMAGE &&
              (aAttribute == nsGkAtoms::alt ||
               aAttribute == nsGkAtoms::value)) {
     // We might need to rebuild our alt text.  Just go ahead and
     // reconstruct our frame.  This should be quite rare..
     NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
@@ -4694,17 +4696,17 @@ HTMLInputElement::DoneCreatingElement()
 {
   mParserCreating = false;
 
   //
   // Restore state as needed.  Note that disabled state applies to all control
   // types.
   //
   bool restoredCheckedState =
-    !mInhibitRestoration && RestoreFormControlState(this, this);
+    !mInhibitRestoration && NS_SUCCEEDED(GenerateStateKey()) && RestoreFormControlState();
 
   //
   // If restore does not occur, we initialize .checked using the CHECKED
   // property.
   //
   if (!restoredCheckedState && mShouldInitChecked) {
     DoSetChecked(DefaultChecked(), false, true);
     DoSetCheckedChanged(false, false);
@@ -4721,17 +4723,17 @@ HTMLInputElement::DoneCreatingElement()
 }
 
 nsEventStates
 HTMLInputElement::IntrinsicState() const
 {
   // If you add states here, and they're type-dependent, you need to add them
   // to the type case in AfterSetAttr.
 
-  nsEventStates state = nsGenericHTMLFormElement::IntrinsicState();
+  nsEventStates state = nsGenericHTMLFormElementWithState::IntrinsicState();
   if (mType == NS_FORM_INPUT_CHECKBOX || mType == NS_FORM_INPUT_RADIO) {
     // Check current checked state (:checked)
     if (mChecked) {
       state |= NS_EVENT_STATE_CHECKED;
     }
 
     // Check current indeterminate state (:indeterminate)
     if (mType == NS_FORM_INPUT_CHECKBOX && mIndeterminate) {
@@ -4928,17 +4930,19 @@ HTMLInputElement::WillRemoveFromRadioGro
   // the group validity is updated (with this element being ignored).
   UpdateValueMissingValidityStateForRadio(true);
   container->RemoveFromRadioGroup(name, static_cast<nsIFormControl*>(this));
 }
 
 bool
 HTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, int32_t* aTabIndex)
 {
-  if (nsGenericHTMLFormElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
+  if (nsGenericHTMLFormElementWithState::IsHTMLFocusable(aWithMouse, aIsFocusable,
+      aTabIndex))
+  {
     return true;
   }
 
   if (IsDisabled()) {
     *aIsFocusable = false;
     return true;
   }
 
@@ -5967,17 +5971,17 @@ HTMLInputElement::HasCachedSelection()
 }
 
 void
 HTMLInputElement::FieldSetDisabledChanged(bool aNotify)
 {
   UpdateValueMissingValidityState();
   UpdateBarredFromConstraintValidation();
 
-  nsGenericHTMLFormElement::FieldSetDisabledChanged(aNotify);
+  nsGenericHTMLFormElementWithState::FieldSetDisabledChanged(aNotify);
 }
 
 void
 HTMLInputElement::SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker)
 {
   // We always add |filterAll|
   filePicker->AppendFilters(nsIFilePicker::filterAll);
 
--- a/content/html/content/src/HTMLInputElement.h
+++ b/content/html/content/src/HTMLInputElement.h
@@ -72,30 +72,30 @@ public:
     NS_DECL_NSICONTENTPREFCALLBACK2
 
     nsCOMPtr<nsIFilePicker> mFilePicker;
     nsCOMPtr<nsIFilePickerShownCallback> mFpCallback;
     nsCOMPtr<nsIContentPref> mResult;
   };
 };
 
-class HTMLInputElement MOZ_FINAL : public nsGenericHTMLFormElement,
+class HTMLInputElement MOZ_FINAL : public nsGenericHTMLFormElementWithState,
                                    public nsImageLoadingContent,
                                    public nsIDOMHTMLInputElement,
                                    public nsITextControlElement,
                                    public nsIPhonetic,
                                    public nsIDOMNSEditableElement,
                                    public nsIConstraintValidation
 {
 public:
   using nsIConstraintValidation::GetValidationMessage;
   using nsIConstraintValidation::CheckValidity;
   using nsIConstraintValidation::WillValidate;
   using nsIConstraintValidation::Validity;
-  using nsGenericHTMLFormElement::GetForm;
+  using nsGenericHTMLFormElementWithState::GetForm;
 
   HTMLInputElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                    mozilla::dom::FromParser aFromParser);
   virtual ~HTMLInputElement();
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLInputElement, input)
 
   // nsISupports
@@ -221,17 +221,17 @@ public:
   already_AddRefed<nsIDOMHTMLInputElement> GetSelectedRadioButton();
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   void MaybeFireAsyncClickHandler(nsEventChainPostVisitor& aVisitor);
   NS_IMETHOD FireAsyncClickHandler();
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLInputElement,
-                                           nsGenericHTMLFormElement)
+                                           nsGenericHTMLFormElementWithState)
 
   static UploadLastDir* gUploadLastDir;
   // create and destroy the static UploadLastDir object for remembering
   // which directory was last used on a site-by-site basis
   static void InitUploadLastDir();
   static void DestroyUploadLastDir();
 
   void MaybeLoadImage();
@@ -660,17 +660,17 @@ public:
   // XPCOM GetPhonetic() is OK
 
 protected:
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   // Pull IsSingleLineTextControl into our scope, otherwise it'd be hidden
   // by the nsITextControlElement version.
-  using nsGenericHTMLFormElement::IsSingleLineTextControl;
+  using nsGenericHTMLFormElementWithState::IsSingleLineTextControl;
 
   /**
    * The ValueModeType specifies how the value IDL attribute should behave.
    *
    * See: http://dev.w3.org/html5/spec/forms.html#dom-input-value
    */
   enum ValueModeType
   {
--- a/content/html/content/src/HTMLLegendElement.cpp
+++ b/content/html/content/src/HTMLLegendElement.cpp
@@ -20,40 +20,23 @@ HTMLLegendElement::~HTMLLegendElement()
 }
 
 
 NS_IMPL_ADDREF_INHERITED(HTMLLegendElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLLegendElement, Element)
 
 
 // QueryInterface implementation for HTMLLegendElement
-NS_INTERFACE_TABLE_HEAD(HTMLLegendElement)
+NS_INTERFACE_MAP_BEGIN(HTMLLegendElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
-  NS_INTERFACE_TABLE_INHERITED1(HTMLLegendElement, nsIDOMHTMLLegendElement)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
-// nsIDOMHTMLLegendElement
-
-
 NS_IMPL_ELEMENT_CLONE(HTMLLegendElement)
 
-
-NS_IMETHODIMP
-HTMLLegendElement::GetForm(nsIDOMHTMLFormElement** aForm)
-{
-  Element* form = GetFormElement();
-
-  return form ? CallQueryInterface(form, aForm) : NS_OK;
-}
-
-
-NS_IMPL_STRING_ATTR(HTMLLegendElement, Align, align)
-
 // this contains center, because IE4 does
 static const nsAttrValue::EnumTable kAlignTable[] = {
   { "left", NS_STYLE_TEXT_ALIGN_LEFT },
   { "right", NS_STYLE_TEXT_ALIGN_RIGHT },
   { "center", NS_STYLE_TEXT_ALIGN_CENTER },
   { "bottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
   { "top", NS_STYLE_VERTICAL_ALIGN_TOP },
   { 0 }
--- a/content/html/content/src/HTMLLegendElement.h
+++ b/content/html/content/src/HTMLLegendElement.h
@@ -2,25 +2,24 @@
 /* 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_HTMLLegendElement_h
 #define mozilla_dom_HTMLLegendElement_h
 
 #include "mozilla/Attributes.h"
-#include "nsIDOMHTMLLegendElement.h"
 #include "nsGenericHTMLElement.h"
 #include "mozilla/dom/HTMLFormElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLLegendElement MOZ_FINAL : public nsGenericHTMLElement,
-                                    public nsIDOMHTMLLegendElement
+                                    public nsIDOMHTMLElement
 {
 public:
   HTMLLegendElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLLegendElement();
 
@@ -30,19 +29,16 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
-  // nsIDOMHTMLLegendElement
-  NS_DECL_NSIDOMHTMLLEGENDELEMENT
-
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
   virtual void Focus(ErrorResult& aError) MOZ_OVERRIDE;
 
   virtual void PerformAccesskey(bool aKeyCausesActivation,
                                 bool aIsTrustedEvent) MOZ_OVERRIDE;
 
@@ -81,17 +77,21 @@ public:
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
   /**
    * WebIDL Interface
    */
 
   already_AddRefed<HTMLFormElement> GetForm();
 
-  // The XPCOM GetAlign is OK for us
+  void GetAlign(nsAString& aAlign)
+  {
+    GetHTMLAttr(nsGkAtoms::align, aAlign);
+  }
+
   void SetAlign(const nsAString& aAlign, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
   }
 
   nsINode* GetParentObject() {
     Element* form = GetFormElement();
     return form ? static_cast<nsINode*>(form)
--- a/content/html/content/src/HTMLLinkElement.cpp
+++ b/content/html/content/src/HTMLLinkElement.cpp
@@ -35,20 +35,23 @@ HTMLLinkElement::HTMLLinkElement(already
   , Link(MOZ_THIS_IN_INITIALIZER_LIST())
 {
 }
 
 HTMLLinkElement::~HTMLLinkElement()
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLLinkElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLLinkElement,
                                                   nsGenericHTMLElement)
   tmp->nsStyleLinkElement::Traverse(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLLinkElement,
                                                 nsGenericHTMLElement)
   tmp->nsStyleLinkElement::Unlink();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLLinkElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLLinkElement, Element)
 
--- a/content/html/content/src/HTMLMapElement.cpp
+++ b/content/html/content/src/HTMLMapElement.cpp
@@ -15,16 +15,18 @@ NS_IMPL_NS_NEW_HTML_ELEMENT(Map)
 namespace mozilla {
 namespace dom {
 
 HTMLMapElement::HTMLMapElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLMapElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMapElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAreas)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLMapElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLMapElement, Element)
 
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -397,16 +397,18 @@ NS_IMETHODIMP HTMLMediaElement::MediaLoa
 NS_IMETHODIMP HTMLMediaElement::MediaLoadListener::GetInterface(const nsIID & aIID, void **aResult)
 {
   return QueryInterface(aIID, aResult);
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
 NS_IMPL_RELEASE_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLMediaElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaSource)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSrcStream)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSrcAttrStream)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourcePointer)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoadBlockedDoc)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceLoadCandidate)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioChannelAgent)
--- a/content/html/content/src/HTMLMeterElement.cpp
+++ b/content/html/content/src/HTMLMeterElement.cpp
@@ -24,21 +24,18 @@ HTMLMeterElement::HTMLMeterElement(alrea
 HTMLMeterElement::~HTMLMeterElement()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLMeterElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLMeterElement, Element)
 
 
-NS_INTERFACE_TABLE_HEAD(HTMLMeterElement)
+NS_INTERFACE_MAP_BEGIN(HTMLMeterElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
-  NS_INTERFACE_TABLE_INHERITED1(HTMLMeterElement,
-                                nsIDOMHTMLMeterElement)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLMeterElement)
 
 
 nsEventStates
 HTMLMeterElement::IntrinsicState() const
 {
@@ -218,98 +215,16 @@ HTMLMeterElement::Optimum() const
 
   if (optimum <= min) {
     return min;
   }
 
   return std::min(optimum, max);
 }
 
-/*
- * XPCOM methods
- */
-
-NS_IMETHODIMP
-HTMLMeterElement::GetMin(double* aValue)
-{
-  *aValue = Min();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLMeterElement::SetMin(double aValue)
-{
-  return SetDoubleAttr(nsGkAtoms::min, aValue);
-}
-
-NS_IMETHODIMP
-HTMLMeterElement::GetMax(double* aValue)
-{
-  *aValue = Max();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLMeterElement::SetMax(double aValue)
-{
-  return SetDoubleAttr(nsGkAtoms::max, aValue);
-}
-
-NS_IMETHODIMP
-HTMLMeterElement::GetValue(double* aValue)
-{
-  *aValue = Value();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLMeterElement::SetValue(double aValue)
-{
-  return SetDoubleAttr(nsGkAtoms::value, aValue);
-}
-
-NS_IMETHODIMP
-HTMLMeterElement::GetLow(double* aValue)
-{
-  *aValue = Low();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLMeterElement::SetLow(double aValue)
-{
-  return SetDoubleAttr(nsGkAtoms::low, aValue);
-}
-
-NS_IMETHODIMP
-HTMLMeterElement::GetHigh(double* aValue)
-{
-  *aValue = High();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLMeterElement::SetHigh(double aValue)
-{
-  return SetDoubleAttr(nsGkAtoms::high, aValue);
-}
-
-NS_IMETHODIMP
-HTMLMeterElement::GetOptimum(double* aValue)
-{
-  *aValue = Optimum();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLMeterElement::SetOptimum(double aValue)
-{
-  return SetDoubleAttr(nsGkAtoms::optimum, aValue);
-}
-
 nsEventStates
 HTMLMeterElement::GetOptimumState() const
 {
   /*
    * If the optimum value is in [minimum, low[,
    *     return if the value is in optimal, suboptimal or sub-suboptimal region
    *
    * If the optimum value is in [low, high],
--- a/content/html/content/src/HTMLMeterElement.h
+++ b/content/html/content/src/HTMLMeterElement.h
@@ -2,29 +2,28 @@
 /* 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_HTMLMeterElement_h
 #define mozilla_dom_HTMLMeterElement_h
 
 #include "mozilla/Attributes.h"
-#include "nsIDOMHTMLMeterElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "nsEventStateManager.h"
 #include "nsAlgorithm.h"
 #include <algorithm>
 
 namespace mozilla {
 namespace dom {
 
 class HTMLMeterElement MOZ_FINAL : public nsGenericHTMLElement,
-                                   public nsIDOMHTMLMeterElement
+                                   public nsIDOMHTMLElement
 {
 public:
   HTMLMeterElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~HTMLMeterElement();
 
   /* nsISupports */
   NS_DECL_ISUPPORTS_INHERITED
 
@@ -32,70 +31,67 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   /* nsIDOMElement */
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   /* nsIDOMHTMLElement */
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
-  /* nsIDOMHTMLMeterElement */
-  NS_DECL_NSIDOMHTMLMETERELEMENT
-
   virtual nsEventStates IntrinsicState() const MOZ_OVERRIDE;
 
   nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
 
   bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
                       const nsAString& aValue, nsAttrValue& aResult) MOZ_OVERRIDE;
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
   // WebIDL
 
   /* @return the value */
   double Value() const;
   void SetValue(double aValue, ErrorResult& aRv)
   {
-    aRv = SetValue(aValue);
+    aRv = SetDoubleAttr(nsGkAtoms::value, aValue);
   }
 
   /* @return the minimum value */
   double Min() const;
   void SetMin(double aValue, ErrorResult& aRv)
   {
-    aRv = SetMin(aValue);
+    aRv = SetDoubleAttr(nsGkAtoms::min, aValue);
   }
 
   /* @return the maximum value */
   double Max() const;
   void SetMax(double aValue, ErrorResult& aRv)
   {
-    aRv = SetMax(aValue);
+    aRv = SetDoubleAttr(nsGkAtoms::max, aValue);
   }
 
   /* @return the low value */
   double Low() const;
   void SetLow(double aValue, ErrorResult& aRv)
   {
-    aRv = SetLow(aValue);
+    aRv = SetDoubleAttr(nsGkAtoms::low, aValue);
   }
 
   /* @return the high value */
   double High() const;
   void SetHigh(double aValue, ErrorResult& aRv)
   {
-    aRv = SetHigh(aValue);
+    aRv = SetDoubleAttr(nsGkAtoms::high, aValue);
   }
 
   /* @return the optimum value */
   double Optimum() const;
   void SetOptimum(double aValue, ErrorResult& aRv)
   {
-    aRv = SetOptimum(aValue);
+    aRv = SetDoubleAttr(nsGkAtoms::optimum, aValue);
   }
 
 protected:
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
 private:
 
--- a/content/html/content/src/HTMLModElement.cpp
+++ b/content/html/content/src/HTMLModElement.cpp
@@ -21,30 +21,23 @@ HTMLModElement::~HTMLModElement()
 {
 }
 
 
 NS_IMPL_ADDREF_INHERITED(HTMLModElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLModElement, Element)
 
 // QueryInterface implementation for HTMLModElement
-NS_INTERFACE_TABLE_HEAD(HTMLModElement)
+NS_INTERFACE_MAP_BEGIN(HTMLModElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
-  NS_INTERFACE_TABLE_INHERITED1(HTMLModElement,
-                                nsIDOMHTMLModElement)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLModElement)
 
-
-NS_IMPL_URI_ATTR(HTMLModElement, Cite, cite)
-NS_IMPL_STRING_ATTR(HTMLModElement, DateTime, datetime)
-
 JSObject*
 HTMLModElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return HTMLModElementBinding::Wrap(aCx, aScope, this);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/content/html/content/src/HTMLModElement.h
+++ b/content/html/content/src/HTMLModElement.h
@@ -3,24 +3,23 @@
  * 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_HTMLModElement_h
 #define mozilla_dom_HTMLModElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
-#include "nsIDOMHTMLModElement.h"
 #include "nsGkAtoms.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLModElement MOZ_FINAL : public nsGenericHTMLElement,
-                                 public nsIDOMHTMLModElement
+                                 public nsIDOMHTMLElement
 {
 public:
   HTMLModElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~HTMLModElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
@@ -28,32 +27,32 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
-  // nsIDOMHTMLModElement
-  NS_DECL_NSIDOMHTMLMODELEMENT
-
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
   void GetCite(nsString& aCite)
   {
     GetHTMLURIAttr(nsGkAtoms::cite, aCite);
   }
   void SetCite(const nsAString& aCite, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::cite, aCite, aRv);
   }
-  // XPCOM GetDateTime is fine.
+  void GetDateTime(nsAString& aDateTime)
+  {
+    GetHTMLAttr(nsGkAtoms::datetime, aDateTime);
+  }
   void SetDateTime(const nsAString& aDateTime, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::datetime, aDateTime, aRv);
   }
 
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 };
--- a/content/html/content/src/HTMLObjectElement.cpp
+++ b/content/html/content/src/HTMLObjectElement.cpp
@@ -58,21 +58,24 @@ HTMLObjectElement::DoneAddingChildren(bo
 
   // If we're already in a document, we need to trigger the load
   // Otherwise, BindToTree takes care of that.
   if (IsInDoc()) {
     StartObjectLoad(aHaveNotified);
   }
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLObjectElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLObjectElement,
                                                   nsGenericHTMLFormElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
   nsObjectLoadingContent::Traverse(tmp, cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLObjectElement,
                                                 nsGenericHTMLFormElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLObjectElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLObjectElement, Element)
 
--- a/content/html/content/src/HTMLOutputElement.cpp
+++ b/content/html/content/src/HTMLOutputElement.cpp
@@ -29,16 +29,18 @@ HTMLOutputElement::HTMLOutputElement(alr
 
 HTMLOutputElement::~HTMLOutputElement()
 {
   if (mTokenList) {
     mTokenList->DropReference();
   }
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLOutputElement)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLOutputElement,
                                                 nsGenericHTMLFormElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
   if (tmp->mTokenList) {
     tmp->mTokenList->DropReference();
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mTokenList)
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@@ -48,39 +50,30 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTokenList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLOutputElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLOutputElement, Element)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLOutputElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElement)
-  NS_INTERFACE_TABLE_INHERITED3(HTMLOutputElement,
-                                nsIDOMHTMLOutputElement,
+  NS_INTERFACE_TABLE_INHERITED2(HTMLOutputElement,
                                 nsIMutationObserver,
                                 nsIConstraintValidation)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLOutputElement)
 
-
-NS_IMPL_STRING_ATTR(HTMLOutputElement, Name, name)
-
-// nsIConstraintValidation
-NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(HTMLOutputElement)
-
-NS_IMETHODIMP
+void
 HTMLOutputElement::SetCustomValidity(const nsAString& aError)
 {
   nsIConstraintValidation::SetCustomValidity(aError);
 
   UpdateState(true);
-
-  return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLOutputElement::Reset()
 {
   mValueModeFlag = eModeDefault;
   return nsContentUtils::SetNodeTextContent(this, mDefaultValue, true);
 }
@@ -144,77 +137,41 @@ HTMLOutputElement::BindToTree(nsIDocumen
   // might end up a in a novalidate form, and unlike other form
   // controls that on its own is enough to make change ui-valid state.
   // So just go ahead and update our state now.
   UpdateState(false);
 
   return rv;
 }
 
-NS_IMETHODIMP
-HTMLOutputElement::GetForm(nsIDOMHTMLFormElement** aForm)
+void
+HTMLOutputElement::SetValue(const nsAString& aValue, ErrorResult& aRv)
 {
-  return nsGenericHTMLFormElement::GetForm(aForm);
-}
-
-NS_IMETHODIMP
-HTMLOutputElement::GetType(nsAString& aType)
-{
-  aType.AssignLiteral("output");
-  return NS_OK;
+  mValueModeFlag = eModeValue;
+  aRv = nsContentUtils::SetNodeTextContent(this, aValue, true);
 }
 
-NS_IMETHODIMP
-HTMLOutputElement::GetValue(nsAString& aValue)
-{
-  nsContentUtils::GetNodeTextContent(this, true, aValue);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLOutputElement::SetValue(const nsAString& aValue)
-{
-  mValueModeFlag = eModeValue;
-  return nsContentUtils::SetNodeTextContent(this, aValue, true);
-}
-
-NS_IMETHODIMP
-HTMLOutputElement::GetDefaultValue(nsAString& aDefaultValue)
-{
-  aDefaultValue = mDefaultValue;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue)
+void
+HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aRv)
 {
   mDefaultValue = aDefaultValue;
   if (mValueModeFlag == eModeDefault) {
-    return nsContentUtils::SetNodeTextContent(this, mDefaultValue, true);
+    aRv = nsContentUtils::SetNodeTextContent(this, mDefaultValue, true);
   }
-
-  return NS_OK;
 }
 
 nsDOMSettableTokenList*
 HTMLOutputElement::HtmlFor()
 {
   if (!mTokenList) {
     mTokenList = new nsDOMSettableTokenList(this, nsGkAtoms::_for);
   }
   return mTokenList;
 }
 
-NS_IMETHODIMP
-HTMLOutputElement::GetHtmlFor(nsISupports** aResult)
-{
-  NS_ADDREF(*aResult = HtmlFor());
-  return NS_OK;
-}
-
 void HTMLOutputElement::DescendantsChanged()
 {
   if (mValueModeFlag == eModeDefault) {
     nsContentUtils::GetNodeTextContent(this, true, mDefaultValue);
   }
 }
 
 // nsIMutationObserver
--- a/content/html/content/src/HTMLOutputElement.h
+++ b/content/html/content/src/HTMLOutputElement.h
@@ -3,25 +3,24 @@
  * 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_HTMLOutputElement_h
 #define mozilla_dom_HTMLOutputElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
-#include "nsIDOMHTMLOutputElement.h"
 #include "nsStubMutationObserver.h"
 #include "nsIConstraintValidation.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLOutputElement MOZ_FINAL : public nsGenericHTMLFormElement,
-                                    public nsIDOMHTMLOutputElement,
+                                    public nsIDOMHTMLElement,
                                     public nsStubMutationObserver,
                                     public nsIConstraintValidation
 {
 public:
   using nsIConstraintValidation::GetValidationMessage;
 
   HTMLOutputElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~HTMLOutputElement();
@@ -33,19 +32,16 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
-  // nsIDOMHTMLOutputElement
-  NS_DECL_NSIDOMHTMLOUTPUTELEMENT
-
   // nsIFormControl
   NS_IMETHOD_(uint32_t) GetType() const { return NS_FORM_OUTPUT; }
   NS_IMETHOD Reset() MOZ_OVERRIDE;
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission) MOZ_OVERRIDE;
 
   virtual bool IsDisabled() const MOZ_OVERRIDE { return false; }
 
   nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
@@ -74,41 +70,50 @@ public:
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   // WebIDL
   nsDOMSettableTokenList* HtmlFor();
   // nsGenericHTMLFormElement::GetForm is fine.
-  using nsGenericHTMLFormElement::GetForm;
-  // XPCOM GetName is fine.
+  void GetName(nsAString& aName)
+  {
+    GetHTMLAttr(nsGkAtoms::name, aName);
+  }
+
   void SetName(const nsAString& aName, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::name, aName, aRv);
   }
 
-  // XPCOM GetType is fine.
-  // XPCOM GetDefaultValue is fine.
-  void SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aRv)
+  void GetType(nsAString& aType)
   {
-    aRv = SetDefaultValue(aDefaultValue);
+    aType.AssignLiteral("output");
+  }
+
+  void GetDefaultValue(nsAString& aDefaultValue)
+  {
+    aDefaultValue = mDefaultValue;
   }
-  // XPCOM GetValue is fine.
-  void SetValue(const nsAString& aValue, ErrorResult& aRv)
+
+  void SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aRv);
+
+  void GetValue(nsAString& aValue)
   {
-    aRv = SetValue(aValue);
+    nsContentUtils::GetNodeTextContent(this, true, aValue);
   }
 
+  void SetValue(const nsAString& aValue, ErrorResult& aRv);
+
   // nsIConstraintValidation::WillValidate is fine.
   // nsIConstraintValidation::Validity() is fine.
   // nsIConstraintValidation::GetValidationMessage() is fine.
   // nsIConstraintValidation::CheckValidity() is fine.
-  using nsIConstraintValidation::CheckValidity;
-  // nsIConstraintValidation::SetCustomValidity() is fine.
+  void SetCustomValidity(const nsAString& aError);
 
 protected:
   enum ValueModeFlag {
     eModeDefault,
     eModeValue
   };
 
   ValueModeFlag                     mValueModeFlag;
--- a/content/html/content/src/HTMLProgressElement.cpp
+++ b/content/html/content/src/HTMLProgressElement.cpp
@@ -26,21 +26,18 @@ HTMLProgressElement::HTMLProgressElement
 HTMLProgressElement::~HTMLProgressElement()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLProgressElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLProgressElement, Element)
 
 
-NS_INTERFACE_TABLE_HEAD(HTMLProgressElement)
+NS_INTERFACE_MAP_BEGIN(HTMLProgressElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
-  NS_INTERFACE_TABLE_INHERITED1(HTMLProgressElement,
-                                nsIDOMHTMLProgressElement)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLProgressElement)
 
 
 nsEventStates
 HTMLProgressElement::IntrinsicState() const
 {
@@ -62,77 +59,40 @@ HTMLProgressElement::ParseAttribute(int3
       return aResult.ParseDoubleValue(aValue);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute,
                                               aValue, aResult);
 }
 
-NS_IMETHODIMP
-HTMLProgressElement::GetValue(double* aValue)
-{
-  *aValue = Value();
-  return NS_OK;
-}
-
 double
 HTMLProgressElement::Value() const
 {
   const nsAttrValue* attrValue = mAttrsAndChildren.GetAttr(nsGkAtoms::value);
   if (!attrValue || attrValue->Type() != nsAttrValue::eDoubleValue ||
       attrValue->GetDoubleValue() < 0.0) {
     return kDefaultValue;
   }
 
   return std::min(attrValue->GetDoubleValue(), Max());
 }
 
-NS_IMETHODIMP
-HTMLProgressElement::SetValue(double aValue)
-{
-  ErrorResult rv;
-  SetValue(aValue, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLProgressElement::GetMax(double* aValue)
-{
-  *aValue = Max();
-  return NS_OK;
-}
-
 double
 HTMLProgressElement::Max() const
 {
   const nsAttrValue* attrMax = mAttrsAndChildren.GetAttr(nsGkAtoms::max);
   if (!attrMax || attrMax->Type() != nsAttrValue::eDoubleValue ||
       attrMax->GetDoubleValue() <= 0.0) {
     return kDefaultMax;
   }
 
   return attrMax->GetDoubleValue();
 }
 
-NS_IMETHODIMP
-HTMLProgressElement::SetMax(double aValue)
-{
-  ErrorResult rv;
-  SetMax(aValue, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLProgressElement::GetPosition(double* aPosition)
-{
-  *aPosition = Position();
-  return NS_OK;
-}
-
 double
 HTMLProgressElement::Position() const
 {
   if (IsIndeterminate()) {
     return kIndeterminatePosition;
   }
 
   return Value() / Max();
--- a/content/html/content/src/HTMLProgressElement.h
+++ b/content/html/content/src/HTMLProgressElement.h
@@ -2,28 +2,27 @@
 /* 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_HTMLProgressElement_h
 #define mozilla_dom_HTMLProgressElement_h
 
 #include "mozilla/Attributes.h"
-#include "nsIDOMHTMLProgressElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "nsEventStateManager.h"
 #include <algorithm>
 
 namespace mozilla {
 namespace dom {
 
 class HTMLProgressElement MOZ_FINAL : public nsGenericHTMLElement,
-                                      public nsIDOMHTMLProgressElement
+                                      public nsIDOMHTMLElement
 {
 public:
   HTMLProgressElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~HTMLProgressElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
@@ -31,19 +30,16 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
-  // nsIDOMHTMLProgressElement
-  NS_DECL_NSIDOMHTMLPROGRESSELEMENT
-
   nsEventStates IntrinsicState() const MOZ_OVERRIDE;
 
   nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
 
   bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
                         const nsAString& aValue, nsAttrValue& aResult) MOZ_OVERRIDE;
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
--- a/content/html/content/src/HTMLPropertiesCollection.cpp
+++ b/content/html/content/src/HTMLPropertiesCollection.cpp
@@ -12,16 +12,18 @@
 #include "nsDOMSettableTokenList.h"
 #include "nsAttrValue.h"
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/dom/HTMLPropertiesCollectionBinding.h"
 
 namespace mozilla {
 namespace dom {
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLPropertiesCollection)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(HTMLPropertiesCollection)
   // SetDocument(nullptr) ensures that we remove ourselves as a mutation observer
   tmp->SetDocument(nullptr);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNames)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNamedItemEntries)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mProperties)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
@@ -400,16 +402,18 @@ PropertyNodeList::GetParentObject()
 }
 
 JSObject*
 PropertyNodeList::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope)
 {
   return PropertyNodeListBinding::Wrap(cx, scope, this);
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(PropertyNodeList)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PropertyNodeList)
   // SetDocument(nullptr) ensures that we remove ourselves as a mutation observer
   tmp->SetDocument(nullptr);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCollection)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mElements)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/html/content/src/HTMLSelectElement.cpp
+++ b/content/html/content/src/HTMLSelectElement.cpp
@@ -98,17 +98,17 @@ SafeOptionListMutation::~SafeOptionListM
 // HTMLSelectElement
 //
 
 // construction, destruction
 
 
 HTMLSelectElement::HTMLSelectElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                                      FromParser aFromParser)
-  : nsGenericHTMLFormElement(aNodeInfo),
+  : nsGenericHTMLFormElementWithState(aNodeInfo),
     mOptions(new HTMLOptionsCollection(MOZ_THIS_IN_INITIALIZER_LIST())),
     mIsDoneAddingChildren(!aFromParser),
     mDisabledChanged(false),
     mMutating(false),
     mInhibitStateRestoration(!!(aFromParser & FROM_PARSER_FRAGMENT)),
     mSelectionHasChanged(false),
     mDefaultSelectionSet(false),
     mCanShowInvalidUI(true),
@@ -128,32 +128,34 @@ HTMLSelectElement::HTMLSelectElement(alr
 
 HTMLSelectElement::~HTMLSelectElement()
 {
   mOptions->DropReference();
 }
 
 // ISupports
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLSelectElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLSelectElement,
-                                                  nsGenericHTMLFormElement)
+                                                  nsGenericHTMLFormElementWithState)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOptions)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLSelectElement,
-                                                nsGenericHTMLFormElement)
+                                                nsGenericHTMLFormElementWithState)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLSelectElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLSelectElement, Element)
 
 // QueryInterface implementation for HTMLSelectElement
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLSelectElement)
-  NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElement)
+  NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElementWithState)
   NS_INTERFACE_TABLE_INHERITED2(HTMLSelectElement,
                                 nsIDOMHTMLSelectElement,
                                 nsIConstraintValidation)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 // nsIDOMHTMLSelectElement
@@ -172,37 +174,38 @@ HTMLSelectElement::SetCustomValidity(con
   UpdateState(true);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLSelectElement::GetForm(nsIDOMHTMLFormElement** aForm)
 {
-  return nsGenericHTMLFormElement::GetForm(aForm);
+  return nsGenericHTMLFormElementWithState::GetForm(aForm);
 }
 
 nsresult
 HTMLSelectElement::InsertChildAt(nsIContent* aKid,
                                  uint32_t aIndex,
                                  bool aNotify)
 {
   SafeOptionListMutation safeMutation(this, this, aKid, aIndex, aNotify);
-  nsresult rv = nsGenericHTMLFormElement::InsertChildAt(aKid, aIndex, aNotify);
+  nsresult rv = nsGenericHTMLFormElementWithState::InsertChildAt(aKid, aIndex,
+                                                                 aNotify);
   if (NS_FAILED(rv)) {
     safeMutation.MutationFailed();
   }
   return rv;
 }
 
 void
 HTMLSelectElement::RemoveChildAt(uint32_t aIndex, bool aNotify)
 {
   SafeOptionListMutation safeMutation(this, this, nullptr, aIndex, aNotify);
-  nsGenericHTMLFormElement::RemoveChildAt(aIndex, aNotify);
+  nsGenericHTMLFormElementWithState::RemoveChildAt(aIndex, aNotify);
 }
 
 
 
 void
 HTMLSelectElement::InsertOptionsIntoList(nsIContent* aOptions,
                                          int32_t aListIndex,
                                          int32_t aDepth,
@@ -1169,17 +1172,19 @@ HTMLSelectElement::TabIndexDefault()
 {
   return 0;
 }
 
 bool
 HTMLSelectElement::IsHTMLFocusable(bool aWithMouse,
                                    bool* aIsFocusable, int32_t* aTabIndex)
 {
-  if (nsGenericHTMLFormElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
+  if (nsGenericHTMLFormElementWithState::IsHTMLFocusable(aWithMouse, aIsFocusable,
+      aTabIndex))
+  {
     return true;
   }
 
   *aIsFocusable = !IsDisabled();
 
   return false;
 }
 
@@ -1234,19 +1239,19 @@ HTMLSelectElement::SelectSomething(bool 
   return false;
 }
 
 nsresult
 HTMLSelectElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers)
 {
-  nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
-                                                     aBindingParent,
-                                                     aCompileEventHandlers);
+  nsresult rv = nsGenericHTMLFormElementWithState::BindToTree(aDocument, aParent,
+                                                              aBindingParent,
+                                                              aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If there is a disabled fieldset in the parent chain, the element is now
   // barred from constraint validation.
   // XXXbz is this still needed now that fieldset changes always call
   // FieldSetDisabledChanged?
   UpdateBarredFromConstraintValidation();
 
@@ -1254,17 +1259,17 @@ HTMLSelectElement::BindToTree(nsIDocumen
   UpdateState(false);
 
   return rv;
 }
 
 void
 HTMLSelectElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
-  nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
+  nsGenericHTMLFormElementWithState::UnbindFromTree(aDeep, aNullParent);
 
   // We might be no longer disabled because our parent chain changed.
   // XXXbz is this still needed now that fieldset changes always call
   // FieldSetDisabledChanged?
   UpdateBarredFromConstraintValidation();
 
   // And now make sure our state is up to date
   UpdateState(false);
@@ -1275,36 +1280,36 @@ HTMLSelectElement::BeforeSetAttr(int32_t
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify)
 {
   if (aNotify && aName == nsGkAtoms::disabled &&
       aNameSpaceID == kNameSpaceID_None) {
     mDisabledChanged = true;
   }
 
-  return nsGenericHTMLFormElement::BeforeSetAttr(aNameSpaceID, aName,
-                                                 aValue, aNotify);
+  return nsGenericHTMLFormElementWithState::BeforeSetAttr(aNameSpaceID, aName,
+                                                          aValue, aNotify);
 }
 
 nsresult
 HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue, bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::disabled) {
       UpdateBarredFromConstraintValidation();
     } else if (aName == nsGkAtoms::required) {
       UpdateValueMissingValidityState();
     }
 
     UpdateState(aNotify);
   }
 
-  return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
-                                                aValue, aNotify);
+  return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
+                                                         aValue, aNotify);
 }
 
 nsresult
 HTMLSelectElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify)
 {
   if (aNotify && aNameSpaceID == kNameSpaceID_None &&
       aAttribute == nsGkAtoms::multiple) {
@@ -1314,18 +1319,18 @@ HTMLSelectElement::UnsetAttr(int32_t aNa
     // since SetOptionsSelectedByIndex does some bail-out type
     // optimization for cases when the select is not multiple that
     // would lead to only a single option getting deselected.
     if (mSelectedIndex >= 0) {
       SetSelectedIndexInternal(mSelectedIndex, aNotify);
     }
   }
 
-  nsresult rv = nsGenericHTMLFormElement::UnsetAttr(aNameSpaceID, aAttribute,
-                                                    aNotify);
+  nsresult rv = nsGenericHTMLFormElementWithState::UnsetAttr(aNameSpaceID, aAttribute,
+                                                             aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aNotify && aNameSpaceID == kNameSpaceID_None &&
       aAttribute == nsGkAtoms::multiple) {
     // We might have become a combobox; make sure _something_ gets
     // selected in that case
     CheckSelectSomething(aNotify);
   }
@@ -1347,19 +1352,21 @@ HTMLSelectElement::DoneAddingChildren(bo
     mRestoreState = nullptr;
   }
 
   // Notify the frame
   if (selectFrame) {
     selectFrame->DoneAddingChildren(true);
   }
 
-  // Restore state
   if (!mInhibitStateRestoration) {
-    RestoreFormControlState(this, this);
+    nsresult rv = GenerateStateKey();
+    if (NS_SUCCEEDED(rv)) {
+      RestoreFormControlState();
+    }
   }
 
   // Now that we're done, select something (if it's a single select something
   // must be selected)
   if (!CheckSelectSomething(false)) {
     // If an option has @selected set, it will be selected during parsing but
     // with an empty value. We have to make sure the select element updates it's
     // validity state to take this into account.
@@ -1384,26 +1391,26 @@ HTMLSelectElement::ParseAttribute(int32_
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 static void
 MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                       nsRuleData* aData)
 {
-  nsGenericHTMLFormElement::MapImageAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLFormElementWithState::MapImageAlignAttributeInto(aAttributes, aData);
+  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
 }
 
 nsChangeHint
 HTMLSelectElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                           int32_t aModType) const
 {
   nsChangeHint retval =
-      nsGenericHTMLFormElement::GetAttributeChangeHint(aAttribute, aModType);
+      nsGenericHTMLFormElementWithState::GetAttributeChangeHint(aAttribute, aModType);
   if (aAttribute == nsGkAtoms::multiple ||
       aAttribute == nsGkAtoms::size) {
     NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
   }
   return retval;
 }
 
 NS_IMETHODIMP_(bool)
@@ -1437,17 +1444,17 @@ HTMLSelectElement::IsDisabledForEvents(u
 nsresult
 HTMLSelectElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   aVisitor.mCanHandle = false;
   if (IsDisabledForEvents(aVisitor.mEvent->message)) {
     return NS_OK;
   }
 
-  return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
+  return nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor);
 }
 
 nsresult
 HTMLSelectElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
   if (aVisitor.mEvent->message == NS_FOCUS_CONTENT) {
     // If the invalid UI is shown, we should show it while focused and
     // update the invalid/valid UI.
@@ -1461,23 +1468,23 @@ HTMLSelectElement::PostHandleEvent(nsEve
     // NS_EVENT_STATE_MOZ_UI_VALID given that the states should not change.
   } else if (aVisitor.mEvent->message == NS_BLUR_CONTENT) {
     mCanShowInvalidUI = true;
     mCanShowValidUI = true;
 
     UpdateState(true);
   }
 
-  return nsGenericHTMLFormElement::PostHandleEvent(aVisitor);
+  return nsGenericHTMLFormElementWithState::PostHandleEvent(aVisitor);
 }
 
 nsEventStates
 HTMLSelectElement::IntrinsicState() const
 {
-  nsEventStates state = nsGenericHTMLFormElement::IntrinsicState();
+  nsEventStates state = nsGenericHTMLFormElementWithState::IntrinsicState();
 
   if (IsCandidateForConstraintValidation()) {
     if (IsValid()) {
       state |= NS_EVENT_STATE_VALID;
     } else {
       state |= NS_EVENT_STATE_INVALID;
 
       if ((!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) &&
@@ -1828,17 +1835,17 @@ HTMLSelectElement::UpdateBarredFromConst
   SetBarredFromConstraintValidation(IsDisabled());
 }
 
 void
 HTMLSelectElement::FieldSetDisabledChanged(bool aNotify)
 {
   UpdateBarredFromConstraintValidation();
 
-  nsGenericHTMLFormElement::FieldSetDisabledChanged(aNotify);
+  nsGenericHTMLFormElementWithState::FieldSetDisabledChanged(aNotify);
 }
 
 void
 HTMLSelectElement::SetSelectionChanged(bool aValue, bool aNotify)
 {
   if (!mDefaultSelectionSet) {
     return;
   }
--- a/content/html/content/src/HTMLSelectElement.h
+++ b/content/html/content/src/HTMLSelectElement.h
@@ -98,17 +98,17 @@ private:
   /** Option list must be recreated if more than one mutation is detected. */
   nsMutationGuard            mGuard;
 };
 
 
 /**
  * Implementation of &lt;select&gt;
  */
-class HTMLSelectElement MOZ_FINAL : public nsGenericHTMLFormElement,
+class HTMLSelectElement MOZ_FINAL : public nsGenericHTMLFormElementWithState,
                                     public nsIDOMHTMLSelectElement,
                                     public nsIConstraintValidation
 {
 public:
   using nsIConstraintValidation::GetValidationMessage;
 
   HTMLSelectElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                     FromParser aFromParser = NOT_FROM_PARSER);
@@ -147,17 +147,17 @@ public:
     return GetBoolAttr(nsGkAtoms::disabled);
   }
   void SetDisabled(bool aVal, ErrorResult& aRv)
   {
     SetHTMLBoolAttr(nsGkAtoms::disabled, aVal, aRv);
   }
   HTMLFormElement* GetForm() const
   {
-    return nsGenericHTMLFormElement::GetForm();
+    return nsGenericHTMLFormElementWithState::GetForm();
   }
   bool Multiple() const
   {
     return GetBoolAttr(nsGkAtoms::multiple);
   }
   void SetMultiple(bool aVal, ErrorResult& aRv)
   {
     SetHTMLBoolAttr(nsGkAtoms::multiple, aVal, aRv);
@@ -364,17 +364,17 @@ public:
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               int32_t aModType) const MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
 
   virtual nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLSelectElement,
-                                           nsGenericHTMLFormElement)
+                                           nsGenericHTMLFormElementWithState)
 
   HTMLOptionsCollection* GetOptions()
   {
     return mOptions;
   }
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
--- a/content/html/content/src/HTMLSharedElement.cpp
+++ b/content/html/content/src/HTMLSharedElement.cpp
@@ -29,38 +29,28 @@ HTMLSharedElement::~HTMLSharedElement()
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLSharedElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLSharedElement, Element)
 
 // QueryInterface implementation for HTMLSharedElement
 NS_INTERFACE_MAP_BEGIN(HTMLSharedElement)
   NS_HTML_CONTENT_INTERFACES_AMBIGUOUS(nsGenericHTMLElement,
-                                       nsIDOMHTMLParamElement)
-  NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLParamElement, param)
+                                       nsIDOMHTMLBaseElement)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLBaseElement, base)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLDirectoryElement, dir)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLQuoteElement, q)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLQuoteElement, blockquote)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLHeadElement, head)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLHtmlElement, html)
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLSharedElement)
 
-// nsIDOMHTMLParamElement
-NS_IMPL_STRING_ATTR(HTMLSharedElement, Name, name)
-NS_IMPL_STRING_ATTR(HTMLSharedElement, Type, type)
-NS_IMPL_STRING_ATTR(HTMLSharedElement, Value, value)
-NS_IMPL_STRING_ATTR(HTMLSharedElement, ValueType, valuetype)
-
-// nsIDOMHTMLDirectoryElement
-NS_IMPL_BOOL_ATTR(HTMLSharedElement, Compact, compact)
-
 // nsIDOMHTMLQuoteElement
 NS_IMPL_URI_ATTR(HTMLSharedElement, Cite, cite)
 
 // nsIDOMHTMLHeadElement
 // Empty
 
 // nsIDOMHTMLHtmlElement
 NS_IMPL_STRING_ATTR(HTMLSharedElement, Version, version)
--- a/content/html/content/src/HTMLSharedElement.h
+++ b/content/html/content/src/HTMLSharedElement.h
@@ -1,34 +1,32 @@
 /* -*- 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_HTMLSharedElement_h
 #define mozilla_dom_HTMLSharedElement_h
 
-#include "nsIDOMHTMLParamElement.h"
 #include "nsIDOMHTMLBaseElement.h"
 #include "nsIDOMHTMLDirectoryElement.h"
 #include "nsIDOMHTMLQuoteElement.h"
 #include "nsIDOMHTMLHeadElement.h"
 #include "nsIDOMHTMLHtmlElement.h"
 #include "nsGenericHTMLElement.h"
 
 #include "nsGkAtoms.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/Assertions.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLSharedElement MOZ_FINAL : public nsGenericHTMLElement,
-                                    public nsIDOMHTMLParamElement,
                                     public nsIDOMHTMLBaseElement,
                                     public nsIDOMHTMLDirectoryElement,
                                     public nsIDOMHTMLQuoteElement,
                                     public nsIDOMHTMLHeadElement,
                                     public nsIDOMHTMLHtmlElement
 {
 public:
   HTMLSharedElement(already_AddRefed<nsINodeInfo> aNodeInfo)
@@ -44,25 +42,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
-  // nsIDOMHTMLParamElement
-  NS_DECL_NSIDOMHTMLPARAMELEMENT
-
   // nsIDOMHTMLBaseElement
   NS_DECL_NSIDOMHTMLBASEELEMENT
 
-  // nsIDOMHTMLDirectoryElement
-  NS_DECL_NSIDOMHTMLDIRECTORYELEMENT
-
   // nsIDOMHTMLQuoteElement
   NS_DECL_NSIDOMHTMLQUOTEELEMENT
 
   // nsIDOMHTMLHeadElement
   NS_DECL_NSIDOMHTMLHEADELEMENT
 
   // nsIDOMHTMLHtmlElement
   NS_DECL_NSIDOMHTMLHTMLELEMENT
@@ -93,17 +85,17 @@ public:
 
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE
   {
-    return static_cast<nsIDOMHTMLParamElement*>(this);
+    return static_cast<nsIDOMHTMLBaseElement*>(this);
   }
 
   // WebIDL API
   // HTMLParamElement
   void GetName(DOMString& aValue)
   {
     MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::param));
     GetHTMLAttr(nsGkAtoms::name, aValue);
--- a/content/html/content/src/HTMLSharedListElement.cpp
+++ b/content/html/content/src/HTMLSharedListElement.cpp
@@ -27,17 +27,16 @@ HTMLSharedListElement::~HTMLSharedListEl
 NS_IMPL_ADDREF_INHERITED(HTMLSharedListElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLSharedListElement, Element)
 
 // QueryInterface implementation for nsHTMLSharedListElement
 NS_INTERFACE_MAP_BEGIN(HTMLSharedListElement)
   NS_HTML_CONTENT_INTERFACES_AMBIGUOUS(nsGenericHTMLElement,
                                        nsIDOMHTMLOListElement)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLOListElement, ol)
-  NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLDListElement, dl)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLUListElement, ul)
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLSharedListElement)
 
 
 NS_IMPL_BOOL_ATTR(HTMLSharedListElement, Compact, compact)
--- a/content/html/content/src/HTMLSharedListElement.h
+++ b/content/html/content/src/HTMLSharedListElement.h
@@ -4,26 +4,24 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_HTMLSharedListElement_h
 #define mozilla_dom_HTMLSharedListElement_h
 #include "mozilla/Attributes.h"
 #include "mozilla/Util.h"
 
 #include "nsIDOMHTMLOListElement.h"
-#include "nsIDOMHTMLDListElement.h"
 #include "nsIDOMHTMLUListElement.h"
 #include "nsGenericHTMLElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLSharedListElement MOZ_FINAL : public nsGenericHTMLElement,
                                         public nsIDOMHTMLOListElement,
-                                        public nsIDOMHTMLDListElement,
                                         public nsIDOMHTMLUListElement
 {
 public:
   HTMLSharedListElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLSharedListElement();
@@ -38,19 +36,16 @@ public:
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
   // nsIDOMHTMLOListElement
   NS_DECL_NSIDOMHTMLOLISTELEMENT
 
-  // nsIDOMHTMLDListElement
-  // fully declared by NS_DECL_NSIDOMHTMLOLISTELEMENT
-
   // nsIDOMHTMLUListElement
   // fully declared by NS_DECL_NSIDOMHTMLOLISTELEMENT
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) MOZ_OVERRIDE;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
--- a/content/html/content/src/HTMLSharedObjectElement.cpp
+++ b/content/html/content/src/HTMLSharedObjectElement.cpp
@@ -75,16 +75,18 @@ HTMLSharedObjectElement::DoneAddingChild
     // If we're already in a document, we need to trigger the load
     // Otherwise, BindToTree takes care of that.
     if (IsInDoc()) {
       StartObjectLoad(aHaveNotified);
     }
   }
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLSharedObjectElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLSharedObjectElement,
                                                   nsGenericHTMLElement)
   nsObjectLoadingContent::Traverse(tmp, cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLSharedObjectElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLSharedObjectElement, Element)
 
--- a/content/html/content/src/HTMLStyleElement.cpp
+++ b/content/html/content/src/HTMLStyleElement.cpp
@@ -26,20 +26,23 @@ HTMLStyleElement::HTMLStyleElement(alrea
 {
   AddMutationObserver(this);
 }
 
 HTMLStyleElement::~HTMLStyleElement()
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLStyleElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLStyleElement,
                                                   nsGenericHTMLElement)
   tmp->nsStyleLinkElement::Traverse(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLStyleElement,
                                                 nsGenericHTMLElement)
   tmp->nsStyleLinkElement::Unlink();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLStyleElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLStyleElement, Element)
 
--- a/content/html/content/src/HTMLTableColElement.cpp
+++ b/content/html/content/src/HTMLTableColElement.cpp
@@ -29,125 +29,22 @@ HTMLTableColElement::WrapNode(JSContext 
 {
   return HTMLTableColElementBinding::Wrap(aCx, aScope, this);
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLTableColElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTableColElement, Element)
 
 // QueryInterface implementation for HTMLTableColElement
-NS_INTERFACE_TABLE_HEAD(HTMLTableColElement)
+NS_INTERFACE_MAP_BEGIN(HTMLTableColElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
-  NS_INTERFACE_TABLE_INHERITED1(HTMLTableColElement,
-                                nsIDOMHTMLTableColElement)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableColElement)
 
-NS_IMETHODIMP
-HTMLTableColElement::SetSpan(int32_t aSpan)
-{
-  ErrorResult rv;
-  SetSpan(aSpan, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableColElement::GetSpan(int32_t* aSpan)
-{
-  *aSpan = Span();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableColElement::SetAlign(const nsAString& aAlign)
-{
-  ErrorResult rv;
-  SetAlign(aAlign, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableColElement::GetAlign(nsAString& aAlign)
-{
-  nsString align;
-  GetAlign(align);
-  aAlign = align;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableColElement::SetVAlign(const nsAString& aVAlign)
-{
-  ErrorResult rv;
-  SetVAlign(aVAlign, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableColElement::GetVAlign(nsAString& aVAlign)
-{
-  nsString vAlign;
-  GetVAlign(vAlign);
-  aVAlign = vAlign;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableColElement::SetCh(const nsAString& aCh)
-{
-  ErrorResult rv;
-  SetCh(aCh, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableColElement::GetCh(nsAString& aCh)
-{
-  nsString ch;
-  GetCh(ch);
-  aCh = ch;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableColElement::SetChOff(const nsAString& aChOff)
-{
-  ErrorResult rv;
-  SetChOff(aChOff, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableColElement::GetChOff(nsAString& aChOff)
-{
-  nsString chOff;
-  GetChOff(chOff);
-  aChOff = chOff;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableColElement::SetWidth(const nsAString& aWidth)
-{
-  ErrorResult rv;
-  SetWidth(aWidth, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableColElement::GetWidth(nsAString& aWidth)
-{
-  nsString width;
-  GetWidth(width);
-  aWidth = width;
-  return NS_OK;
-}
-
 bool
 HTMLTableColElement::ParseAttribute(int32_t aNamespaceID,
                                     nsIAtom* aAttribute,
                                     const nsAString& aValue,
                                     nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     /* ignore these attributes, stored simply as strings ch */
--- a/content/html/content/src/HTMLTableColElement.h
+++ b/content/html/content/src/HTMLTableColElement.h
@@ -2,23 +2,22 @@
 /* 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_HTMLTableColElement_h
 #define mozilla_dom_HTMLTableColElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
-#include "nsIDOMHTMLTableColElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLTableColElement MOZ_FINAL : public nsGenericHTMLElement,
-                                      public nsIDOMHTMLTableColElement
+                                      public nsIDOMHTMLElement
 {
 public:
   HTMLTableColElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLTableColElement();
 
@@ -29,19 +28,16 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
-  // nsIDOMHTMLTableColElement
-  NS_DECL_NSIDOMHTMLTABLECOLELEMENT
-
   uint32_t Span() const
   {
     return GetIntAttr(nsGkAtoms::span, 1);
   }
   void SetSpan(uint32_t aSpan, ErrorResult& aError)
   {
     SetHTMLIntAttr(nsGkAtoms::span, aSpan, aError);
   }
--- a/content/html/content/src/HTMLTableElement.cpp
+++ b/content/html/content/src/HTMLTableElement.cpp
@@ -1,17 +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 "mozilla/Util.h"
 
 #include "mozilla/dom/HTMLTableElement.h"
-#include "nsIDOMHTMLTableSectionElement.h"
 #include "nsAttrValueInlines.h"
 #include "nsRuleData.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsMappedAttributes.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/HTMLCollectionBinding.h"
 #include "mozilla/dom/HTMLTableElementBinding.h"
 #include "nsContentUtils.h"
@@ -308,16 +307,18 @@ HTMLTableElement::~HTMLTableElement()
 }
 
 JSObject*
 HTMLTableElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aScope)
 {
   return HTMLTableElementBinding::Wrap(aCx, aScope, this);
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLTableElement)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLTableElement, nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTBodies)
   if (tmp->mRows) {
     tmp->mRows->ParentDestroyed();
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRows)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLTableElement,
@@ -339,246 +340,26 @@ NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableElement)
 
 
 // the DOM spec says border, cellpadding, cellSpacing are all "wstring"
 // in fact, they are integers or they are meaningless.  so we store them
 // here as ints.
 
-NS_IMETHODIMP
-HTMLTableElement::SetAlign(const nsAString& aAlign)
-{
-  ErrorResult rv;
-  SetAlign(aAlign, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableElement::GetAlign(nsAString& aAlign)
-{
-  nsString align;
-  GetAlign(align);
-  aAlign = align;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableElement::SetBgColor(const nsAString& aBgColor)
-{
-  ErrorResult rv;
-  SetBgColor(aBgColor, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableElement::GetBgColor(nsAString& aBgColor)
-{
-  nsString bgColor;
-  GetBgColor(bgColor);
-  aBgColor = bgColor;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableElement::SetBorder(const nsAString& aBorder)
-{
-  ErrorResult rv;
-  SetBorder(aBorder, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableElement::GetBorder(nsAString& aBorder)
-{
-  nsString border;
-  GetBorder(border);
-  aBorder = border;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableElement::SetCellPadding(const nsAString& aCellPadding)
-{
-  ErrorResult rv;
-  SetCellPadding(aCellPadding, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableElement::GetCellPadding(nsAString& aCellPadding)
-{
-  nsString cellPadding;
-  GetCellPadding(cellPadding);
-  aCellPadding = cellPadding;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableElement::SetCellSpacing(const nsAString& aCellSpacing)
-{
-  ErrorResult rv;
-  SetCellSpacing(aCellSpacing, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableElement::GetCellSpacing(nsAString& aCellSpacing)
-{
-  nsString cellSpacing;
-  GetCellSpacing(cellSpacing);
-  aCellSpacing = cellSpacing;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableElement::SetFrame(const nsAString& aFrame)
-{
-  ErrorResult rv;
-  SetFrame(aFrame, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableElement::GetFrame(nsAString& aFrame)
-{
-  nsString frame;
-  GetFrame(frame);
-  aFrame = frame;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableElement::SetRules(const nsAString& aRules)
-{
-  ErrorResult rv;
-  SetRules(aRules, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableElement::GetRules(nsAString& aRules)
-{
-  nsString rules;
-  GetRules(rules);
-  aRules = rules;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableElement::SetSummary(const nsAString& aSummary)
-{
-  ErrorResult rv;
-  SetSummary(aSummary, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableElement::GetSummary(nsAString& aSummary)
-{
-  nsString summary;
-  GetSummary(summary);
-  aSummary = summary;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableElement::SetWidth(const nsAString& aWidth)
-{
-  ErrorResult rv;
-  SetWidth(aWidth, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableElement::GetWidth(nsAString& aWidth)
-{
-  nsString width;
-  GetWidth(width);
-  aWidth = width;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableElement::GetCaption(nsIDOMHTMLTableCaptionElement** aValue)
-{
-  nsCOMPtr<nsIDOMHTMLTableCaptionElement> caption = GetCaption();
-  caption.forget(aValue);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableElement::SetCaption(nsIDOMHTMLTableCaptionElement* aValue)
-{
-  HTMLTableCaptionElement* caption =
-    static_cast<HTMLTableCaptionElement*>(aValue);
-  SetCaption(caption);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableElement::GetTHead(nsIDOMHTMLTableSectionElement** aValue)
-{
-  NS_IF_ADDREF(*aValue = GetTHead());
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableElement::SetTHead(nsIDOMHTMLTableSectionElement* aValue)
-{
-  HTMLTableSectionElement* section =
-    static_cast<HTMLTableSectionElement*>(aValue);
-  ErrorResult rv;
-  SetTHead(section, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableElement::GetTFoot(nsIDOMHTMLTableSectionElement** aValue)
-{
-  NS_IF_ADDREF(*aValue = GetTFoot());
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableElement::SetTFoot(nsIDOMHTMLTableSectionElement* aValue)
-{
-  HTMLTableSectionElement* section =
-    static_cast<HTMLTableSectionElement*>(aValue);
-  ErrorResult rv;
-  SetTFoot(section, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableElement::GetRows(nsIDOMHTMLCollection** aValue)
-{
-  NS_ADDREF(*aValue = Rows());
-  return NS_OK;
-}
-
 nsIHTMLCollection*
 HTMLTableElement::Rows()
 {
   if (!mRows) {
     mRows = new TableRowsCollection(this);
   }
 
   return mRows;
 }
 
-NS_IMETHODIMP
-HTMLTableElement::GetTBodies(nsIDOMHTMLCollection** aValue)
-{
-  NS_ADDREF(*aValue = TBodies());
-  return NS_OK;
-}
-
 nsIHTMLCollection*
 HTMLTableElement::TBodies()
 {
   if (!mTBodies) {
     // Not using NS_GetContentList because this should not be cached
     mTBodies = new nsContentList(this,
                                  kNameSpaceID_XHTML,
                                  nsGkAtoms::tbody,
@@ -605,34 +386,25 @@ HTMLTableElement::CreateTHead()
     }
 
     ErrorResult rv;
     nsINode::InsertBefore(*head, nsINode::GetFirstChild(), rv);
   }
   return head.forget();
 }
 
-NS_IMETHODIMP
-HTMLTableElement::CreateTHead(nsIDOMHTMLElement** aValue)
-{
-  nsRefPtr<nsGenericHTMLElement> thead = CreateTHead();
-  return thead ? CallQueryInterface(thead, aValue) : NS_OK;
-}
-
-NS_IMETHODIMP
+void
 HTMLTableElement::DeleteTHead()
 {
   HTMLTableSectionElement* tHead = GetTHead();
   if (tHead) {
     mozilla::ErrorResult rv;
     nsINode::RemoveChild(*tHead, rv);
     MOZ_ASSERT(!rv.Failed());
   }
-
-  return NS_OK;
 }
 
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableElement::CreateTFoot()
 {
   nsRefPtr<nsGenericHTMLElement> foot = GetTFoot();
   if (!foot) {
     // create a new foot rowgroup
@@ -645,34 +417,25 @@ HTMLTableElement::CreateTFoot()
       return nullptr;
     }
     AppendChildTo(foot, true);
   }
 
   return foot.forget();
 }
 
-NS_IMETHODIMP
-HTMLTableElement::CreateTFoot(nsIDOMHTMLElement** aValue)
-{
-  nsRefPtr<nsGenericHTMLElement> tfoot = CreateTFoot();
-  return tfoot ? CallQueryInterface(tfoot, aValue) : NS_OK;
-}
-
-NS_IMETHODIMP
+void
 HTMLTableElement::DeleteTFoot()
 {
   HTMLTableSectionElement* tFoot = GetTFoot();
   if (tFoot) {
     mozilla::ErrorResult rv;
     nsINode::RemoveChild(*tFoot, rv);
     MOZ_ASSERT(!rv.Failed());
   }
-
-  return NS_OK;
 }
 
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableElement::CreateCaption()
 {
   nsRefPtr<nsGenericHTMLElement> caption = GetCaption();
   if (!caption) {
     // Create a new caption.
@@ -685,34 +448,25 @@ HTMLTableElement::CreateCaption()
       return nullptr;
     }
 
     AppendChildTo(caption, true);
   }
   return caption.forget();
 }
 
-NS_IMETHODIMP
-HTMLTableElement::CreateCaption(nsIDOMHTMLElement** aValue)
-{
-  nsRefPtr<nsGenericHTMLElement> caption = CreateCaption();
-  return caption ? CallQueryInterface(caption, aValue) : NS_OK;
-}
-
-NS_IMETHODIMP
+void
 HTMLTableElement::DeleteCaption()
 {
   HTMLTableCaptionElement* caption = GetCaption();
   if (caption) {
     mozilla::ErrorResult rv;
     nsINode::RemoveChild(*caption, rv);
     MOZ_ASSERT(!rv.Failed());
   }
-
-  return NS_OK;
 }
 
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableElement::CreateTBody()
 {
   nsCOMPtr<nsINodeInfo> nodeInfo =
     OwnerDoc()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::tbody, nullptr,
                                                kNameSpaceID_XHTML,
@@ -738,17 +492,17 @@ HTMLTableElement::CreateTBody()
 
   return newBody.forget();
 }
 
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableElement::InsertRow(int32_t aIndex, ErrorResult& aError)
 {
   /* get the ref row at aIndex
-     if there is one, 
+     if there is one,
        get its parent
        insert the new row just before the ref row
      else
        get the first row group
        insert the new row as its first child
   */
   if (aIndex < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
@@ -843,24 +597,16 @@ HTMLTableElement::InsertRow(int32_t aInd
         rowGroup->InsertBefore(*newRow, rows->Item(0), aError);
       }
     }
   }
 
   return newRow.forget();
 }
 
-NS_IMETHODIMP
-HTMLTableElement::InsertRow(int32_t aIndex, nsIDOMHTMLElement** aValue)
-{
-  ErrorResult rv;
-  nsRefPtr<nsGenericHTMLElement> newRow = InsertRow(aIndex, rv);
-  return rv.Failed() ? rv.ErrorCode() : CallQueryInterface(newRow, aValue);
-}
-
 void
 HTMLTableElement::DeleteRow(int32_t aIndex, ErrorResult& aError)
 {
   if (aIndex < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
@@ -881,24 +627,16 @@ HTMLTableElement::DeleteRow(int32_t aInd
   if (!row) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
   row->RemoveFromParent();
 }
 
-NS_IMETHODIMP
-HTMLTableElement::DeleteRow(int32_t aValue)
-{
-  ErrorResult rv;
-  DeleteRow(aValue, rv);
-  return rv.ErrorCode();
-}
-
 static const nsAttrValue::EnumTable kFrameTable[] = {
   { "void",   NS_STYLE_TABLE_FRAME_NONE },
   { "above",  NS_STYLE_TABLE_FRAME_ABOVE },
   { "below",  NS_STYLE_TABLE_FRAME_BELOW },
   { "hsides", NS_STYLE_TABLE_FRAME_HSIDES },
   { "lhs",    NS_STYLE_TABLE_FRAME_LEFT },
   { "rhs",    NS_STYLE_TABLE_FRAME_RIGHT },
   { "vsides", NS_STYLE_TABLE_FRAME_VSIDES },
--- a/content/html/content/src/HTMLTableElement.h
+++ b/content/html/content/src/HTMLTableElement.h
@@ -34,33 +34,35 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
-  // nsIDOMHTMLTableElement
-  NS_DECL_NSIDOMHTMLTABLEELEMENT
-
   HTMLTableCaptionElement* GetCaption() const
   {
     return static_cast<HTMLTableCaptionElement*>(GetChild(nsGkAtoms::caption));
   }
   void SetCaption(HTMLTableCaptionElement* aCaption)
   {
     DeleteCaption();
     if (aCaption) {
       mozilla::ErrorResult rv;
       nsINode::AppendChild(*aCaption, rv);
     }
   }
+
+  void DeleteTFoot();
+
   already_AddRefed<nsGenericHTMLElement> CreateCaption();
 
+  void DeleteCaption();
+
   HTMLTableSectionElement* GetTHead() const
   {
     return static_cast<HTMLTableSectionElement*>(GetChild(nsGkAtoms::thead));
   }
   void SetTHead(HTMLTableSectionElement* aTHead, ErrorResult& aError)
   {
     if (aTHead && !aTHead->IsHTML(nsGkAtoms::thead)) {
       aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
@@ -69,16 +71,18 @@ public:
 
     DeleteTHead();
     if (aTHead) {
       nsINode::InsertBefore(*aTHead, nsINode::GetFirstChild(), aError);
     }
   }
   already_AddRefed<nsGenericHTMLElement> CreateTHead();
 
+  void DeleteTHead();
+
   HTMLTableSectionElement* GetTFoot() const
   {
     return static_cast<HTMLTableSectionElement*>(GetChild(nsGkAtoms::tfoot));
   }
   void SetTFoot(HTMLTableSectionElement* aTFoot, ErrorResult& aError)
   {
     if (aTFoot && !aTFoot->IsHTML(nsGkAtoms::tfoot)) {
       aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
--- a/content/html/content/src/HTMLTableRowElement.cpp
+++ b/content/html/content/src/HTMLTableRowElement.cpp
@@ -21,43 +21,46 @@ namespace mozilla {
 namespace dom {
 
 JSObject*
 HTMLTableRowElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aScope)
 {
   return HTMLTableRowElementBinding::Wrap(aCx, aScope, this);
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLTableRowElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLTableRowElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCells)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLTableRowElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTableRowElement, Element)
 
 // QueryInterface implementation for HTMLTableRowElement
-NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLTableRowElement)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLTableRowElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
-  NS_INTERFACE_TABLE_INHERITED1(HTMLTableRowElement,
-                                nsIDOMHTMLTableRowElement)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableRowElement)
 
 
 // protected method
-already_AddRefed<nsIDOMHTMLTableSectionElement>
+HTMLTableSectionElement*
 HTMLTableRowElement::GetSection() const
 {
-  nsCOMPtr<nsIDOMHTMLTableSectionElement> section =
-    do_QueryInterface(GetParent());
-  return section.forget();
+  nsIContent* parent = GetParent();
+  if (parent->IsHTML() && (parent->Tag() == nsGkAtoms::thead ||
+                           parent->Tag() == nsGkAtoms::tbody ||
+                           parent->Tag() == nsGkAtoms::tfoot)) {
+    return static_cast<HTMLTableSectionElement*>(parent);
+  }
+  return nullptr;
 }
 
 // protected method
 HTMLTableElement*
 HTMLTableRowElement::GetTable() const
 {
   nsIContent* parent = GetParent();
   if (!parent) {
@@ -89,52 +92,35 @@ HTMLTableRowElement::RowIndex() const
     if (rows->GetElementAt(i) == this) {
       return i;
     }
   }
 
   return -1;
 }
 
-NS_IMETHODIMP
-HTMLTableRowElement::GetRowIndex(int32_t* aValue)
-{
-  *aValue = RowIndex();
-  return NS_OK;
-}
-
 int32_t
 HTMLTableRowElement::SectionRowIndex() const
 {
-  nsCOMPtr<nsIDOMHTMLTableSectionElement> section = GetSection();
+  HTMLTableSectionElement* section = GetSection();
   if (!section) {
     return -1;
   }
 
-  nsCOMPtr<nsIDOMHTMLCollection> rows;
-  section->GetRows(getter_AddRefs(rows));
-
-  nsCOMPtr<nsIHTMLCollection> coll = do_QueryInterface(rows);
+  nsCOMPtr<nsIHTMLCollection> coll = section->Rows();
   uint32_t numRows = coll->Length();
   for (uint32_t i = 0; i < numRows; i++) {
     if (coll->GetElementAt(i) == this) {
       return i;
     }
   }
 
   return -1;
 }
 
-NS_IMETHODIMP
-HTMLTableRowElement::GetSectionRowIndex(int32_t* aValue)
-{
-  *aValue = SectionRowIndex();
-  return NS_OK;
-}
-
 static bool
 IsCell(nsIContent *aContent, int32_t aNamespaceID,
        nsIAtom* aAtom, void *aData)
 {
   nsIAtom* tag = aContent->Tag();
 
   return ((tag == nsGkAtoms::td || tag == nsGkAtoms::th) &&
           aContent->IsHTML());
@@ -152,23 +138,16 @@ HTMLTableRowElement::Cells()
                                nullptr,
                                kNameSpaceID_XHTML,
                                false);
   }
 
   return mCells;
 }
 
-NS_IMETHODIMP
-HTMLTableRowElement::GetCells(nsIDOMHTMLCollection** aValue)
-{
-  NS_ADDREF(*aValue = Cells());
-  return NS_OK;
-}
-
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableRowElement::InsertCell(int32_t aIndex,
                                 ErrorResult& aError)
 {
   if (aIndex < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return nullptr;
   }
@@ -206,24 +185,16 @@ HTMLTableRowElement::InsertCell(int32_t 
     return nullptr;
   }
 
   nsINode::InsertBefore(*cell, nextSibling, aError);
 
   return cell.forget();
 }
 
-NS_IMETHODIMP
-HTMLTableRowElement::InsertCell(int32_t aIndex, nsIDOMHTMLElement** aValue)
-{
-  ErrorResult rv;
-  nsRefPtr<nsGenericHTMLElement> cell = InsertCell(aIndex, rv);
-  return rv.Failed() ? rv.ErrorCode() : CallQueryInterface(cell, aValue);
-}
-
 void
 HTMLTableRowElement::DeleteCell(int32_t aValue, ErrorResult& aError)
 {
   if (aValue < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
@@ -246,109 +217,16 @@ HTMLTableRowElement::DeleteCell(int32_t 
   if (!cell) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
   nsINode::RemoveChild(*cell, aError);
 }
 
-NS_IMETHODIMP
-HTMLTableRowElement::DeleteCell(int32_t aValue)
-{
-  ErrorResult rv;
-  DeleteCell(aValue, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableRowElement::SetAlign(const nsAString& aAlign)
-{
-  ErrorResult rv;
-  SetAlign(aAlign, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableRowElement::GetAlign(nsAString& aAlign)
-{
-  nsString align;
-  GetAlign(align);
-  aAlign = align;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableRowElement::SetVAlign(const nsAString& aVAlign)
-{
-  ErrorResult rv;
-  SetVAlign(aVAlign, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableRowElement::GetVAlign(nsAString& aVAlign)
-{
-  nsString vAlign;
-  GetVAlign(vAlign);
-  aVAlign = vAlign;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableRowElement::SetCh(const nsAString& aCh)
-{
-  ErrorResult rv;
-  SetCh(aCh, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableRowElement::GetCh(nsAString& aCh)
-{
-  nsString ch;
-  GetCh(ch);
-  aCh = ch;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableRowElement::SetChOff(const nsAString& aChOff)
-{
-  ErrorResult rv;
-  SetChOff(aChOff, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableRowElement::GetChOff(nsAString& aChOff)
-{
-  nsString chOff;
-  GetChOff(chOff);
-  aChOff = chOff;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableRowElement::SetBgColor(const nsAString& aBgColor)
-{
-  ErrorResult rv;
-  SetBgColor(aBgColor, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableRowElement::GetBgColor(nsAString& aBgColor)
-{
-  nsString bgColor;
-  GetBgColor(bgColor);
-  aBgColor = bgColor;
-  return NS_OK;
-}
-
 bool
 HTMLTableRowElement::ParseAttribute(int32_t aNamespaceID,
                                     nsIAtom* aAttribute,
                                     const nsAString& aValue,
                                     nsAttrValue& aResult)
 {
   /*
    * ignore these attributes, stored simply as strings
--- a/content/html/content/src/HTMLTableRowElement.h
+++ b/content/html/content/src/HTMLTableRowElement.h
@@ -2,27 +2,27 @@
 /* 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_HTMLTableRowElement_h
 #define mozilla_dom_HTMLTableRowElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
-#include "nsIDOMHTMLTableRowElement.h"
 
 class nsIDOMHTMLTableElement;
-class nsIDOMHTMLTableSectionElement;
 class nsContentList;
 
 namespace mozilla {
 namespace dom {
 
+class HTMLTableSectionElement;
+
 class HTMLTableRowElement MOZ_FINAL : public nsGenericHTMLElement,
-                                      public nsIDOMHTMLTableRowElement
+                                      public nsIDOMHTMLElement
 {
 public:
   HTMLTableRowElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLTableRowElement, tr)
@@ -34,19 +34,16 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
-  // nsIDOMHTMLTableRowElement
-  NS_DECL_NSIDOMHTMLTABLEROWELEMENT
-
   int32_t RowIndex() const;
   int32_t SectionRowIndex() const;
   nsIHTMLCollection* Cells();
   already_AddRefed<nsGenericHTMLElement>
     InsertCell(int32_t aIndex, ErrorResult& aError);
   void DeleteCell(int32_t aValue, ErrorResult& aError);
 
   void GetAlign(nsString& aAlign)
@@ -103,17 +100,17 @@ public:
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(HTMLTableRowElement,
                                                      nsGenericHTMLElement)
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
-  already_AddRefed<nsIDOMHTMLTableSectionElement> GetSection() const;
+  HTMLTableSectionElement* GetSection() const;
   HTMLTableElement* GetTable() const;
   nsRefPtr<nsContentList> mCells;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableRowElement_h */
--- a/content/html/content/src/HTMLTableSectionElement.cpp
+++ b/content/html/content/src/HTMLTableSectionElement.cpp
@@ -21,124 +21,48 @@ namespace dom {
 // you will see the phrases "rowgroup" and "section" used interchangably
 
 JSObject*
 HTMLTableSectionElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aScope)
 {
   return HTMLTableSectionElementBinding::Wrap(aCx, aScope, this);
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLTableSectionElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLTableSectionElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRows)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLTableSectionElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTableSectionElement, Element)
 
 // QueryInterface implementation for HTMLTableSectionElement
-NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLTableSectionElement)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLTableSectionElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
-  NS_INTERFACE_TABLE_INHERITED1(HTMLTableSectionElement,
-                                nsIDOMHTMLTableSectionElement)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableSectionElement)
 
-NS_IMETHODIMP
-HTMLTableSectionElement::SetAlign(const nsAString& aAlign)
-{
-  ErrorResult rv;
-  SetAlign(aAlign, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableSectionElement::GetAlign(nsAString& aAlign)
-{
-  nsString align;
-  GetAlign(align);
-  aAlign = align;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableSectionElement::SetVAlign(const nsAString& aVAlign)
-{
-  ErrorResult rv;
-  SetVAlign(aVAlign, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableSectionElement::GetVAlign(nsAString& aVAlign)
-{
-  nsString vAlign;
-  GetVAlign(vAlign);
-  aVAlign = vAlign;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableSectionElement::SetCh(const nsAString& aCh)
-{
-  ErrorResult rv;
-  SetCh(aCh, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableSectionElement::GetCh(nsAString& aCh)
-{
-  nsString ch;
-  GetCh(ch);
-  aCh = ch;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLTableSectionElement::SetChOff(const nsAString& aChOff)
-{
-  ErrorResult rv;
-  SetChOff(aChOff, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-HTMLTableSectionElement::GetChOff(nsAString& aChOff)
-{
-  nsString chOff;
-  GetChOff(chOff);
-  aChOff = chOff;
-  return NS_OK;
-}
-
 nsIHTMLCollection*
 HTMLTableSectionElement::Rows()
 {
   if (!mRows) {
     mRows = new nsContentList(this,
                               mNodeInfo->NamespaceID(),
                               nsGkAtoms::tr,
                               nsGkAtoms::tr,
                               false);
   }
 
   return mRows;
 }
 
-NS_IMETHODIMP
-HTMLTableSectionElement::GetRows(nsIDOMHTMLCollection** aValue)
-{
-  NS_ADDREF(*aValue = Rows());
-  return NS_OK;
-}
-
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableSectionElement::InsertRow(int32_t aIndex, ErrorResult& aError)
 {
   if (aIndex < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return nullptr;
   }
 
@@ -167,25 +91,16 @@ HTMLTableSectionElement::InsertRow(int32
   if (doInsert) {
     nsINode::InsertBefore(*rowContent, rows->Item(aIndex), aError);
   } else {
     nsINode::AppendChild(*rowContent, aError);
   }
   return rowContent.forget();
 }
 
-NS_IMETHODIMP
-HTMLTableSectionElement::InsertRow(int32_t aIndex,
-                                   nsIDOMHTMLElement** aValue)
-{
-  ErrorResult rv;
-  nsRefPtr<nsGenericHTMLElement> row = InsertRow(aIndex, rv);
-  return rv.Failed() ? rv.ErrorCode() : CallQueryInterface(row, aValue);
-}
-
 void
 HTMLTableSectionElement::DeleteRow(int32_t aValue, ErrorResult& aError)
 {
   if (aValue < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
@@ -208,24 +123,16 @@ HTMLTableSectionElement::DeleteRow(int32
   if (!row) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
   nsINode::RemoveChild(*row, aError);
 }
 
-NS_IMETHODIMP
-HTMLTableSectionElement::DeleteRow(int32_t aValue)
-{
-  ErrorResult rv;
-  DeleteRow(aValue, rv);
-  return rv.ErrorCode();
-}
-
 bool
 HTMLTableSectionElement::ParseAttribute(int32_t aNamespaceID,
                                         nsIAtom* aAttribute,
                                         const nsAString& aValue,
                                         nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     /* ignore these attributes, stored simply as strings
@@ -250,17 +157,17 @@ HTMLTableSectionElement::ParseAttribute(
 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static 
+static
 void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
     // height: value
     nsCSSValue* height = aData->ValueForHeight();
     if (height->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
       if (value && value->Type() == nsAttrValue::eInteger)
@@ -289,17 +196,17 @@ void MapAttributesIntoRule(const nsMappe
   nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableSectionElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
-    { &nsGkAtoms::align }, 
+    { &nsGkAtoms::align },
     { &nsGkAtoms::valign },
     { &nsGkAtoms::height },
     { nullptr }
   };
 
   static const MappedAttributeEntry* const map[] = {
     attributes,
     sCommonAttributeMap,
--- a/content/html/content/src/HTMLTableSectionElement.h
+++ b/content/html/content/src/HTMLTableSectionElement.h
@@ -2,24 +2,23 @@
 /* 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_HTMLTableSectionElement_h
 #define mozilla_dom_HTMLTableSectionElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
-#include "nsIDOMHTMLTableSectionElement.h"
 #include "nsContentList.h" // For ctor.
 
 namespace mozilla {
 namespace dom {
 
 class HTMLTableSectionElement MOZ_FINAL : public nsGenericHTMLElement,
-                                          public nsIDOMHTMLTableSectionElement
+                                          public nsIDOMHTMLElement
 {
 public:
   HTMLTableSectionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
 
   // nsISupports
@@ -29,19 +28,16 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
-  // nsIDOMHTMLTableSectionElement
-  NS_DECL_NSIDOMHTMLTABLESECTIONELEMENT
-
   nsIHTMLCollection* Rows();
   already_AddRefed<nsGenericHTMLElement>
     InsertRow(int32_t aIndex, ErrorResult& aError);
   void DeleteRow(int32_t aValue, ErrorResult& aError);
 
   void GetAlign(nsString& aAlign)
   {
     GetHTMLAttr(nsGkAtoms::align, aAlign);
--- a/content/html/content/src/HTMLTextAreaElement.cpp
+++ b/content/html/content/src/HTMLTextAreaElement.cpp
@@ -45,17 +45,17 @@ static NS_DEFINE_CID(kXULControllersCID,
 
 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(TextArea)
 
 namespace mozilla {
 namespace dom {
 
 HTMLTextAreaElement::HTMLTextAreaElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                                          FromParser aFromParser)
-  : nsGenericHTMLFormElement(aNodeInfo),
+  : nsGenericHTMLFormElementWithState(aNodeInfo),
     mValueChanged(false),
     mHandlingSelect(false),
     mDoneAddingChildren(!aFromParser),
     mInhibitStateRestoration(!!(aFromParser & FROM_PARSER_FRAGMENT)),
     mDisabledChanged(false),
     mCanShowInvalidUI(true),
     mCanShowValidUI(true),
     mState(MOZ_THIS_IN_INITIALIZER_LIST())
@@ -68,28 +68,29 @@ HTMLTextAreaElement::HTMLTextAreaElement
   // until someone calls UpdateEditableState on us, apparently!  Also
   // by default we don't have to show validity UI and so forth.
   AddStatesSilently(NS_EVENT_STATE_ENABLED |
                     NS_EVENT_STATE_OPTIONAL |
                     NS_EVENT_STATE_VALID);
 }
 
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED_3(HTMLTextAreaElement, nsGenericHTMLFormElement,
+NS_IMPL_CYCLE_COLLECTION_INHERITED_3(HTMLTextAreaElement,
+                                     nsGenericHTMLFormElementWithState,
                                      mValidity,
                                      mControllers,
                                      mState)
 
 NS_IMPL_ADDREF_INHERITED(HTMLTextAreaElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTextAreaElement, Element)
 
 
 // QueryInterface implementation for HTMLTextAreaElement
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLTextAreaElement)
-  NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElement)
+  NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElementWithState)
   NS_INTERFACE_TABLE_INHERITED5(HTMLTextAreaElement,
                                 nsIDOMHTMLTextAreaElement,
                                 nsITextControlElement,
                                 nsIDOMNSEditableElement,
                                 nsIMutationObserver,
                                 nsIConstraintValidation)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
@@ -102,17 +103,17 @@ NS_IMPL_ELEMENT_CLONE(HTMLTextAreaElemen
 
 // nsIConstraintValidation
 NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(HTMLTextAreaElement)
 
 
 NS_IMETHODIMP
 HTMLTextAreaElement::GetForm(nsIDOMHTMLFormElement** aForm)
 {
-  return nsGenericHTMLFormElement::GetForm(aForm);
+  return nsGenericHTMLFormElementWithState::GetForm(aForm);
 }
 
 
 // nsIContent
 
 NS_IMETHODIMP
 HTMLTextAreaElement::Select()
 {
@@ -170,17 +171,19 @@ HTMLTextAreaElement::SelectAll(nsPresCon
 
   return NS_OK;
 }
 
 bool
 HTMLTextAreaElement::IsHTMLFocusable(bool aWithMouse,
                                      bool *aIsFocusable, int32_t *aTabIndex)
 {
-  if (nsGenericHTMLFormElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
+  if (nsGenericHTMLFormElementWithState::IsHTMLFocusable(aWithMouse, aIsFocusable,
+                                                         aTabIndex))
+  {
     return true;
   }
 
   // disabled textareas are not focusable
   *aIsFocusable = !IsDisabled();
   return false;
 }
 
@@ -397,26 +400,26 @@ HTMLTextAreaElement::ParseAttribute(int3
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 static void
 MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                       nsRuleData* aData)
 {
-  nsGenericHTMLFormElement::MapDivAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLFormElementWithState::MapDivAlignAttributeInto(aAttributes, aData);
+  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
 }
 
 nsChangeHint
 HTMLTextAreaElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                             int32_t aModType) const
 {
   nsChangeHint retval =
-      nsGenericHTMLFormElement::GetAttributeChangeHint(aAttribute, aModType);
+      nsGenericHTMLFormElementWithState::GetAttributeChangeHint(aAttribute, aModType);
   if (aAttribute == nsGkAtoms::rows ||
       aAttribute == nsGkAtoms::cols) {
     NS_UpdateHint(retval, NS_STYLE_HINT_REFLOW);
   } else if (aAttribute == nsGkAtoms::wrap) {
     NS_UpdateHint(retval, nsChangeHint_ReconstructFrame);
   } else if (aAttribute == nsGkAtoms::placeholder) {
     NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
   }
@@ -481,17 +484,17 @@ HTMLTextAreaElement::PreHandleEvent(nsEv
     aVisitor.mEvent->mFlags.mNoContentDispatch = false;
   }
 
   // Fire onchange (if necessary), before we do the blur, bug 370521.
   if (aVisitor.mEvent->message == NS_BLUR_CONTENT) {
     FireChangeEventIfNeeded();
   }
 
-  return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
+  return nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor);
 }
 
 void
 HTMLTextAreaElement::FireChangeEventIfNeeded()
 {
   nsString value;
   GetValueInternal(value, true);
 
@@ -544,18 +547,22 @@ void
 HTMLTextAreaElement::DoneAddingChildren(bool aHaveNotified)
 {
   if (!mValueChanged) {
     if (!mDoneAddingChildren) {
       // Reset now that we're done adding children if the content sink tried to
       // sneak some text in without calling AppendChildTo.
       Reset();
     }
+
     if (!mInhibitStateRestoration) {
-      RestoreFormControlState(this, this);
+      nsresult rv = GenerateStateKey();
+      if (NS_SUCCEEDED(rv)) {
+        RestoreFormControlState();
+      }
     }
   }
 
   mDoneAddingChildren = true;
 }
 
 bool
 HTMLTextAreaElement::IsDoneAddingChildren()
@@ -998,17 +1005,17 @@ HTMLTextAreaElement::RestoreState(nsPres
   }
 
   return false;
 }
 
 nsEventStates
 HTMLTextAreaElement::IntrinsicState() const
 {
-  nsEventStates state = nsGenericHTMLFormElement::IntrinsicState();
+  nsEventStates state = nsGenericHTMLFormElementWithState::IntrinsicState();
 
   if (HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
     state |= NS_EVENT_STATE_REQUIRED;
   } else {
     state |= NS_EVENT_STATE_OPTIONAL;
   }
 
   if (IsCandidateForConstraintValidation()) {
@@ -1045,36 +1052,36 @@ HTMLTextAreaElement::IntrinsicState() co
   return state;
 }
 
 nsresult
 HTMLTextAreaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                 nsIContent* aBindingParent,
                                 bool aCompileEventHandlers)
 {
-  nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
-                                                     aBindingParent,
-                                                     aCompileEventHandlers);
+  nsresult rv = nsGenericHTMLFormElementWithState::BindToTree(aDocument, aParent,
+                                                              aBindingParent,
+                                                              aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If there is a disabled fieldset in the parent chain, the element is now
   // barred from constraint validation and can't suffer from value missing.
   UpdateValueMissingValidityState();
   UpdateBarredFromConstraintValidation();
 
   // And now make sure our state is up to date
   UpdateState(false);
 
   return rv;
 }
 
 void
 HTMLTextAreaElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
-  nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
+  nsGenericHTMLFormElementWithState::UnbindFromTree(aDeep, aNullParent);
 
   // We might be no longer disabled because of parent chain changed.
   UpdateValueMissingValidityState();
   UpdateBarredFromConstraintValidation();
 
   // And now make sure our state is up to date
   UpdateState(false);
 }
@@ -1084,17 +1091,17 @@ HTMLTextAreaElement::BeforeSetAttr(int32
                                    const nsAttrValueOrString* aValue,
                                    bool aNotify)
 {
   if (aNotify && aName == nsGkAtoms::disabled &&
       aNameSpaceID == kNameSpaceID_None) {
     mDisabledChanged = true;
   }
 
-  return nsGenericHTMLFormElement::BeforeSetAttr(aNameSpaceID, aName,
+  return nsGenericHTMLFormElementWithState::BeforeSetAttr(aNameSpaceID, aName,
                                                  aValue, aNotify);
 }
 
 void
 HTMLTextAreaElement::CharacterDataChanged(nsIDocument* aDocument,
                                           nsIContent* aContent,
                                           CharacterDataChangeInfo* aInfo)
 {
@@ -1156,24 +1163,24 @@ HTMLTextAreaElement::AfterSetAttr(int32_
       }
     } else if (aName == nsGkAtoms::maxlength) {
       UpdateTooLongValidityState();
     }
 
     UpdateState(aNotify);
   }
 
-  return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                                aNotify);
-}
+  return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue,
+                                                         aNotify);
+  }
 
 nsresult
 HTMLTextAreaElement::CopyInnerTo(Element* aDest)
 {
-  nsresult rv = nsGenericHTMLFormElement::CopyInnerTo(aDest);
+  nsresult rv = nsGenericHTMLFormElementWithState::CopyInnerTo(aDest);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDest->OwnerDoc()->IsStaticDocument()) {
     nsAutoString value;
     GetValueInternal(value, true);
     static_cast<HTMLTextAreaElement*>(aDest)->SetValue(value);
   }
   return NS_OK;
@@ -1417,17 +1424,17 @@ HTMLTextAreaElement::HasCachedSelection(
 }
 
 void
 HTMLTextAreaElement::FieldSetDisabledChanged(bool aNotify)
 {
   UpdateValueMissingValidityState();
   UpdateBarredFromConstraintValidation();
 
-  nsGenericHTMLFormElement::FieldSetDisabledChanged(aNotify);
+  nsGenericHTMLFormElementWithState::FieldSetDisabledChanged(aNotify);
 }
 
 JSObject*
 HTMLTextAreaElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return HTMLTextAreaElementBinding::Wrap(aCx, aScope, this);
 }
 
--- a/content/html/content/src/HTMLTextAreaElement.h
+++ b/content/html/content/src/HTMLTextAreaElement.h
@@ -25,17 +25,17 @@ class nsFormSubmission;
 class nsIControllers;
 class nsIDocument;
 class nsPresContext;
 class nsPresState;
 
 namespace mozilla {
 namespace dom {
 
-class HTMLTextAreaElement MOZ_FINAL : public nsGenericHTMLFormElement,
+class HTMLTextAreaElement MOZ_FINAL : public nsGenericHTMLFormElementWithState,
                                       public nsIDOMHTMLTextAreaElement,
                                       public nsITextControlElement,
                                       public nsIDOMNSEditableElement,
                                       public nsStubMutationObserver,
                                       public nsIConstraintValidation
 {
 public:
   using nsIConstraintValidation::GetValidationMessage;
@@ -142,17 +142,17 @@ public:
 
   // nsIMutationObserver
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTextAreaElement,
-                                           nsGenericHTMLFormElement)
+                                           nsGenericHTMLFormElementWithState)
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
   // nsIConstraintValidation
   bool     IsTooLong();
   bool     IsValueMissing() const;
   void     UpdateTooLongValidityState();
   void     UpdateValueMissingValidityState();
@@ -184,18 +184,18 @@ public:
   bool Disabled()
   {
     return GetBoolAttr(nsGkAtoms::disabled);
   }
   void SetDisabled(bool aDisabled, ErrorResult& aError)
   {
     SetHTMLBoolAttr(nsGkAtoms::disabled, aDisabled, aError);
   }
-  // nsGenericHTMLFormElement::GetForm is fine
-  using nsGenericHTMLFormElement::GetForm;
+  // nsGenericHTMLFormElementWithState::GetForm is fine
+  using nsGenericHTMLFormElementWithState::GetForm;
   int32_t MaxLength()
   {
     return GetIntAttr(nsGkAtoms::maxlength, -1);
   }
   void SetMaxLength(int32_t aMaxLength, ErrorResult& aError)
   {
     if (aMaxLength < 0) {
       aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
@@ -267,17 +267,18 @@ public:
   void SetSelectionRange(uint32_t aSelectionStart, uint32_t aSelectionEnd, const Optional<nsAString>& aDirecton, ErrorResult& aError);
   nsIControllers* GetControllers(ErrorResult& aError);
   nsIEditor* GetEditor()
   {
     return mState.GetEditor();
   }
 
 protected:
-  using nsGenericHTMLFormElement::IsSingleLineTextControl; // get rid of the compiler warning
+  // get rid of the compiler warning
+  using nsGenericHTMLFormElementWithState::IsSingleLineTextControl;
 
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   nsCOMPtr<nsIControllers> mControllers;
   /** Whether or not the value has changed since its default value was given. */
   bool                     mValueChanged;
   /** Whether or not we are already handling select event. */
--- a/content/html/content/src/HTMLUnknownElement.cpp
+++ b/content/html/content/src/HTMLUnknownElement.cpp
@@ -1,15 +1,15 @@
 /* -*- 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 "nsDocument.h"
-#include "HTMLUnknownElement.h"
+#include "mozilla/dom/HTMLUnknownElement.h"
 #include "mozilla/dom/HTMLElementBinding.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Unknown)
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_ADDREF_INHERITED(HTMLUnknownElement, Element)
@@ -30,19 +30,16 @@ HTMLUnknownElement::WrapNode(JSContext *
       NS_ENSURE_TRUE(JS_WrapObject(aCx, prototype.address()), nullptr);
       NS_ENSURE_TRUE(JS_SetPrototype(aCx, obj, prototype), nullptr);
     }
   }
   return obj;
 }
 
 // QueryInterface implementation for HTMLUnknownElement
-NS_INTERFACE_TABLE_HEAD(HTMLUnknownElement)
+NS_INTERFACE_MAP_BEGIN(HTMLUnknownElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
-  NS_INTERFACE_TABLE_INHERITED1(HTMLUnknownElement,
-                                nsIDOMHTMLUnknownElement)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLUnknownElement)
 
 } // namespace dom
 } // namespace mozilla
--- a/content/html/content/src/HTMLUnknownElement.h
+++ b/content/html/content/src/HTMLUnknownElement.h
@@ -1,24 +1,23 @@
 /* -*- 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 HTMLUnknownElement_h___
-#define HTMLUnknownElement_h___
+#ifndef mozilla_dom_HTMLUnknownElement_h
+#define mozilla_dom_HTMLUnknownElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
-#include "nsIDOMHTMLUnknownElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLUnknownElement MOZ_FINAL : public nsGenericHTMLElement
-                                   , public nsIDOMHTMLUnknownElement
+                                   , public nsIDOMHTMLElement
 {
 public:
   HTMLUnknownElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
     if (NodeInfo()->Equals(nsGkAtoms::bdi)) {
       SetHasDirAuto();
     }
@@ -43,9 +42,9 @@ public:
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 };
 
 } // namespace dom
 } // namespace mozilla
 
-#endif /* HTMLUnknownElement_h___ */
+#endif /* mozilla_dom_HTMLUnknownElement_h */
--- a/content/html/content/src/nsDOMStringMap.cpp
+++ b/content/html/content/src/nsDOMStringMap.cpp
@@ -10,20 +10,23 @@
 #include "nsGenericHTMLElement.h"
 #include "nsContentUtils.h"
 #include "mozilla/dom/DOMStringMapBinding.h"
 #include "nsIDOMMutationEvent.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMStringMap)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMStringMap)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMStringMap)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   // Check that mElement exists in case the unlink code is run more than once.
   if (tmp->mElement) {
     // Call back to element to null out weak reference to this object.
     tmp->mElement->ClearDataset();
     tmp->mElement->RemoveMutationObserver(tmp);
     tmp->mElement = nullptr;
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -1170,100 +1170,16 @@ nsGenericHTMLElement::GetFormControlFram
         return form_frame;
       }
     }
   }
 
   return nullptr;
 }
 
-nsPresState*
-nsGenericHTMLElement::GetPrimaryPresState()
-{
-  nsAutoCString key;
-  nsCOMPtr<nsILayoutHistoryState> history = GetLayoutHistoryAndKey(this, false, key);
-  if (!history) {
-    return nullptr;
-  }
-
-  // Get the pres state for this key, if it doesn't exist, create one
-  nsPresState* presState = history->GetState(key);
-  if (!presState) {
-    presState = new nsPresState();
-    history->AddState(key, presState);
-  }
-  return presState;
-}
-
-
-already_AddRefed<nsILayoutHistoryState>
-nsGenericHTMLElement::GetLayoutHistoryAndKey(nsGenericHTMLElement* aContent,
-                                             bool aRead,
-                                             nsACString& aKey)
-{
-  //
-  // Get the pres shell
-  //
-  nsCOMPtr<nsIDocument> doc = aContent->GetDocument();
-  if (!doc) {
-    return nullptr;
-  }
-
-  //
-  // Get the history (don't bother with the key if the history is not there)
-  //
-  nsCOMPtr<nsILayoutHistoryState> history = doc->GetLayoutHistoryState();
-  if (!history) {
-    return nullptr;
-  }
-
-  if (aRead && !history->HasStates()) {
-    return nullptr;
-  }
-
-  //
-  // Get the state key
-  //
-  nsresult rv = nsContentUtils::GenerateStateKey(aContent, doc, aKey);
-  if (NS_FAILED(rv)) {
-    return nullptr;
-  }
-
-  // If the state key is blank, this is anonymous content or for
-  // whatever reason we are not supposed to save/restore state.
-  if (aKey.IsEmpty()) {
-    return nullptr;
-  }
-
-  // Add something unique to content so layout doesn't muck us up
-  aKey += "-C";
-
-  return history.forget();
-}
-
-bool
-nsGenericHTMLElement::RestoreFormControlState(nsGenericHTMLElement* aContent,
-                                              nsIFormControl* aControl)
-{
-  nsAutoCString key;
-  nsCOMPtr<nsILayoutHistoryState> history = GetLayoutHistoryAndKey(aContent, true, key);
-  if (!history) {
-    return false;
-  }
-
-  nsPresState* state = history->GetState(key);
-  if (state) {
-    bool result = aControl->RestoreState(state);
-    history->RemoveState(key);
-    return result;
-  }
-
-  return false;
-}
-
 // XXX This creates a dependency between content and frames
 nsPresContext*
 nsGenericHTMLElement::GetPresContext()
 {
   // Get the document
   nsIDocument* doc = GetDocument();
   if (doc) {
     // Get presentation shell.
@@ -3109,16 +3025,134 @@ nsGenericHTMLElement::ChangeEditableStat
 
   // MakeContentDescendantsEditable is going to call ContentStateChanged for
   // this element and all descendants if editable state has changed.
   // We might as well wrap it all in one script blocker.
   nsAutoScriptBlocker scriptBlocker;
   MakeContentDescendantsEditable(this, document);
 }
 
+
+//----------------------------------------------------------------------
+
+nsGenericHTMLFormElementWithState::nsGenericHTMLFormElementWithState(
+    already_AddRefed<nsINodeInfo> aNodeInfo
+  )
+  : nsGenericHTMLFormElement(aNodeInfo)
+{
+  mStateKey.SetIsVoid(true);
+}
+
+nsresult
+nsGenericHTMLFormElementWithState::GenerateStateKey()
+{
+  // Keep the key if already computed
+  if (!mStateKey.IsVoid()) {
+    return NS_OK;
+  }
+
+  nsIDocument* doc = GetDocument();
+  if (!doc) {
+    return NS_OK;
+  }
+
+  // Generate the state key
+  nsresult rv = nsContentUtils::GenerateStateKey(this, doc, mStateKey);
+
+  if (NS_FAILED(rv)) {
+    mStateKey.SetIsVoid(true);
+    return rv;
+  }
+
+  // If the state key is blank, this is anonymous content or for whatever
+  // reason we are not supposed to save/restore state: keep it as such.
+  if (!mStateKey.IsEmpty()) {
+    // Add something unique to content so layout doesn't muck us up.
+    mStateKey += "-C";
+  }
+  return NS_OK;
+}
+
+nsPresState*
+nsGenericHTMLFormElementWithState::GetPrimaryPresState()
+{
+  if (mStateKey.IsEmpty()) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsILayoutHistoryState> history = GetLayoutHistory(false);
+
+  if (!history) {
+    return nullptr;
+  }
+
+  // Get the pres state for this key, if it doesn't exist, create one.
+  nsPresState* result = history->GetState(mStateKey);
+  if (!result) {
+    result = new nsPresState();
+    history->AddState(mStateKey, result);
+  }
+
+  return result;
+}
+
+already_AddRefed<nsILayoutHistoryState>
+nsGenericHTMLFormElementWithState::GetLayoutHistory(bool aRead)
+{
+  nsCOMPtr<nsIDocument> doc = GetDocument();
+  if (!doc) {
+    return nullptr;
+  }
+
+  //
+  // Get the history
+  //
+  nsCOMPtr<nsILayoutHistoryState> history = doc->GetLayoutHistoryState();
+  if (!history) {
+    return nullptr;
+  }
+
+  if (aRead && !history->HasStates()) {
+    return nullptr;
+  }
+
+  return history.forget();
+}
+
+bool
+nsGenericHTMLFormElementWithState::RestoreFormControlState()
+{
+  if (mStateKey.IsEmpty()) {
+    return false;
+  }
+
+  nsCOMPtr<nsILayoutHistoryState> history =
+    GetLayoutHistory(true);
+  if (!history) {
+    return false;
+  }
+
+  nsPresState *state;
+  // Get the pres state for this key
+  state = history->GetState(mStateKey);
+  if (state) {
+    bool result = RestoreState(state);
+    history->RemoveState(mStateKey);
+    return result;
+  }
+
+  return false;
+}
+
+void
+nsGenericHTMLFormElementWithState::NodeInfoChanged(nsINodeInfo* aOldNodeInfo)
+{
+  mStateKey.SetIsVoid(true);
+}
+
 JS::Value
 nsGenericHTMLElement::GetItemValue(JSContext* aCx, JSObject* aScope,
                                    ErrorResult& aError)
 {
   JS::Rooted<JSObject*> scope(aCx, aScope);
   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop)) {
     return JS::NullValue();
   }
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -620,49 +620,16 @@ public:
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
   static void MapScrollingAttributeInto(const nsMappedAttributes* aAttributes,
                                         nsRuleData* aData);
   /**
-   * Get the presentation state for this, or create it if it does not exist.
-   * Generally used by SaveState().
-   *
-   * @return the presentation state (out param)
-   */
-  nsPresState* GetPrimaryPresState();
-  /**
-   * Get the layout history object *and* generate the key for a particular
-   * piece of content.
-   *
-   * @param aContent the content to generate the key for
-   * @param aRead if true, won't return a layout history state (and won't
-   *              generate a key) if the layout history state is empty.
-   * @param aState the history state object (out param)
-   * @param aKey the key (out param)
-   */
-  static already_AddRefed<nsILayoutHistoryState>
-  GetLayoutHistoryAndKey(nsGenericHTMLElement* aContent,
-                         bool aRead,
-                         nsACString& aKey);
-  /**
-   * Restore the state for a form control.  Ends up calling
-   * nsIFormControl::RestoreState().
-   *
-   * @param aContent an nsGenericHTMLElement* pointing to the form control
-   * @param aControl an nsIFormControl* pointing to the form control
-   * @return false if RestoreState() was not called, the return
-   *         value of RestoreState() otherwise.
-   */
-  static bool RestoreFormControlState(nsGenericHTMLElement* aContent,
-                                        nsIFormControl* aControl);
-
-  /**
    * Get the presentation context for this content node.
    * @return the presentation context
    */
   NS_HIDDEN_(nsPresContext*) GetPresContext();
 
   // Form Helper Routines
   /**
    * Find an ancestor of this content node which is a form (could be null)
@@ -1230,16 +1197,62 @@ protected:
 
   /** The form that contains this control */
   mozilla::dom::HTMLFormElement* mForm;
 
   /* This is a pointer to our closest fieldset parent if any */
   mozilla::dom::HTMLFieldSetElement* mFieldSet;
 };
 
+class nsGenericHTMLFormElementWithState : public nsGenericHTMLFormElement
+{
+public:
+  nsGenericHTMLFormElementWithState(already_AddRefed<nsINodeInfo> aNodeInfo);
+
+  /**
+   * Get the presentation state for a piece of content, or create it if it does
+   * not exist.  Generally used by SaveState().
+   */
+  nsPresState* GetPrimaryPresState();
+
+  /**
+   * Get the layout history object for a particular piece of content.
+   *
+   * @param aRead if true, won't return a layout history state if the
+   *              layout history state is empty.
+   * @return the history state object
+   */
+  already_AddRefed<nsILayoutHistoryState>
+    GetLayoutHistory(bool aRead);
+
+  /**
+   * Restore the state for a form control.  Ends up calling
+   * nsIFormControl::RestoreState().
+   *
+   * @return false if RestoreState() was not called, the return
+   *         value of RestoreState() otherwise.
+   */
+  bool RestoreFormControlState();
+
+  /**
+   * Called when we have been cloned and adopted, and the information of the
+   * node has been changed.
+   */
+  virtual void NodeInfoChanged(nsINodeInfo* aOldNodeInfo) MOZ_OVERRIDE;
+
+protected:
+  /* Generates the state key for saving the form state in the session if not
+     computed already. The result is stored in mStateKey on success */
+  nsresult GenerateStateKey();
+
+  /* Used to store the key to that element in the session. Is void until
+     GenerateStateKey has been used */
+  nsCString mStateKey;
+};
+
 //----------------------------------------------------------------------
 
 /**
  * This macro is similar to NS_IMPL_STRING_ATTR except that the getter method
  * falls back to an alternative method if the content attribute isn't set.
  */
 #define NS_IMPL_STRING_ATTR_WITH_FALLBACK(_class, _method, _atom, _fallback) \
   NS_IMETHODIMP                                                              \
--- a/content/html/content/src/nsGenericHTMLFrameElement.cpp
+++ b/content/html/content/src/nsGenericHTMLFrameElement.cpp
@@ -14,16 +14,18 @@
 #include "nsServiceManagerUtils.h"
 #include "nsIDOMApplicationRegistry.h"
 #include "nsIPermissionManager.h"
 #include "GeckoProfiler.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericHTMLFrameElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameLoader)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_TABLE_HEAD(nsGenericHTMLFrameElement)
   NS_INTERFACE_TABLE_INHERITED3(nsGenericHTMLFrameElement,
                                 nsIFrameLoaderOwner,
--- a/content/html/content/test/forms/Makefile.in
+++ b/content/html/content/test/forms/Makefile.in
@@ -61,12 +61,13 @@ MOCHITEST_FILES = \
 		test_input_file_picker.html \
 		test_input_event.html \
 		test_input_number_rounding.html \
 		test_valueAsDate_pref.html \
 		test_input_color_picker_initial.html \
 		test_input_color_picker_update.html \
 		test_input_color_picker_popup.html \
 		test_input_color_input_change_events.html \
+		test_restore_form_elements.html \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/forms/test_restore_form_elements.html
@@ -0,0 +1,174 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=737851
+-->
+<head>
+  <meta charset="utf-8">
+
+  <title>Test for Bug 737851</title>
+
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<body>
+
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=737851">Mozilla Bug 737851</a>
+
+<p id="display"></p>
+
+
+<div id="content">
+
+  <iframe id="frame" width="800px" height="600px" src='data:text/html,
+          <html>
+            <body style="display:none;">
+
+              <h3>Checking persistence of inputs through js inserts and moves</h3>
+              <div id="test">
+                <input id="a"/>
+                <input id="b"/>
+                <form id="form1">
+                  <input id="c"/>
+                  <input id="d"/>
+                </form>
+                <form id="form2">
+                  <input id="radio1" type="radio" name="radio"/>
+                  <input type="radio" name="radio"/>
+                  <input type="radio" name="radio"/>
+                  <input type="radio" name="radio"/>
+                </form>
+                <input id="e"/>
+              </div>
+
+              <h3>Bug 728798: checking persistence of inputs when forward-using @form</h3>
+              <div>
+                <input id="728798-a" form="728798-form" name="a"/>
+                <form id="728798-form">
+                  <input id="728798-b" form="728798-form" name="b"/>
+                  <input id="728798-c" name="c"/>
+                </form>
+                <input id="728798-d" form="728798-form" name="d"/>
+              </div>
+
+            </body>
+          </html>
+  '></iframe>
+
+</div>
+
+
+<pre id="test">
+<script type="text/javascript">
+
+var frameElement = document.getElementById("frame");
+var frame = frameElement.contentWindow;
+
+
+/* -- Main test run -- */
+
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(function() {
+  shuffle();
+  fill();
+  frameElement.addEventListener("load", function() {
+    shuffle();
+    checkAllFields();
+    SimpleTest.finish();
+  });
+  frame.location.reload();
+})
+
+
+/* -- Input fields js changes and moves -- */
+
+function shuffle() {
+  var framedoc = frame.document;
+
+  // Insert a button (toplevel)
+  var btn = framedoc.createElement("button");
+  var testdiv = framedoc.getElementById("test");
+  testdiv.insertBefore(btn, framedoc.getElementById("b"));
+
+  // Insert a dynamically generated input (in a form)
+  var newInput = framedoc.createElement("input");
+  newInput.setAttribute("id","c0");
+  var form1 = framedoc.getElementById("form1");
+  form1.insertBefore(newInput, form1.firstChild);
+
+  // Move an input around
+  var inputD = framedoc.getElementById("d");
+  var form2 = framedoc.getElementById("form2");
+  form2.insertBefore(inputD, form2.firstChild)
+
+  // Clone an existing input
+  var inputE2 = framedoc.getElementById("e").cloneNode();
+  inputE2.setAttribute("id","e2");
+  testdiv.appendChild(inputE2);
+}
+
+
+/* -- Input fields fill & check -- */
+
+/* Values entered in the input fields (by id) */
+
+var fieldValues = {
+  'a':'simple input',
+  'b':'moved by inserting a button before (no form)',
+  'c0':'dynamically generated input',
+  'c':'moved by inserting an input before (in a form)',
+  'd':'moved from a form to another',
+  'e':'the original',
+  'e2':'the clone',
+  '728798-a':'before the form',
+  '728798-b':'from within the form',
+  '728798-c':'no form attribute in the form',
+  '728798-d':'after the form'
+}
+
+/* Fields for which the input is changed, and corresponding value
+   (clone and creation, same behaviour as webkit) */
+
+var changedFields = {
+  // dynamically generated input field not preserved
+  'c0':'',
+  // cloned input field is restored with the value of the original
+  'e2':fieldValues.e
+}
+
+/* Simulate user input by entering the values */
+
+function fill() {
+  for (id in fieldValues) {
+    frame.document.getElementById(id).value = fieldValues[id];
+  }
+  // an input is inserted before the radios (that may move the selected one by 1)
+  frame.document.getElementById('radio1').checked = true;
+}
+
+/* Check that all the fields are as they have been entered */
+
+function checkAllFields() {
+
+  for (id in fieldValues) {
+    var fieldValue = frame.document.getElementById(id).value;
+    if (changedFields[id] === undefined) {
+      is(fieldValue, fieldValues[id],
+                    "Field "+id+" should be restored after reload");
+    } else {
+      is(fieldValue, changedFields[id],
+                    "Field "+id+" normally gets a different value after reload");
+    }
+  }
+
+  ok(frame.document.getElementById('radio1').checked,
+                "Radio button radio1 should be restored after reload")
+
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/html/content/test/test_bug389797.html
+++ b/content/html/content/test/test_bug389797.html
@@ -239,23 +239,19 @@ for (var tag of allTags) {
   is(nodeString, "[object " + classInfoString,
      "Unexpected classname for " + tagName(tag));
   is(node instanceof window[classInfoString], true,
      tagName(tag) + " not an instance of " + classInfos[tag]);
 
   if (classInfoString != 'HTMLUnknownElement') {
     is(node instanceof HTMLUnknownElement, false,
        tagName(tag) + " is an instance of HTMLUnknownElement");
-    is(node instanceof SpecialPowers.Ci.nsIDOMHTMLUnknownElement, false,
-       tagName(tag) + " is an instance of nsIDOMHTMLUnknownElement");
   } else {
     is(node instanceof HTMLUnknownElement, true,
        tagName(tag) + " is an instance of HTMLUnknownElement");
-    is(node instanceof SpecialPowers.Ci.nsIDOMHTMLUnknownElement, true,
-       tagName(tag) + " is an instance of nsIDOMHTMLUnknownElement");
   }
 
   // Check that each node QIs to all the things we expect it to QI to
   for (var iface of interfaces[tag].concat(interfacesNonClassinfo[tag])) {
     is(iface in SpecialPowers.Ci, true,
        iface + " not in Components.interfaces");
     is(node instanceof SpecialPowers.Ci[iface], true,
        tagName(tag) + " does not QI to " + iface);
--- a/content/html/document/src/nsHTMLContentSink.cpp
+++ b/content/html/document/src/nsHTMLContentSink.cpp
@@ -1265,16 +1265,18 @@ HTMLContentSink::~HTMLContentSink()
 
   delete mHeadContext;
 
   for (i = 0; uint32_t(i) < ArrayLength(mNodeInfoCache); ++i) {
     NS_IF_RELEASE(mNodeInfoCache[i]);
   }
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLContentSink)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLContentSink, nsContentSink)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mHTMLDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mBody)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mHead)
   for (uint32_t i = 0; i < ArrayLength(tmp->mNodeInfoCache); ++i) {
     NS_IF_RELEASE(tmp->mNodeInfoCache[i]);
   }
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -207,16 +207,18 @@ nsHTMLDocument::nsHTMLDocument()
   mCompatMode = eCompatibility_NavQuirks;
 }
 
 nsHTMLDocument::~nsHTMLDocument()
 {
   mAll = nullptr;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLDocument)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
   NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration()),
                "Shouldn't traverse nsHTMLDocument!");
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImages)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mApplets)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEmbeds)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLinks)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnchors)
--- a/content/media/DOMMediaStream.cpp
+++ b/content/media/DOMMediaStream.cpp
@@ -19,16 +19,19 @@ using namespace mozilla::dom;
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMMediaStream)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMediaStream)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMMediaStream)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMMediaStream)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMMediaStream)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMMediaStream)
   tmp->Destroy();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTracks)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMMediaStream)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
--- a/content/media/webaudio/AudioBuffer.cpp
+++ b/content/media/webaudio/AudioBuffer.cpp
@@ -14,16 +14,18 @@
 #include "nsIScriptError.h"
 #include "nsPIDOMWindow.h"
 #include "AudioChannelFormat.h"
 #include "mozilla/PodOperations.h"
 
 namespace mozilla {
 namespace dom {
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(AudioBuffer)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioBuffer)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mJSChannels)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   tmp->ClearJSChannels();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioBuffer)
--- a/content/media/webaudio/AudioBufferSourceNode.cpp
+++ b/content/media/webaudio/AudioBufferSourceNode.cpp
@@ -12,16 +12,18 @@
 #include "AudioDestinationNode.h"
 #include "PannerNode.h"
 #include "speex/speex_resampler.h"
 #include <limits>
 
 namespace mozilla {
 namespace dom {
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(AudioBufferSourceNode)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioBufferSourceNode)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mBuffer)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlaybackRate)
   if (tmp->Context()) {
     // AudioNode's Unlink implementation disconnects us from the graph
     // too, but we need to do this right here to make sure that
     // UnregisterAudioBufferSourceNode can properly untangle us from
     // the possibly connected PannerNodes.
--- a/content/media/webaudio/AudioNode.cpp
+++ b/content/media/webaudio/AudioNode.cpp
@@ -10,16 +10,18 @@
 #include "mozilla/ErrorResult.h"
 #include "AudioNodeStream.h"
 
 namespace mozilla {
 namespace dom {
 
 static const uint32_t INVALID_PORT = 0xffffffff;
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(AudioNode)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AudioNode, nsDOMEventTargetHelper)
   tmp->DisconnectFromGraph();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputNodes)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputParams)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AudioNode, nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
--- a/content/media/webaudio/AudioParam.cpp
+++ b/content/media/webaudio/AudioParam.cpp
@@ -10,16 +10,18 @@
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/AudioParamBinding.h"
 #include "AudioNodeEngine.h"
 #include "AudioNodeStream.h"
 
 namespace mozilla {
 namespace dom {
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(AudioParam)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioParam)
   tmp->DisconnectFromGraphAndDestroyStream();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNode)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioParam)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNode)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
--- a/content/media/webaudio/MediaBufferDecoder.cpp
+++ b/content/media/webaudio/MediaBufferDecoder.cpp
@@ -20,16 +20,18 @@
 #include "nsIScriptContext.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptError.h"
 #include "nsMimeTypes.h"
 #include "nsCxPusher.h"
 
 namespace mozilla {
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(WebAudioDecodeJob)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebAudioDecodeJob)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutput)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuccessCallback)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFailureCallback)
   tmp->mArrayBuffer = nullptr;
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
--- a/content/media/webaudio/PannerNode.cpp
+++ b/content/media/webaudio/PannerNode.cpp
@@ -10,16 +10,18 @@
 #include "AudioListener.h"
 #include "AudioBufferSourceNode.h"
 
 namespace mozilla {
 namespace dom {
 
 using namespace std;
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(PannerNode)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PannerNode)
   if (tmp->Context()) {
     tmp->Context()->UnregisterPannerNode(tmp);
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(AudioNode)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PannerNode, AudioNode)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/content/media/webaudio/ScriptProcessorNode.cpp
+++ b/content/media/webaudio/ScriptProcessorNode.cpp
@@ -15,16 +15,18 @@
 #include "nsCxPusher.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/PodOperations.h"
 #include <deque>
 
 namespace mozilla {
 namespace dom {
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(ScriptProcessorNode)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ScriptProcessorNode)
   if (tmp->Context()) {
     tmp->Context()->UnregisterScriptProcessorNode(tmp);
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(AudioNode)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ScriptProcessorNode, AudioNode)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/content/media/webaudio/WaveShaperNode.cpp
+++ b/content/media/webaudio/WaveShaperNode.cpp
@@ -9,16 +9,18 @@
 #include "AudioNode.h"
 #include "AudioNodeEngine.h"
 #include "AudioNodeStream.h"
 #include "mozilla/PodOperations.h"
 
 namespace mozilla {
 namespace dom {
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(WaveShaperNode)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WaveShaperNode, AudioNode)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   tmp->ClearCurve();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WaveShaperNode, AudioNode)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/content/media/webspeech/synth/SpeechSynthesis.cpp
+++ b/content/media/webspeech/synth/SpeechSynthesis.cpp
@@ -38,16 +38,18 @@ namespace dom {
 static PLDHashOperator
 TraverseCachedVoices(const nsAString& aKey, SpeechSynthesisVoice* aEntry, void* aData)
 {
   nsCycleCollectionTraversalCallback* cb = static_cast<nsCycleCollectionTraversalCallback*>(aData);
   cb->NoteXPCOMChild(aEntry);
   return PL_DHASH_NEXT;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(SpeechSynthesis)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SpeechSynthesis)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCurrentTask)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   tmp->mVoiceCache.Clear();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(SpeechSynthesis)
--- a/content/svg/content/nsISVGPoint.cpp
+++ b/content/svg/content/nsISVGPoint.cpp
@@ -16,16 +16,18 @@
 // See the architecture comment in DOMSVGPointList.h.
 
 using namespace mozilla;
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our list's weak ref to us to be safe. (The other option would be to
 // not unlink and rely on the breaking of the other edges in the cycle, as
 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPoint)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPoint)
   // We may not belong to a list, so we must null check tmp->mList.
   if (tmp->mList) {
     tmp->mList->mItems[tmp->mListIndex] = nullptr;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/svg/content/src/DOMSVGLength.cpp
+++ b/content/svg/content/src/DOMSVGLength.cpp
@@ -16,16 +16,18 @@
 // See the architecture comment in DOMSVGAnimatedLengthList.h.
 
 namespace mozilla {
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our list's weak ref to us to be safe. (The other option would be to
 // not unlink and rely on the breaking of the other edges in the cycle, as
 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGLength)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGLength)
   // We may not belong to a list, so we must null check tmp->mList.
   if (tmp->mList) {
     tmp->mList->mItems[tmp->mListIndex] = nullptr;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGLength)
--- a/content/svg/content/src/DOMSVGLengthList.cpp
+++ b/content/svg/content/src/DOMSVGLengthList.cpp
@@ -35,16 +35,18 @@ void UpdateListIndicesFromIndex(Fallible
 } // namespace
 
 namespace mozilla {
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our DOMSVGAnimatedLengthList's weak ref to us to be safe. (The other
 // option would be to not unlink and rely on the breaking of the other edges in
 // the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGLengthList)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGLengthList)
   if (tmp->mAList) {
     if (tmp->IsAnimValList()) {
       tmp->mAList->mAnimVal = nullptr;
     } else {
       tmp->mAList->mBaseVal = nullptr;
     }
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mAList)
--- a/content/svg/content/src/DOMSVGNumber.cpp
+++ b/content/svg/content/src/DOMSVGNumber.cpp
@@ -15,16 +15,18 @@
 // See the architecture comment in DOMSVGAnimatedNumberList.h.
 
 using namespace mozilla;
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our list's weak ref to us to be safe. (The other option would be to
 // not unlink and rely on the breaking of the other edges in the cycle, as
 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGNumber)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGNumber)
   // We may not belong to a list, so we must null check tmp->mList.
   if (tmp->mList) {
     tmp->mList->mItems[tmp->mListIndex] = nullptr;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGNumber)
--- a/content/svg/content/src/DOMSVGNumberList.cpp
+++ b/content/svg/content/src/DOMSVGNumberList.cpp
@@ -35,16 +35,18 @@ void UpdateListIndicesFromIndex(Fallible
 }
 
 } // namespace
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our DOMSVGAnimatedNumberList's weak ref to us to be safe. (The other
 // option would be to not unlink and rely on the breaking of the other edges in
 // the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGNumberList)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGNumberList)
   if (tmp->mAList) {
     if (tmp->IsAnimValList()) {
       tmp->mAList->mAnimVal = nullptr;
     } else {
       tmp->mAList->mBaseVal = nullptr;
     }
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mAList)
--- a/content/svg/content/src/DOMSVGPathSeg.cpp
+++ b/content/svg/content/src/DOMSVGPathSeg.cpp
@@ -15,16 +15,18 @@
 // See the architecture comment in DOMSVGPathSegList.h.
 
 using namespace mozilla;
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our list's weak ref to us to be safe. (The other option would be to
 // not unlink and rely on the breaking of the other edges in the cycle, as
 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPathSeg)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPathSeg)
   // We may not belong to a list, so we must null check tmp->mList.
   if (tmp->mList) {
     tmp->mList->ItemAt(tmp->mListIndex) = nullptr;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/svg/content/src/DOMSVGPathSegList.cpp
+++ b/content/svg/content/src/DOMSVGPathSegList.cpp
@@ -22,16 +22,18 @@ namespace mozilla {
 nsSVGAttrTearoffTable<void, DOMSVGPathSegList>&
 SVGPathSegListTearoffTable()
 {
   static nsSVGAttrTearoffTable<void, DOMSVGPathSegList>
     sSVGPathSegListTearoffTable;
   return sSVGPathSegListTearoffTable;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPathSegList)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPathSegList)
   // No unlinking of mElement, we'd need to null out the value pointer (the
   // object it points to is held by the element) and null-check it everywhere.
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPathSegList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
--- a/content/svg/content/src/DOMSVGPointList.cpp
+++ b/content/svg/content/src/DOMSVGPointList.cpp
@@ -40,16 +40,18 @@ namespace mozilla {
 nsSVGAttrTearoffTable<void, DOMSVGPointList>&
 SVGPointListTearoffTable()
 {
   static nsSVGAttrTearoffTable<void, DOMSVGPointList>
     sSVGPointListTearoffTable;
   return sSVGPointListTearoffTable;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPointList)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPointList)
   // No unlinking of mElement, we'd need to null out the value pointer (the
   // object it points to is held by the element) and null-check it everywhere.
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPointList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
--- a/content/svg/content/src/DOMSVGTransformList.cpp
+++ b/content/svg/content/src/DOMSVGTransformList.cpp
@@ -34,16 +34,18 @@ void UpdateListIndicesFromIndex(
 namespace mozilla {
 
 using namespace dom;
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our SVGAnimatedTransformList's weak ref to us to be safe. (The other
 // option would be to not unlink and rely on the breaking of the other edges in
 // the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGTransformList)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGTransformList)
   if (tmp->mAList) {
     if (tmp->IsAnimValList()) {
       tmp->mAList->mAnimVal = nullptr;
     } else {
       tmp->mAList->mBaseVal = nullptr;
     }
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mAList)
--- a/content/svg/content/src/SVGAnimationElement.cpp
+++ b/content/svg/content/src/SVGAnimationElement.cpp
@@ -20,16 +20,18 @@ namespace dom {
 NS_IMPL_ADDREF_INHERITED(SVGAnimationElement, SVGAnimationElementBase)
 NS_IMPL_RELEASE_INHERITED(SVGAnimationElement, SVGAnimationElementBase)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SVGAnimationElement)
   NS_INTERFACE_MAP_ENTRY(mozilla::dom::SVGTests)
 NS_INTERFACE_MAP_END_INHERITING(SVGAnimationElementBase)
 
 // Cycle collection magic -- based on nsSVGUseElement
+NS_IMPL_CYCLE_COLLECTION_CLASS(SVGAnimationElement)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGAnimationElement,
                                                 SVGAnimationElementBase)
   tmp->mHrefTarget.Unlink();
   tmp->mTimedElement.Unlink();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGAnimationElement,
                                                   SVGAnimationElementBase)
--- a/content/svg/content/src/SVGMPathElement.cpp
+++ b/content/svg/content/src/SVGMPathElement.cpp
@@ -24,16 +24,18 @@ SVGMPathElement::WrapNode(JSContext *aCx
 }
 
 nsSVGElement::StringInfo SVGMPathElement::sStringInfo[1] =
 {
   { &nsGkAtoms::href, kNameSpaceID_XLink, false }
 };
 
 // Cycle collection magic -- based on nsSVGUseElement
+NS_IMPL_CYCLE_COLLECTION_CLASS(SVGMPathElement)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGMPathElement,
                                                 SVGMPathElementBase)
   tmp->UnlinkHrefTarget(false);
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGMPathElement,
                                                   SVGMPathElementBase)
   tmp->mHrefTarget.Traverse(&cb);
--- a/content/svg/content/src/SVGSVGElement.cpp
+++ b/content/svg/content/src/SVGSVGElement.cpp
@@ -123,16 +123,18 @@ nsSVGElement::EnumInfo SVGSVGElement::sE
     sZoomAndPanMap,
     SVG_ZOOMANDPAN_MAGNIFY
   }
 };
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(SVGSVGElement)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGSVGElement,
                                                 SVGSVGElementBase)
   if (tmp->mTimedDocumentRoot) {
     tmp->mTimedDocumentRoot->Unlink();
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGSVGElement,
                                                   SVGSVGElementBase)
--- a/content/svg/content/src/SVGStyleElement.cpp
+++ b/content/svg/content/src/SVGStyleElement.cpp
@@ -26,20 +26,23 @@ NS_IMPL_ADDREF_INHERITED(SVGStyleElement
 NS_IMPL_RELEASE_INHERITED(SVGStyleElement, SVGStyleElementBase)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(SVGStyleElement)
   NS_INTERFACE_TABLE_INHERITED3(SVGStyleElement, nsIDOMLinkStyle,
                                 nsIStyleSheetLinkingElement,
                                 nsIMutationObserver)
 NS_INTERFACE_TABLE_TAIL_INHERITING(SVGStyleElementBase)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(SVGStyleElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGStyleElement,
                                                   SVGStyleElementBase)
   tmp->nsStyleLinkElement::Traverse(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGStyleElement,
                                                 SVGStyleElementBase)
   tmp->nsStyleLinkElement::Unlink();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 //----------------------------------------------------------------------
 // Implementation
 
--- a/content/svg/content/src/SVGTransform.cpp
+++ b/content/svg/content/src/SVGTransform.cpp
@@ -24,16 +24,18 @@ SVGMatrixTearoffTable()
 }
 
 //----------------------------------------------------------------------
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our list's weak ref to us to be safe. (The other option would be to
 // not unlink and rely on the breaking of the other edges in the cycle, as
 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
+NS_IMPL_CYCLE_COLLECTION_CLASS(SVGTransform)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SVGTransform)
   // We may not belong to a list, so we must null check tmp->mList.
   if (tmp->mList) {
     tmp->mList->mItems[tmp->mListIndex] = nullptr;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/svg/content/src/SVGUseElement.cpp
+++ b/content/svg/content/src/SVGUseElement.cpp
@@ -39,16 +39,18 @@ nsSVGElement::LengthInfo SVGUseElement::
 nsSVGElement::StringInfo SVGUseElement::sStringInfo[1] =
 {
   { &nsGkAtoms::href, kNameSpaceID_XLink, true }
 };
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(SVGUseElement)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGUseElement,
                                                 SVGUseElementBase)
   nsAutoScriptBlocker scriptBlocker;
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOriginal)
   tmp->DestroyAnonymousContent();
   tmp->UnlinkSource();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGUseElement,
--- a/content/svg/content/src/nsISVGPoint.cpp
+++ b/content/svg/content/src/nsISVGPoint.cpp
@@ -14,16 +14,18 @@
 // See the architecture comment in DOMSVGPointList.h.
 
 using namespace mozilla;
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our list's weak ref to us to be safe. (The other option would be to
 // not unlink and rely on the breaking of the other edges in the cycle, as
 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsISVGPoint)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsISVGPoint)
   // We may not belong to a list, so we must null check tmp->mList.
   if (tmp->mList) {
     tmp->mList->mItems[tmp->mListIndex] = nullptr;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -682,22 +682,24 @@ NS_NewSVG##_elementName##Element(nsICont
   it.forget(aResult);                                                        \
                                                                              \
   return rv;                                                                 \
 }
 
 // No unlinking, we'd need to null out the value pointer (the object it
 // points to is held by the element) and null-check it everywhere.
 #define NS_SVG_VAL_IMPL_CYCLE_COLLECTION(_val, _element)                     \
+NS_IMPL_CYCLE_COLLECTION_CLASS(_val)                                         \
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_val)                                \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_element) \
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                                        \
 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(_val)
 
 #define NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(_val, _element)       \
+NS_IMPL_CYCLE_COLLECTION_CLASS(_val)                                         \
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_val)                                  \
 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER                            \
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                          \
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_val)                                \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_element)                                \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS                           \
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                                        \
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_val)                                   \
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -180,16 +180,18 @@ SetOrRemoveObject(PLDHashTable& table, n
 }
 
 // Implementation /////////////////////////////////////////////////////////////////
 
 // Static member variable initialization
 
 // Implement our nsISupports methods
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsBindingManager)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsBindingManager)
   tmp->mDestroyed = true;
 
   if (tmp->mBoundContentSet.IsInitialized())
     tmp->mBoundContentSet.Clear();
 
   if (tmp->mDocumentTable.IsInitialized())
     tmp->mDocumentTable.Clear();
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -155,16 +155,18 @@ nsXBLBinding::~nsXBLBinding(void)
 {
   if (mContent) {
     nsXBLBinding::UninstallAnonymousContent(mContent->OwnerDoc(), mContent);
   }
   nsXBLDocumentInfo* info = mPrototypeBinding->XBLDocumentInfo();
   NS_RELEASE(info);
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLBinding)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLBinding)
   // XXX Probably can't unlink mPrototypeBinding->XBLDocumentInfo(), because
   //     mPrototypeBinding is weak.
   if (tmp->mContent) {
     nsXBLBinding::UninstallAnonymousContent(tmp->mContent->OwnerDoc(),
                                             tmp->mContent);
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContent)
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -247,19 +247,21 @@ nsXBLDocGlobalObject::EnsureScriptEnviro
 
   mScriptContext = newCtx;
 
   AutoPushJSContext cx(mScriptContext->GetNativeContext());
 
   JS_SetErrorReporter(cx, xpc::SystemErrorReporter);
 
   JS::CompartmentOptions options;
-  options.setZone(JS::SystemZone);
+  options.setZone(JS::SystemZone)
+         .setInvisibleToDebugger(true);
   mJSObject = JS_NewGlobalObject(cx, &gSharedGlobalClass,
                                  nsJSPrincipals::get(GetPrincipal()),
+                                 JS::DontFireOnNewGlobalHook,
                                  options);
   if (!mJSObject)
       return NS_OK;
 
   // Set the location information for the new global, so that tools like
   // about:memory may use that information
   nsIURI *ownerURI = mGlobalObjectOwner->DocumentURI();
   xpc::SetLocationForGlobal(mJSObject, ownerURI);
@@ -389,16 +391,18 @@ static bool
 TraceProtos(nsHashKey *aKey, void *aData, void* aClosure)
 {
   ProtoTracer* closure = static_cast<ProtoTracer*>(aClosure);
   nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
   proto->Trace(closure->mCallbacks, closure->mClosure);
   return kHashEnumerateNext;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
   if (tmp->mBindingTable) {
     tmp->mBindingTable->Enumerate(UnlinkProtoJSObjects, nullptr);
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobalObject)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo)
--- a/content/xml/content/src/XMLStylesheetProcessingInstruction.cpp
+++ b/content/xml/content/src/XMLStylesheetProcessingInstruction.cpp
@@ -18,20 +18,23 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION
                                 nsIStyleSheetLinkingElement)
 NS_INTERFACE_TABLE_TAIL_INHERITING(ProcessingInstruction)
 
 NS_IMPL_ADDREF_INHERITED(XMLStylesheetProcessingInstruction,
                          ProcessingInstruction)
 NS_IMPL_RELEASE_INHERITED(XMLStylesheetProcessingInstruction,
                           ProcessingInstruction)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(XMLStylesheetProcessingInstruction)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XMLStylesheetProcessingInstruction,
                                                   ProcessingInstruction)
   tmp->nsStyleLinkElement::Traverse(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XMLStylesheetProcessingInstruction,
                                                 ProcessingInstruction)
   tmp->nsStyleLinkElement::Unlink();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
 XMLStylesheetProcessingInstruction::~XMLStylesheetProcessingInstruction()
 {
--- a/content/xml/document/src/nsXMLContentSink.cpp
+++ b/content/xml/document/src/nsXMLContentSink.cpp
@@ -135,16 +135,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_INTERFACE_MAP_ENTRY(nsIXMLContentSink)
   NS_INTERFACE_MAP_ENTRY(nsIExpatSink)
   NS_INTERFACE_MAP_ENTRY(nsITransformObserver)
 NS_INTERFACE_MAP_END_INHERITING(nsContentSink)
 
 NS_IMPL_ADDREF_INHERITED(nsXMLContentSink, nsContentSink)
 NS_IMPL_RELEASE_INHERITED(nsXMLContentSink, nsContentSink)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLContentSink)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLContentSink,
                                                   nsContentSink)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentHead)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocElement)
   for (uint32_t i = 0, count = tmp->mContentStack.Length(); i < count; i++) {
     const StackNode& node = tmp->mContentStack.ElementAt(i);
     cb.NoteXPCOMChild(node.mContent);
   }
--- a/content/xml/document/src/nsXMLFragmentContentSink.cpp
+++ b/content/xml/document/src/nsXMLFragmentContentSink.cpp
@@ -137,16 +137,18 @@ nsXMLFragmentContentSink::~nsXMLFragment
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLFragmentContentSink)
   NS_INTERFACE_MAP_ENTRY(nsIFragmentContentSink)
 NS_INTERFACE_MAP_END_INHERITING(nsXMLContentSink)
 
 NS_IMPL_ADDREF_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink)
 NS_IMPL_RELEASE_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLFragmentContentSink)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLFragmentContentSink,
                                                   nsXMLContentSink)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTargetDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMETHODIMP 
 nsXMLFragmentContentSink::WillBuildModel(nsDTDMode aDTDMode)
--- a/content/xslt/src/xpath/nsXPathResult.cpp
+++ b/content/xslt/src/xpath/nsXPathResult.cpp
@@ -41,16 +41,18 @@ nsXPathResult::nsXPathResult(const nsXPa
     }
 }
 
 nsXPathResult::~nsXPathResult()
 {
     RemoveObserver();
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXPathResult)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXPathResult)
     {
         tmp->RemoveObserver();
     }
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXPathResult)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
--- a/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp
+++ b/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp
@@ -286,16 +286,18 @@ private:
     nsCOMPtr<nsIVariant> mValue;
     nsRefPtr<txAExprResult> mTxValue;
 };
 
 /**
  * txMozillaXSLTProcessor
  */
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(txMozillaXSLTProcessor)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(txMozillaXSLTProcessor)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mEmbeddedStylesheetRoot)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mSource)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrincipal)
     tmp->mVariables.clear();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(txMozillaXSLTProcessor)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEmbeddedStylesheetRoot)
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -318,16 +318,18 @@ NS_TrustedNewXULElement(nsIContent** aRe
 
     // Create an nsXULElement with the specified namespace and tag.
     NS_ADDREF(*aResult = new nsXULElement(aNodeInfo));
 }
 
 //----------------------------------------------------------------------
 // nsISupports interface
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULElement)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULElement,
                                                   nsStyledElement)
     {
         nsXULSlots* slots = static_cast<nsXULSlots*>(tmp->GetExistingSlots());
         if (slots) {
             slots->Traverse(cb);
         }
     }
@@ -1924,16 +1926,18 @@ nsXULElement::IsEventAttributeName(nsIAt
 }
 
 JSObject*
 nsXULElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aScope)
 {
     return dom::XULElementBinding::Wrap(aCx, aScope, this);
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeNode)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULPrototypeNode)
     if (tmp->mType == nsXULPrototypeNode::eType_Element) {
         static_cast<nsXULPrototypeElement*>(tmp)->Unlink();
     }
     else if (tmp->mType == nsXULPrototypeNode::eType_Script) {
         static_cast<nsXULPrototypeScript*>(tmp)->UnlinkJSObjects();
     }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/xul/document/src/XULDocument.cpp
+++ b/content/xul/document/src/XULDocument.cpp
@@ -309,16 +309,18 @@ TraverseObservers(nsIURI* aKey, nsIObser
         static_cast<nsCycleCollectionTraversalCallback*>(aContext);
 
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mOverlayLoadObservers/mPendingOverlayLoadNotifications value");
     cb->NoteXPCOMChild(aData);
 
     return PL_DHASH_NEXT;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(XULDocument)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XULDocument, XMLDocument)
     NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration()),
                  "Shouldn't traverse XULDocument!");
     // XXX tmp->mForwardReferences?
     // XXX tmp->mContextStack?
 
     // An element will only have a template builder as long as it's in the
     // document, so we'll traverse the table here instead of from the element.
--- a/content/xul/document/src/nsXULCommandDispatcher.cpp
+++ b/content/xul/document/src/nsXULCommandDispatcher.cpp
@@ -65,16 +65,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
     NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMXULCommandDispatcher)
     NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULCommandDispatcher)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULCommandDispatcher)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULCommandDispatcher)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULCommandDispatcher)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULCommandDispatcher)
   tmp->Disconnect();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULCommandDispatcher)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
   Updater* updater = tmp->mUpdaters;
   while (updater) {
--- a/content/xul/document/src/nsXULContentSink.cpp
+++ b/content/xul/document/src/nsXULContentSink.cpp
@@ -185,16 +185,18 @@ XULContentSinkImpl::~XULContentSinkImpl(
     mContextStack.Clear();
 
     moz_free(mText);
 }
 
 //----------------------------------------------------------------------
 // nsISupports interface
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(XULContentSinkImpl)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XULContentSinkImpl)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNodeInfoManager)
   tmp->mContextStack.Clear();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrototype)
   NS_IF_RELEASE(tmp->mParser);
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XULContentSinkImpl)
--- a/content/xul/document/src/nsXULControllers.cpp
+++ b/content/xul/document/src/nsXULControllers.cpp
@@ -57,16 +57,18 @@ NS_NewXULControllers(nsISupports* aOuter
   
   nsresult rv;
   NS_ADDREF(controllers);
   rv = controllers->QueryInterface(aIID, aResult);
   NS_RELEASE(controllers);
   return rv;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULControllers)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULControllers)
   tmp->DeleteControllers();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULControllers)
   {
     uint32_t i, count = tmp->mControllers.Length();
     for (i = 0; i < count; ++i) {
       nsXULControllerData* controllerData = tmp->mControllers[i];
--- a/content/xul/document/src/nsXULPrototypeDocument.cpp
+++ b/content/xul/document/src/nsXULPrototypeDocument.cpp
@@ -154,16 +154,18 @@ nsXULPrototypeDocument::~nsXULPrototypeD
         mRoot->ReleaseSubtree();
 
     if (--gRefCnt == 0) {
         NS_IF_RELEASE(gSystemPrincipal);
         NS_IF_RELEASE(gSystemGlobal);
     }
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeDocument)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULPrototypeDocument)
     tmp->mPrototypeWaiters.Clear();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPrototypeDocument)
     if (nsCCUncollectableMarker::InGeneration(cb, tmp->mCCGeneration)) {
         return NS_SUCCESS_INTERRUPTED_TRAVERSE;
     }
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
@@ -713,16 +715,18 @@ nsXULPDGlobalObject::nsXULPDGlobalObject
 {
 }
 
 
 nsXULPDGlobalObject::~nsXULPDGlobalObject()
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPDGlobalObject)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsXULPDGlobalObject)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPDGlobalObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULPDGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
@@ -754,20 +758,22 @@ nsXULPDGlobalObject::EnsureScriptEnviron
   MOZ_ASSERT(ctxNew);
 
   // We have to setup a special global object.  We do this then
   // attach it as the global for this context.  Then, we
   // will re-fetch the global and set it up in our language globals array.
   {
     AutoPushJSContext cx(ctxNew->GetNativeContext());
     JS::CompartmentOptions options;
-    options.setZone(JS::SystemZone);
+    options.setZone(JS::SystemZone)
+           .setInvisibleToDebugger(true);
     JS::Rooted<JSObject*> newGlob(cx,
       JS_NewGlobalObject(cx, &gSharedGlobalClass,
-                         nsJSPrincipals::get(GetPrincipal()), options));
+                         nsJSPrincipals::get(GetPrincipal()), JS::DontFireOnNewGlobalHook,
+                         options));
     if (!newGlob)
         return NS_OK;
 
     js::SetDefaultObjectForContext(cx, newGlob);
 
     // Add an owning reference from JS back to us. This'll be
     // released when the JSObject is finalized.
     ::JS_SetPrivate(newGlob, this);
--- a/content/xul/templates/src/nsXMLBinding.cpp
+++ b/content/xul/templates/src/nsXMLBinding.cpp
@@ -5,16 +5,18 @@
 
 #include "nsXULTemplateQueryProcessorXML.h"
 #include "nsXULTemplateResultXML.h"
 #include "nsXMLBinding.h"
 
 NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(nsXMLBindingSet)
 NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(nsXMLBindingSet)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLBindingSet)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXMLBindingSet)
   nsXMLBinding* binding = tmp->mFirst;
   while (binding) {
     binding->mExpr = nullptr;
     binding = binding->mNext;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
--- a/content/xul/templates/src/nsXULTemplateBuilder.cpp
+++ b/content/xul/templates/src/nsXULTemplateBuilder.cpp
@@ -229,16 +229,18 @@ TraverseMatchList(nsISupports* aKey, nsT
         cb->NoteXPCOMChild(match->GetContainer());
         cb->NoteXPCOMChild(match->mResult);
         match = match->mNext;
     }
 
     return PL_DHASH_NEXT;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateBuilder)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateBuilder)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDataSource)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDB)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mCompDB)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootResult)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mListeners)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mQueryProcessor)
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp
@@ -41,16 +41,18 @@ static NS_DEFINE_CID(kRDFServiceCID,    
 #define PARSE_TYPE_INTEGER  "Integer"
 
 nsrefcnt                  nsXULTemplateQueryProcessorRDF::gRefCnt = 0;
 nsIRDFService*            nsXULTemplateQueryProcessorRDF::gRDFService;
 nsIRDFContainerUtils*     nsXULTemplateQueryProcessorRDF::gRDFContainerUtils;
 nsIRDFResource*           nsXULTemplateQueryProcessorRDF::kNC_BookmarkSeparator;
 nsIRDFResource*           nsXULTemplateQueryProcessorRDF::kRDF_type;
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorRDF)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorRDF)
     tmp->Done();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 static PLDHashOperator
 BindingDependenciesTraverser(nsISupports* key,
                              nsXULTemplateQueryProcessorRDF::ResultArray* array,
                              void* userArg)
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
@@ -81,16 +81,18 @@ TraverseRuleToBindingsMap(nsISupports* a
         static_cast<nsCycleCollectionTraversalCallback*>(aContext);
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap key");
     cb->NoteXPCOMChild(aKey);
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap value");
     cb->NoteNativeChild(aMatch, NS_CYCLE_COLLECTION_PARTICIPANT(nsXMLBindingSet));
     return PL_DHASH_NEXT;
 }
   
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorXML)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorXML)
     if (tmp->mRuleToBindingsMap.IsInitialized()) {
         tmp->mRuleToBindingsMap.Clear();
     }
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mEvaluator)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mTemplateBuilder)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequest)
--- a/dom/apps/src/AppsUtils.jsm
+++ b/dom/apps/src/AppsUtils.jsm
@@ -477,16 +477,40 @@ this.AppsUtils = {
       if (!checkNameAndDev(aManifest1.locales[locale],
                            aManifest2.locales[locale])) {
         return false;
       }
     }
 
     // Nothing failed.
     return true;
+  },
+
+  // Returns the MD5 hash of a string.
+  computeHash: function(aString) {
+    let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
+                      .createInstance(Ci.nsIScriptableUnicodeConverter);
+    converter.charset = "UTF-8";
+    let result = {};
+    // Data is an array of bytes.
+    let data = converter.convertToByteArray(aString, result);
+
+    let hasher = Cc["@mozilla.org/security/hash;1"]
+                   .createInstance(Ci.nsICryptoHash);
+    hasher.init(hasher.MD5);
+    hasher.update(data, data.length);
+    // We're passing false to get the binary hash and not base64.
+    let hash = hasher.finish(false);
+
+    function toHexString(charCode) {
+      return ("0" + charCode.toString(16)).slice(-2);
+    }
+
+    // Convert the binary hash data to a hex string.
+    return [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");
   }
 }
 
 /**
  * Helper object to access manifest information with locale support
  */
 this.ManifestHelper = function(aManifest, aOrigin) {
   this._origin = Services.io.newURI(aOrigin, null, null);
--- a/dom/apps/src/FreeSpaceWatcher.jsm
+++ b/dom/apps/src/FreeSpaceWatcher.jsm
@@ -48,18 +48,24 @@ this.FreeSpaceWatcher = {
             let newStatus = freeBytes > aThreshold;
             if (newStatus != callback.currentStatus) {
               debug("New status: " + (newStatus ? "free" : "full"));
               aOnStatusChange(newStatus ? "free" : "full");
               callback.currentStatus = newStatus;
             }
           };
 
-          let deviceStorage = Services.wm.getMostRecentWindow("navigator:browser")
-                                         .navigator.getDeviceStorage("apps");
+          let navigator = Services.wm.getMostRecentWindow("navigator:browser")
+                                  .navigator;
+          let deviceStorage = null;
+
+          if (navigator.getDeviceStorage) {
+            deviceStorage = navigator.getDeviceStorage("apps");
+          }
+
           if (deviceStorage) {
             let req = deviceStorage.freeSpace();
             req.onsuccess = req.onerror = function statResult(e) {
               if (!e.target.result) {
                 return;
               }
 
               let freeBytes = e.target.result;
--- a/dom/apps/src/Webapps.js
+++ b/dom/apps/src/Webapps.js
@@ -113,51 +113,57 @@ WebappsRegistry.prototype = {
         Services.DOMRequest.fireError(aRequest, "BACKGROUND_APP");
       }
     }
     Services.tm.currentThread.dispatch(runnable,
                                        Ci.nsIThread.DISPATCH_NORMAL);
     return false;
   },
 
-  // mozIDOMApplicationRegistry implementation
-
-  install: function(aURL, aParams) {
-    let uri = this._validateURL(aURL);
-
-    let request = this.createRequest();
-
-    if (!this._ensureForeground(request)) {
-      return request;
-    }
-
+  _prepareInstall: function(aURL, aRequest, aParams, isPackage) {
     let installURL = this._window.location.href;
-    let requestID = this.getRequestId(request);
+    let requestID = this.getRequestId(aRequest);
     let receipts = (aParams && aParams.receipts &&
                     Array.isArray(aParams.receipts)) ? aParams.receipts
                                                      : [];
     let categories = (aParams && aParams.categories &&
                       Array.isArray(aParams.categories)) ? aParams.categories
                                                          : [];
 
     let principal = this._window.document.nodePrincipal;
-    cpmm.sendAsyncMessage("Webapps:Install",
-                          { app: {
-                              installOrigin: this._getOrigin(installURL),
-                              origin: this._getOrigin(uri),
-                              manifestURL: uri,
-                              receipts: receipts,
-                              categories: categories
-                            },
-                            from: installURL,
-                            oid: this._id,
-                            requestID: requestID,
-                            appId: principal.appId,
-                            isBrowser: principal.isInBrowserElement
-                          });
+
+    return { app: {
+                    installOrigin: this._getOrigin(installURL),
+                    origin: this._getOrigin(aURL),
+                    manifestURL: aURL,
+                    receipts: receipts,
+                    categories: categories
+                  },
+
+             from: installURL,
+             oid: this._id,
+             requestID: requestID,
+             appId: principal.appId,
+             isBrowser: principal.isInBrowserElement,
+             isPackage: isPackage
+           };
+  },
+
+  // mozIDOMApplicationRegistry implementation
+
+  install: function(aURL, aParams) {
+    let uri = this._validateURL(aURL);
+
+    let request = this.createRequest();
+
+    if (this._ensureForeground(request)) {
+      cpmm.sendAsyncMessage("Webapps:Install",
+                            this._prepareInstall(uri, request, aParams, false));
+    }
+
     return request;
   },
 
   getSelf: function() {
     let request = this.createRequest();
     cpmm.sendAsyncMessage("Webapps:GetSelf", { origin: this._getOrigin(this._window.location.href),
                                                appId: this._window.document.nodePrincipal.appId,
                                                oid: this._id,
@@ -196,52 +202,26 @@ WebappsRegistry.prototype = {
   },
 
   uninit: function() {
     this._mgmt = null;
     cpmm.sendAsyncMessage("Webapps:UnregisterForMessages",
                           ["Webapps:Install:Return:OK"]);
   },
 
-  // mozIDOMApplicationRegistry2 implementation
-
   installPackage: function(aURL, aParams) {
     let uri = this._validateURL(aURL);
 
     let request = this.createRequest();
 
-    if (!this._ensureForeground(request)) {
-      return request;
+    if (this._ensureForeground(request)) {
+      cpmm.sendAsyncMessage("Webapps:InstallPackage",
+                            this._prepareInstall(uri, request, aParams, true));
     }
 
-    let installURL = this._window.location.href;
-    let requestID = this.getRequestId(request);
-    let receipts = (aParams && aParams.receipts &&
-                    Array.isArray(aParams.receipts)) ? aParams.receipts
-                                                     : [];
-    let categories = (aParams && aParams.categories &&
-                      Array.isArray(aParams.categories)) ? aParams.categories
-                                                         : [];
-
-    let principal = this._window.document.nodePrincipal;
-    cpmm.sendAsyncMessage("Webapps:InstallPackage",
-                          { app: {
-                              installOrigin: this._getOrigin(installURL),
-                              origin: this._getOrigin(uri),
-                              manifestURL: uri,
-                              receipts: receipts,
-                              categories: categories
-                            },
-                            from: installURL,
-                            oid: this._id,
-                            requestID: requestID,
-                            isPackage: true,
-                            appId: principal.appId,
-                            isBrowser: principal.isInBrowserElement
-                          });
     return request;
   },
 
   // nsIDOMGlobalPropertyInitializer implementation
   init: function(aWindow) {
     this.initDOMRequestHelper(aWindow, ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
                               "Webapps:GetInstalled:Return:OK",
                               "Webapps:GetSelf:Return:OK",
@@ -261,32 +241,23 @@ WebappsRegistry.prototype = {
     // the mgmt object.
     this.hasMgmtPrivilege = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
   },
 
   classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference,
                                          Ci.mozIDOMApplicationRegistry,
-#ifdef MOZ_B2G
                                          Ci.mozIDOMApplicationRegistry2,
-#elifdef MOZ_WIDGET_ANDROID
-                                         Ci.mozIDOMApplicationRegistry2,
-#endif
                                          Ci.nsIDOMGlobalPropertyInitializer]),
 
   classInfo: XPCOMUtils.generateCI({classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
                                     contractID: "@mozilla.org/webapps;1",
                                     interfaces: [Ci.mozIDOMApplicationRegistry,
-#ifdef MOZ_B2G
-                                                 Ci.mozIDOMApplicationRegistry2,
-#elifdef MOZ_WIDGET_ANDROID
-                                                 Ci.mozIDOMApplicationRegistry2,
-#endif
-                                                 ],
+                                                 Ci.mozIDOMApplicationRegistry2],
                                     flags: Ci.nsIClassInfo.DOM_OBJECT,
                                     classDescription: "Webapps Registry"})
 }
 
 /**
   * mozIDOMApplication object
   */
 
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -15,16 +15,17 @@ Cu.import("resource://gre/modules/XPCOMU
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import('resource://gre/modules/ActivitiesService.jsm');
 Cu.import("resource://gre/modules/AppsUtils.jsm");
 Cu.import("resource://gre/modules/PermissionsInstaller.jsm");
 Cu.import("resource://gre/modules/OfflineCacheInstaller.jsm");
 Cu.import("resource://gre/modules/SystemMessagePermissionsChecker.jsm");
 Cu.import("resource://gre/modules/AppDownloadManager.jsm");
+Cu.import("resource://gre/modules/WebappOSUtils.jsm");
 
 #ifdef MOZ_WIDGET_GONK
 XPCOMUtils.defineLazyGetter(this, "libcutils", function() {
   Cu.import("resource://gre/modules/systemlibs.js");
   return libcutils;
 });
 #endif
 
@@ -1367,36 +1368,17 @@ this.DOMApplicationRegistry = {
         debug("Error opening " + aFile.path);
         aCallback(null);
       }
     );
   },
 
   // Returns the MD5 hash of the manifest.
   computeManifestHash: function(aManifest) {
-    let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
-                      .createInstance(Ci.nsIScriptableUnicodeConverter);
-    converter.charset = "UTF-8";
-    let result = {};
-    // Data is an array of bytes.
-    let data = converter.convertToByteArray(JSON.stringify(aManifest), result);
-
-    let hasher = Cc["@mozilla.org/security/hash;1"]
-                   .createInstance(Ci.nsICryptoHash);
-    hasher.init(hasher.MD5);
-    hasher.update(data, data.length);
-    // We're passing false to get the binary hash and not base64.
-    let hash = hasher.finish(false);
-
-    function toHexString(charCode) {
-      return ("0" + charCode.toString(16)).slice(-2);
-    }
-
-    // Convert the binary hash data to a hex string.
-    return [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");
+    return AppsUtils.computeHash(JSON.stringify(aManifest));
   },
 
   // Updates the redirect mapping, activities and system message handlers.
   // aOldManifest can be null if we don't have any handler to unregister.
   updateAppHandlers: function(aOldManifest, aNewManifest, aApp) {
     debug("updateAppHandlers: old=" + aOldManifest + " new=" + aNewManifest);
     this.notifyAppsRegistryStart();
     if (aApp.appStatus >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
@@ -1771,23 +1753,16 @@ this.DOMApplicationRegistry = {
 
     let sendError = function sendError(aError) {
       aData.error = aError;
       aMm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
       Cu.reportError("Error installing app from: " + app.installOrigin +
                      ": " + aError);
     }.bind(this);
 
-    // Disallow reinstalls from the same origin for now.
-    // See https://bugzilla.mozilla.org/show_bug.cgi?id=821288
-    if (this._appId(app.origin) !== null && this._isLaunchable(app.origin)) {
-      sendError("REINSTALL_FORBIDDEN");
-      return;
-    }
-
     // Hosted apps can't be trusted or certified, so just check that the
     // manifest doesn't ask for those.
     function checkAppStatus(aManifest) {
       let manifestStatus = aManifest.type || "web";
       return manifestStatus === "web";
     }
 
     let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
@@ -1807,16 +1782,28 @@ this.DOMApplicationRegistry = {
         }
 
         app.manifest = xhr.response;
         if (!app.manifest) {
           sendError("MANIFEST_PARSE_ERROR");
           return;
         }
 
+        // Disallow multiple hosted apps installations from the same origin for now.
+        // We will remove this code after multiple apps per origin are supported (bug 778277).
+        // This will also disallow reinstalls from the same origin for now.
+        for (let id in this.webapps) {
+          if (this.webapps[id].origin == app.origin &&
+              !this.webapps[id].packageHash &&
+              this._isLaunchable(this.webapps[id])) {
+            sendError("MULTIPLE_APPS_PER_ORIGIN_FORBIDDEN");
+            return;
+          }
+        }
+
         if (!AppsUtils.checkManifest(app.manifest, app)) {
           sendError("INVALID_MANIFEST");
         } else if (!AppsUtils.checkInstallAllowed(app.manifest, app.installOrigin)) {
           sendError("INSTALL_FROM_DENIED");
         } else if (!checkAppStatus(app.manifest)) {
           sendError("INVALID_SECURITY_LEVEL");
         } else {
           app.etag = xhr.getResponseHeader("Etag");
@@ -1849,25 +1836,16 @@ this.DOMApplicationRegistry = {
 
     let sendError = function sendError(aError) {
       aData.error = aError;
       aMm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
       Cu.reportError("Error installing packaged app from: " +
                      app.installOrigin + ": " + aError);
     }.bind(this);
 
-    // Disallow reinstalls from the same manifest URL for now.
-    // See https://bugzilla.mozilla.org/show_bug.cgi?id=821288
-    if (this.getAppLocalIdByManifestURL(app.manifestURL) !==
-        Ci.nsIScriptSecurityManager.NO_APP_ID ||
-        this._appId(app.origin) !== null) {
-      sendError("REINSTALL_FORBIDDEN");
-      return;
-    }
-
     let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
                 .createInstance(Ci.nsIXMLHttpRequest);
     xhr.open("GET", app.manifestURL, true);
     xhr.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
     xhr.channel.notificationCallbacks = this.createLoadContext(aData.appId,
                                                                aData.isBrowser);
     xhr.responseType = "json";
 
@@ -1880,16 +1858,23 @@ this.DOMApplicationRegistry = {
         }
 
         let manifest = app.updateManifest = xhr.response;
         if (!manifest) {
           sendError("MANIFEST_PARSE_ERROR");
           return;
         }
 
+        // Disallow reinstalls from the same manifest URL for now.
+        if (this._appIdForManifestURL(app.manifestURL) !== null &&
+            this._isLaunchable(app)) {
+          sendError("REINSTALL_FORBIDDEN");
+          return;
+        }
+
         if (!(AppsUtils.checkManifest(manifest, app) &&
               manifest.package_path)) {
           sendError("INVALID_MANIFEST");
         } else if (!AppsUtils.checkInstallAllowed(manifest, app.installOrigin)) {
           sendError("INSTALL_FROM_DENIED");
         } else {
           app.etag = xhr.getResponseHeader("Etag");
           app.manifestHash = this.computeManifestHash(manifest);
@@ -1996,17 +1981,17 @@ this.DOMApplicationRegistry = {
     appObject.installTime = app.installTime = Date.now();
     appObject.lastUpdateCheck = app.lastUpdateCheck = Date.now();
     let appNote = JSON.stringify(appObject);
     appNote.id = id;
 
     appObject.id = id;
     appObject.localId = localId;
     appObject.basePath = FileUtils.getDir(DIRECTORY_NAME, ["webapps"], true, true).path;
-    let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
+    let dir = this._getAppDir(id);
     let manFile = dir.clone();
     manFile.append(manifestName);
     let jsonManifest = aData.isPackage ? app.updateManifest : app.manifest;
     this._writeFile(manFile, JSON.stringify(jsonManifest), function() { });
 
     let manifest = new ManifestHelper(jsonManifest, app.origin);
 
     if (manifest.appcache_path) {
@@ -2070,29 +2055,29 @@ this.DOMApplicationRegistry = {
         this.broadcastMessage("Webapps:Install:Return:OK", aData);
         Services.obs.notifyObservers(this, "webapps-sync-install", appNote);
       }).bind(this));
     }
 
     if (!aData.isPackage) {
       this.updateAppHandlers(null, app.manifest, app);
       if (aInstallSuccessCallback) {
-        aInstallSuccessCallback(manifest);
+        aInstallSuccessCallback(app.manifest);
       }
     }
 
     if (manifest.package_path) {
       // origin for install apps is meaningless here, since it's app:// and this
       // can't be used to resolve package paths.
       manifest = new ManifestHelper(jsonManifest, app.manifestURL);
       this.downloadPackage(manifest, appObject, false, (function(aId, aManifest) {
         // Success! Move the zip out of TmpD.
         let app = DOMApplicationRegistry.webapps[aId];
         let zipFile = FileUtils.getFile("TmpD", ["webapps", aId, "application.zip"], true);
-        let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", aId], true, true);
+        let dir = this._getAppDir(id);
         zipFile.moveTo(dir, "application.zip");
         let tmpDir = FileUtils.getDir("TmpD", ["webapps", aId], true, true);
         try {
           tmpDir.remove(true);
         } catch(e) { }
 
         // Save the manifest
         let manFile = dir.clone();
@@ -2696,18 +2681,24 @@ this.DOMApplicationRegistry = {
              aApp.downloadSize + AppDownloadManager.MIN_REMAINING_FREESPACE) {
            cleanup("INSUFFICIENT_STORAGE");
            return;
          }
        }
        download();
     };
 
-    let deviceStorage = Services.wm.getMostRecentWindow("navigator:browser")
-                                .navigator.getDeviceStorage("apps");
+    let navigator = Services.wm.getMostRecentWindow("navigator:browser")
+                            .navigator;
+    let deviceStorage = null;
+
+    if (navigator.getDeviceStorage) {
+      deviceStorage = navigator.getDeviceStorage("apps");
+    }
+
     if (deviceStorage) {
       let req = deviceStorage.freeSpace();
       req.onsuccess = req.onerror = function statResult(e) {
         // Even if we could not retrieve the device storage free space, we try
         // to download the package.
         if (!e.target.result) {
           download();
           return;
@@ -2816,17 +2807,17 @@ this.DOMApplicationRegistry = {
       return;
     }
 
     let tmp = [];
 
     for (let id in this.webapps) {
       if (this.webapps[id].origin == aData.origin &&
           this.webapps[id].localId == aData.appId &&
-          this._isLaunchable(this.webapps[id].origin)) {
+          this._isLaunchable(this.webapps[id])) {
         let app = AppsUtils.cloneAppObject(this.webapps[id]);
         aData.apps.push(app);
         tmp.push({ id: id });
         break;
       }
     }
 
     if (!aData.apps.length) {
@@ -2863,17 +2854,17 @@ this.DOMApplicationRegistry = {
   },
 
   getInstalled: function(aData, aMm) {
     aData.apps = [];
     let tmp = [];
 
     for (let id in this.webapps) {
       if (this.webapps[id].installOrigin == aData.origin &&
-          this._isLaunchable(this.webapps[id].origin)) {
+          this._isLaunchable(this.webapps[id])) {
         aData.apps.push(AppsUtils.cloneAppObject(this.webapps[id]));
         tmp.push({ id: id });
       }
     }
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
@@ -2881,17 +2872,17 @@ this.DOMApplicationRegistry = {
     }).bind(this));
   },
 
   getNotInstalled: function(aData, aMm) {
     aData.apps = [];
     let tmp = [];
 
     for (let id in this.webapps) {
-      if (!this._isLaunchable(this.webapps[id].origin)) {
+      if (!this._isLaunchable(this.webapps[id])) {
         aData.apps.push(AppsUtils.cloneAppObject(this.webapps[id]));
         tmp.push({ id: id });
       }
     }
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
@@ -2908,17 +2899,17 @@ this.DOMApplicationRegistry = {
 
   getAll: function(aCallback) {
     debug("getAll");
     let apps = [];
     let tmp = [];
 
     for (let id in this.webapps) {
       let app = AppsUtils.cloneAppObject(this.webapps[id]);
-      if (!this._isLaunchable(app.origin))
+      if (!this._isLaunchable(app))
         continue;
 
       apps.push(app);
       tmp.push({ id: id });
     }
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
@@ -3061,68 +3052,21 @@ this.DOMApplicationRegistry = {
     }
 
     // Clear the manifest cache.
     this._manifestCache = { };
 
     this._saveApps(aCallback);
   },
 
-  _isLaunchable: function(aOrigin) {
+  _isLaunchable: function(aApp) {
     if (this.allAppsLaunchable)
       return true;
 
-#ifdef XP_WIN
-    let uninstallKey = Cc["@mozilla.org/windows-registry-key;1"]
-                         .createInstance(Ci.nsIWindowsRegKey);
-    try {
-      uninstallKey.open(uninstallKey.ROOT_KEY_CURRENT_USER,
-                        "SOFTWARE\\Microsoft\\Windows\\" +
-                        "CurrentVersion\\Uninstall\\" +
-                        aOrigin,
-                        uninstallKey.ACCESS_READ);
-      uninstallKey.close();
-      return true;
-    } catch (ex) {
-      return false;
-    }
-#elifdef XP_MACOSX
-    let mwaUtils = Cc["@mozilla.org/widget/mac-web-app-utils;1"]
-                     .createInstance(Ci.nsIMacWebAppUtils);
-
-    return !!mwaUtils.pathForAppWithIdentifier(aOrigin);
-#elifdef XP_UNIX
-    let env = Cc["@mozilla.org/process/environment;1"]
-                .getService(Ci.nsIEnvironment);
-    let xdg_data_home_env;
-    try {
-      xdg_data_home_env = env.get("XDG_DATA_HOME");
-    } catch(ex) {
-    }
-
-    let desktopINI;
-    if (xdg_data_home_env) {
-      desktopINI = new FileUtils.File(xdg_data_home_env);
-    } else {
-      desktopINI = FileUtils.getFile("Home", [".local", "share"]);
-    }
-    desktopINI.append("applications");
-
-    let origin = Services.io.newURI(aOrigin, null, null);
-    let uniqueName = origin.scheme + ";" +
-                     origin.host +
-                     (origin.port != -1 ? ";" + origin.port : "");
-
-    desktopINI.append("owa-" + uniqueName + ".desktop");
-
-    return desktopINI.exists();
-#else
-    return true;
-#endif
-
+    return WebappOSUtils.isLaunchable(aApp);
   },
 
   _notifyCategoryAndObservers: function(subject, topic, data,  msg) {
     const serviceMarker = "service,";
 
     // First create observers from the category manager.
     let cm =
       Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
--- a/dom/apps/src/moz.build
+++ b/dom/apps/src/moz.build
@@ -2,23 +2,20 @@
 # vim: set filetype=python:
 # 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/.
 
 EXTRA_COMPONENTS += [
     'AppsService.js',
     'AppsService.manifest',
+    'Webapps.js',
     'Webapps.manifest',
 ]
 
-EXTRA_PP_COMPONENTS += [
-    'Webapps.js',
-]
-
 EXTRA_JS_MODULES += [
     'AppDownloadManager.jsm',
     'AppsServiceChild.jsm',
     'FreeSpaceWatcher.jsm',
     'OfflineCacheInstaller.jsm',
     'PermissionsInstaller.jsm',
     'PermissionsTable.jsm',
 ]
--- a/dom/base/DOMRequest.cpp
+++ b/dom/base/DOMRequest.cpp
@@ -42,16 +42,18 @@ DOMRequest::DOMRequest()
 void
 DOMRequest::Init(nsIDOMWindow* aWindow)
 {
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
   BindToOwner(window->IsInnerWindow() ? window.get() :
                                         window->GetCurrentInnerWindow());
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMRequest)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DOMRequest,
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMRequest,
                                                 nsDOMEventTargetHelper)
   if (tmp->mRooted) {
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -122,16 +122,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNavigator)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigator)
   NS_INTERFACE_MAP_ENTRY(nsIMozNavigatorNetwork)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Navigator)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Navigator)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(Navigator)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Navigator)
   tmp->Invalidate();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins)
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -15,17 +15,16 @@
 #include "nsIDocument.h"
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMHTMLFrameElement.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMHTMLMapElement.h"
-#include "nsIDOMHTMLLegendElement.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMRange.h"
 #include "nsIHTMLDocument.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsLayoutUtils.h"
 #include "nsIPresShell.h"
 #include "nsIContentViewer.h"
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -497,16 +497,18 @@ nsTimeout::~nsTimeout()
   if (mTimer) {
     mTimer->Cancel();
     mTimer = nullptr;
   }
 
   MOZ_COUNT_DTOR(nsTimeout);
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsTimeout)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsTimeout)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsTimeout)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrincipal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptHandler)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTimeout, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTimeout, Release)
@@ -1607,16 +1609,18 @@ inline void
 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
                             IdleObserverHolder& aField,
                             const char* aName,
                             unsigned aFlags)
 {
   CycleCollectionNoteChild(aCallback, aField.mIdleObserver.get(), aName, aFlags);
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindow)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
     char name[512];
     PR_snprintf(name, sizeof(name), "nsGlobalWindow #%ld", tmp->mWindowID);
     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
   } else {
     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindow, tmp->mRefCnt.get())
   }
@@ -11411,16 +11415,18 @@ nsGlobalWindow::SyncGamepadState()
   FORWARD_TO_INNER_VOID(SyncGamepadState, ());
   if (mHasSeenGamepadInput) {
     mGamepads.EnumerateRead(EnumGamepadsForSync, NULL);
   }
 }
 #endif
 // nsGlobalChromeWindow implementation
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow,
                                                   nsGlobalWindow)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserDOMWindow)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalChromeWindow,
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1181,18 +1181,21 @@ nsJSContext::DestroyJSContext()
     PokeGC(JS::gcreason::NSJSCONTEXT_DESTROY);
   }
 
   JS_DestroyContextNoGC(mContext);
   mContext = nullptr;
 }
 
 // QueryInterface implementation for nsJSContext
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSContext)
+
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSContext)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSContext)
   NS_ASSERTION(!tmp->mContext || !js::ContextHasOutstandingRequests(tmp->mContext),
                "Trying to unlink a context with outstanding requests.");
   tmp->mIsInitialized = false;
   tmp->mGCOnDestruction = false;
   if (tmp->mContext) {
     JSAutoRequest ar(tmp->mContext);
     js::SetDefaultObjectForContext(tmp->mContext, nullptr);
@@ -3596,16 +3599,18 @@ nsJSArgArray::ReleaseJSObjects()
   }
   if (mArgc > 0) {
     mArgc = 0;
     NS_DROP_JS_OBJECTS(this, nsJSArgArray);
   }
 }
 
 // QueryInterface implementation for nsJSArgArray
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSArgArray)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSArgArray)
   tmp->ReleaseJSObjects();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSArgArray)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSArgArray)
--- a/dom/base/nsJSTimeoutHandler.cpp
+++ b/dom/base/nsJSTimeoutHandler.cpp
@@ -73,16 +73,18 @@ private:
   // Note this is always a flat string.
   JS::Heap<JSString*> mExpr;
   nsRefPtr<Function> mFunction;
 };
 
 
 // nsJSScriptTimeoutHandler
 // QueryInterface implementation for nsJSScriptTimeoutHandler
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSScriptTimeoutHandler)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSScriptTimeoutHandler)
   tmp->ReleaseJSObjects();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSScriptTimeoutHandler)
   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
     nsAutoCString name("nsJSScriptTimeoutHandler");
     if (tmp->mExpr) {
       name.AppendLiteral(" [");
--- a/dom/base/nsWrapperCache.h
+++ b/dom/base/nsWrapperCache.h
@@ -344,52 +344,56 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperC
   tmp->ReleaseWrapper(p);
 
 #define NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class) \
   NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class)              \
     NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER        \
   NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 #define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(_class) \
+  NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)         \
     NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER   \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_END                   \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)       \
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS    \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                 \
   NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
 
 #define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(_class, _field) \
+  NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                        \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                 \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field)                     \
     NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER           \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_END                           \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)               \
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field)                   \
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS            \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                         \
   NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
 
 #define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(_class, _field1,\
                                                 _field2)        \
+  NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                        \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                 \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field1)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field2)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER           \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_END                           \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)               \
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field1)                  \
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field2)                  \
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS            \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                         \
   NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
 
 #define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_3(_class, _field1,\
                                                 _field2,        \
                                                 _field3)        \
+  NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                        \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                 \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field1)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field2)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field3)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER           \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_END                           \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)               \
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field1)                  \
@@ -398,16 +402,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperC
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS            \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                         \
   NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
 
 #define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_4(_class, _field1,\
                                                 _field2,        \
                                                 _field3,        \
                                                 _field4)        \
+  NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                        \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                 \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field1)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field2)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field3)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field4)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER           \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_END                           \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)               \
@@ -419,16 +424,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperC
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                         \
   NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
 
 #define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_5(_class, _field1,\
                                                 _field2,        \
                                                 _field3,        \
                                                 _field4,        \
                                                 _field5)        \
+  NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                        \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                 \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field1)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field2)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field3)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field4)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field5)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER           \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_END                           \
@@ -443,16 +449,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperC
   NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
 
 #define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_6(_class, _field1,\
                                                 _field2,        \
                                                 _field3,        \
                                                 _field4,        \
                                                 _field5,        \
                                                 _field6)        \
+  NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                        \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                 \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field1)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field2)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field3)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field4)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field5)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field6)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER           \
@@ -470,16 +477,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperC
 
 #define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_7(_class, _field1,\
                                                 _field2,        \
                                                 _field3,        \
                                                 _field4,        \
                                                 _field5,        \
                                                 _field6,        \
                                                 _field7)        \
+  NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                        \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                 \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field1)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field2)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field3)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field4)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field5)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field6)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field7)                    \
@@ -500,16 +508,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperC
 #define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_8(_class, _field1,\
                                                 _field2,        \
                                                 _field3,        \
                                                 _field4,        \
                                                 _field5,        \
                                                 _field6,        \
                                                 _field7,        \
                                                 _field8)        \
+  NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                        \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                 \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field1)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field2)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field3)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field4)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field5)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field6)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field7)                    \
@@ -533,16 +542,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperC
                                                 _field2,        \
                                                 _field3,        \
                                                 _field4,        \
                                                 _field5,        \
                                                 _field6,        \
                                                 _field7,        \
                                                 _field8,        \
                                                 _field9)        \
+  NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                        \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                 \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field1)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field2)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field3)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field4)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field5)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field6)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field7)                    \
@@ -569,16 +579,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperC
                                                  _field3,       \
                                                  _field4,       \
                                                  _field5,       \
                                                  _field6,       \
                                                  _field7,       \
                                                  _field8,       \
                                                  _field9,       \
                                                  _field10)      \
+  NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                        \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                 \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field1)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field2)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field3)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field4)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field5)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field6)                    \
     NS_IMPL_CYCLE_COLLECTION_UNLINK(_field7)                    \
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -21,16 +21,18 @@ namespace dom {
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CallbackObject)
   NS_INTERFACE_MAP_ENTRY(mozilla::dom::CallbackObject)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(CallbackObject)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(CallbackObject)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(CallbackObject)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CallbackObject)
   tmp->DropCallback();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CallbackObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CallbackObject)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCallback)
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -10305,16 +10305,20 @@ struct PrototypeIDMap;
         curr = CGWrapper(curr, post='\n')
 
         # Add the includes
         defineIncludes = [CGHeaders.getDeclarationFilename(desc.interface)
                           for desc in config.getDescriptors(hasInterfaceObject=True,
                                                             workers=False,
                                                             register=True)]
         defineIncludes.append('nsScriptNameSpaceManager.h')
+        defineIncludes.extend([CGHeaders.getDeclarationFilename(desc.interface)
+                               for desc in config.getDescriptors(isNavigatorProperty=True,
+                                                                 workers=False,
+                                                                 register=True)])
         curr = CGHeaders([], [], [], [], [], defineIncludes, 'RegisterBindings',
                          curr)
 
         # Add include guards.
         curr = CGIncludeGuard('RegisterBindings', curr)
 
         # Done.
         return curr
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -28,16 +28,18 @@
 #include "MediaPlayStatus.h"
 
 using namespace mozilla;
 
 USING_BLUETOOTH_NAMESPACE
 
 DOMCI_DATA(BluetoothAdapter, BluetoothAdapter)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
+
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothAdapter,
                                                nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsUuids)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsDeviceAddresses)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter, 
                                                   nsDOMEventTargetHelper)
--- a/dom/bluetooth/BluetoothDevice.cpp
+++ b/dom/bluetooth/BluetoothDevice.cpp
@@ -15,16 +15,18 @@
 #include "nsTArrayHelpers.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 
 USING_BLUETOOTH_NAMESPACE
 
 DOMCI_DATA(BluetoothDevice, BluetoothDevice)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothDevice)
+
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothDevice,
                                                nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsUuids)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsServices)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothDevice,
                                                   nsDOMEventTargetHelper)
--- a/dom/gamepad/GamepadService.cpp
+++ b/dom/gamepad/GamepadService.cpp
@@ -208,26 +208,30 @@ GamepadService::NewButtonEvent(uint32_t 
     --i;
 
     // Only send events to non-background windows
     if (!listeners[i]->GetOuterWindow() ||
         listeners[i]->GetOuterWindow()->IsBackground()) {
       continue;
     }
 
+    bool first_time = false;
     if (!WindowHasSeenGamepad(listeners[i], aIndex)) {
-      SetWindowHasSeenGamepad(listeners[i], aIndex);
       // This window hasn't seen this gamepad before, so
       // send a connection event first.
-      NewConnectionEvent(aIndex, true);
+      SetWindowHasSeenGamepad(listeners[i], aIndex);
+      first_time = true;
     }
 
     nsRefPtr<Gamepad> gamepad = listeners[i]->GetGamepad(aIndex);
     if (gamepad) {
       gamepad->SetButton(aButton, aPressed, aValue);
+      if (first_time) {
+        FireConnectionEvent(listeners[i], gamepad, true);
+      }
       if (mNonstandardEventsEnabled) {
         // Fire event
         FireButtonEvent(listeners[i], gamepad, aButton, aValue);
       }
     }
   }
 }
 
@@ -268,26 +272,30 @@ GamepadService::NewAxisMoveEvent(uint32_
     --i;
 
     // Only send events to non-background windows
     if (!listeners[i]->GetOuterWindow() ||
         listeners[i]->GetOuterWindow()->IsBackground()) {
       continue;
     }
 
+    bool first_time = false;
     if (!WindowHasSeenGamepad(listeners[i], aIndex)) {
-      SetWindowHasSeenGamepad(listeners[i], aIndex);
       // This window hasn't seen this gamepad before, so
       // send a connection event first.
-      NewConnectionEvent(aIndex, true);
+      SetWindowHasSeenGamepad(listeners[i], aIndex);
+      first_time = true;
     }
 
     nsRefPtr<Gamepad> gamepad = listeners[i]->GetGamepad(aIndex);
     if (gamepad) {
       gamepad->SetAxis(aAxis, aValue);
+      if (first_time) {
+        FireConnectionEvent(listeners[i], gamepad, true);
+      }
       if (mNonstandardEventsEnabled) {
         // Fire event
         FireAxisMoveEvent(listeners[i], gamepad, aAxis, aValue);
       }
     }
   }
 }
 
@@ -323,23 +331,24 @@ GamepadService::NewConnectionEvent(uint3
   nsTArray<nsRefPtr<nsGlobalWindow> > listeners(mListeners);
 
   if (aConnected) {
     for (uint32_t i = listeners.Length(); i > 0 ; ) {
       --i;
 
       // Only send events to non-background windows
       if (!listeners[i]->GetOuterWindow() ||
-          listeners[i]->GetOuterWindow()->IsBackground())
+          listeners[i]->GetOuterWindow()->IsBackground()) {
         continue;
+      }
 
       // We don't fire a connected event here unless the window
       // has seen input from at least one device.
-      if (aConnected && !listeners[i]->HasSeenGamepadInput()) {
-        return;
+      if (!listeners[i]->HasSeenGamepadInput()) {
+        continue;
       }
 
       SetWindowHasSeenGamepad(listeners[i], aIndex);
 
       nsRefPtr<Gamepad> gamepad = listeners[i]->GetGamepad(aIndex);
       if (gamepad) {
         // Fire event
         FireConnectionEvent(listeners[i], gamepad, aConnected);
@@ -355,19 +364,16 @@ GamepadService::NewConnectionEvent(uint3
       // deal with the hassle of syncing the state of removed gamepads.
 
       if (WindowHasSeenGamepad(listeners[i], aIndex)) {
         nsRefPtr<Gamepad> gamepad = listeners[i]->GetGamepad(aIndex);
         if (gamepad) {
           gamepad->SetConnected(false);
           // Fire event
           FireConnectionEvent(listeners[i], gamepad, false);
-        }
-
-        if (gamepad) {
           listeners[i]->RemoveGamepad(aIndex);
         }
       }
     }
   }
 }
 
 void
--- a/dom/gamepad/GamepadService.h
+++ b/dom/gamepad/GamepadService.h
@@ -42,40 +42,58 @@ class GamepadService : public nsIObserve
   void RemoveListener(nsGlobalWindow* aWindow);
 
   // Add a gamepad to the list of known gamepads, and return its index.
   uint32_t AddGamepad(const char* aID, GamepadMappingType aMapping,
                       uint32_t aNumButtons, uint32_t aNumAxes);
   // Remove the gamepad at |aIndex| from the list of known gamepads.
   void RemoveGamepad(uint32_t aIndex);
 
+  // Update the state of |aButton| for the gamepad at |aIndex| for all
+  // windows that are listening and visible, and fire one of
+  // a gamepadbutton{up,down} event at them as well.
   // aPressed is used for digital buttons, aValue is for analog buttons.
   void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed,
                       double aValue);
   // When only a digital button is available the value will be synthesized.
   void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed);
+
+  // Update the state of |aAxis| for the gamepad at |aIndex| for all
+  // windows that are listening and visible, and fire a gamepadaxismove
+  // event at them as well.
   void NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis, double aValue);
 
   // Synchronize the state of |aGamepad| to match the gamepad stored at |aIndex|
   void SyncGamepadState(uint32_t aIndex, Gamepad* aGamepad);
 
  protected:
   GamepadService();
   virtual ~GamepadService() {};
   void StartCleanupTimer();
 
+  // Fire a gamepadconnected or gamepaddisconnected event for the gamepad
+  // at |aIndex| to all windows that are listening and have received
+  // gamepad input.
   void NewConnectionEvent(uint32_t aIndex, bool aConnected);
+
+  // Fire a gamepadaxismove event to the window at |aTarget| for |aGamepad|.
   void FireAxisMoveEvent(EventTarget* aTarget,
                          Gamepad* aGamepad,
                          uint32_t axis,
                          double value);
+
+  // Fire one of gamepadbutton{up,down} event at the window at |aTarget| for
+  // |aGamepad|.
   void FireButtonEvent(EventTarget* aTarget,
                        Gamepad* aGamepad,
                        uint32_t aButton,
                        double aValue);
+
+  // Fire one of gamepad{connected,disconnected} event at the window at
+  // |aTarget| for |aGamepad|.
   void FireConnectionEvent(EventTarget* aTarget,
                            Gamepad* aGamepad,
                            bool aConnected);
 
   // true if this feature is enabled in preferences
   bool mEnabled;
   // true if non-standard events are enabled in preferences
   bool mNonstandardEventsEnabled;
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -441,16 +441,18 @@ IDBCursor::ContinueInternal(const Key& a
     NS_WARNING("Failed to dispatch!");
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     return;
   }
 
   mContinueCalled = true;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(IDBCursor)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBCursor)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObjectStore)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndex)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -456,16 +456,18 @@ IDBDatabase::CreateObjectStoreInternal(I
                     "MT IDBDatabase.createObjectStore()",
                     IDB_PROFILER_STRING(this),
                     IDB_PROFILER_STRING(aTransaction),
                     IDB_PROFILER_STRING(objectStore));
 
   return objectStore.forget();
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(IDBDatabase)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBDatabase, IDBWrapperCache)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFactory)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBDatabase, IDBWrapperCache)
   // Don't unlink mFactory!
 
   // Do some cleanup.
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -492,16 +492,18 @@ IDBFactory::SetDatabaseMetadata(Database
 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBFactory)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBFactory)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBFactory)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(IDBFactory)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBFactory)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBFactory)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   if (tmp->mOwningObject) {
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -780,16 +780,18 @@ IDBIndex::OpenCursorFromChildProcess(
   NS_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   NS_ASSERTION(!cloneInfo.mCloneBuffer.data(), "Should have swapped!");
 
   cursor.forget(_retval);
   return NS_OK;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(IDBIndex)
+
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBIndex)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedKeyPath)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBIndex)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObjectStore)
--- a/dom/indexedDB/IDBKeyRange.cpp
+++ b/dom/indexedDB/IDBKeyRange.cpp
@@ -190,16 +190,17 @@ IDBKeyRange::ToSerializedKeyRange(T& aKe
   aKeyRange.isOnly() = IsOnly();
 
   aKeyRange.lower() = Lower();
   if (!IsOnly()) {
     aKeyRange.upper() = Upper();
   }
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(IDBKeyRange)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBKeyRange)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBKeyRange)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedLowerVal)
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -530,17 +530,18 @@ class ThreadLocalJSRuntime
      */
     JS_SetNativeStackQuota(mRuntime, 128 * sizeof(size_t) * 1024); 
 
     mContext = JS_NewContext(mRuntime, 0);
     NS_ENSURE_TRUE(mContext, NS_ERROR_OUT_OF_MEMORY);
 
     JSAutoRequest ar(mContext);
 
-    mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, NULL);
+    mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, NULL,
+                                 JS::FireOnNewGlobalHook);
     NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY);
 
     js::SetDefaultObjectForContext(mContext, mGlobal);
     return NS_OK;
   }
 
  public:
   static ThreadLocalJSRuntime *Create()
@@ -2384,16 +2385,18 @@ IDBObjectStore::Index(const nsAString& a
       aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
       return nullptr;
     }
   }
 
   return retval.forget();
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(IDBObjectStore)
+
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBObjectStore)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedKeyPath)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBObjectStore)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction)
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -271,16 +271,18 @@ IDBRequest::GetError(mozilla::ErrorResul
   if (!mHaveResultOrErrorCode) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
 
   return mError;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(IDBRequest)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBRequest, IDBWrapperCache)
   // Don't need NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS because
   // nsDOMEventTargetHelper does it for us.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSource)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
@@ -350,16 +352,18 @@ IDBOpenDBRequest::SetTransaction(IDBTran
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   NS_ASSERTION(!aTransaction || !mTransaction,
                "Shouldn't have a transaction here!");
 
   mTransaction = aTransaction;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(IDBOpenDBRequest)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBOpenDBRequest,
                                                   IDBRequest)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFactory)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBOpenDBRequest,
                                                 IDBRequest)
   // Don't unlink mFactory!
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -598,16 +598,18 @@ nsresult
 IDBTransaction::Abort(nsresult aErrorCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   nsRefPtr<DOMError> error = new DOMError(GetOwner(), aErrorCode);
   return AbortInternal(aErrorCode, error.forget());
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(IDBTransaction)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBTransaction,
                                                   IDBWrapperCache)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDatabase)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCreatedObjectStores)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeletedObjectStores)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
--- a/dom/indexedDB/IDBWrapperCache.cpp
+++ b/dom/indexedDB/IDBWrapperCache.cpp
@@ -4,16 +4,18 @@
  * 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 "IDBWrapperCache.h"
 #include "nsContentUtils.h"
 
 USING_INDEXEDDB_NAMESPACE
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(IDBWrapperCache)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBWrapperCache,
                                                   nsDOMEventTargetHelper)
   // Don't need NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS because
   // nsDOMEventTargetHelper does it for us.
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBWrapperCache,
                                                 nsDOMEventTargetHelper)
--- a/dom/interfaces/apps/nsIDOMApplicationRegistry.idl
+++ b/dom/interfaces/apps/nsIDOMApplicationRegistry.idl
@@ -133,17 +133,17 @@ interface mozIDOMApplicationMgmt : nsISu
    *
    * @param app : the app object of the web app to be uninstalled.
    * @returns   : A DOMRequest object, returning the app's origin in |result|
    *              if uninstall succeeds; returning "NOT_INSTALLED" error otherwise.
    */
   nsIDOMDOMRequest uninstall(in mozIDOMApplication app);
 };
 
-[scriptable, uuid(abfc6c15-8b92-4b9a-b892-52e6ae76f379)]
+[scriptable, uuid(52710c5f-b2a2-4b27-b5b9-f679a1bcc79b)]
 interface mozIDOMApplicationRegistry : nsISupports
 {
   /**
    * Install a web app.
    *
    * @param manifestUrl : the URL of the webapps manifest.
    * @param parameters  : A structure with optional information.
    *                      {
@@ -164,10 +164,23 @@ interface mozIDOMApplicationRegistry : n
    */
   nsIDOMDOMRequest checkInstalled(in DOMString manifestUrl);
 
   /**
    * the request will return the applications installed from this origin, or null.
    */
   nsIDOMDOMRequest getInstalled();
 
+  /**
+   * Install a packaged web app.
+   *
+   * @param packageUrl : the URL of the webapps manifest.
+   * @param parameters : A structure with optional information.
+   *                      {
+   *                       receipts: ...    Will be used to specify the payment receipts for this installation.
+   *                       categories: ...  Will be used to specify the categories of the webapp.
+   *                      }
+   * @returns          : A DOMRequest object, returning the app object in |result| if install succeeds.
+   */
+  nsIDOMDOMRequest installPackage(in DOMString packageUrl, [optional] in jsval parameters);
+
   readonly attribute mozIDOMApplicationMgmt mgmt;
 };
--- a/dom/interfaces/apps/nsIDOMApplicationRegistry2.idl
+++ b/dom/interfaces/apps/nsIDOMApplicationRegistry2.idl
@@ -1,24 +1,13 @@
 /* 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 "nsIDOMApplicationRegistry.idl"
 
 interface nsIDOMDOMRequest;
 
-[scriptable, uuid(34498a66-3aee-4b80-8b8b-a9c5d5ba32b6)]
+// This interface is still here for backwards compatibility.
+[scriptable, uuid(5bd838b2-cf3d-406e-bbef-f633cf9e68de)]
 interface mozIDOMApplicationRegistry2 : mozIDOMApplicationRegistry
 {
-  /**
-   * Install a packaged web app.
-   *
-   * @param packageUrl : the URL of the webapps manifest.
-   * @param parameters : A structure with optional information.
-   *                      {
-   *                       receipts: ...    Will be used to specify the payment receipts for this installation.
-   *                       categories: ...  Will be used to specify the categories of the webapp.
-   *                      }
-   * @returns          : A DOMRequest object, returning the app object in |result| if install succeeds.
-   */
-  nsIDOMDOMRequest installPackage(in DOMString packageUrl, [optional] in jsval parameters);
 };
--- a/dom/interfaces/base/domstubs.idl
+++ b/dom/interfaces/base/domstubs.idl
@@ -68,17 +68,16 @@ interface nsIDOMMozCSSKeyframeRule;
 interface nsIDOMCSSFontFeatureValuesRule;
 interface nsIDOMCSSStyleSheet;
 interface nsIDOMCSSStyleDeclaration;
 interface nsIDOMCounter;
 interface nsIDOMRect;
 interface nsIDOMCSSStyleRule;
 interface nsIDOMCSSStyleRuleCollection;
 interface nsIDOMHTMLTableCaptionElement;
-interface nsIDOMHTMLTableSectionElement;
 
 // Range
 interface nsIDOMRange;
 
 // Crypto
 interface nsIDOMCRMFObject;
 interface nsIDOMCrypto;
 interface nsIDOMPkcs11;
--- a/dom/interfaces/html/moz.build
+++ b/dom/interfaces/html/moz.build
@@ -11,71 +11,58 @@ XPIDL_SOURCES += [
     'nsIDOMHTMLAudioElement.idl',
     'nsIDOMHTMLBRElement.idl',
     'nsIDOMHTMLBaseElement.idl',
     'nsIDOMHTMLBodyElement.idl',
     'nsIDOMHTMLButtonElement.idl',
     'nsIDOMHTMLByteRanges.idl',
     'nsIDOMHTMLCanvasElement.idl',
     'nsIDOMHTMLCollection.idl',
-    'nsIDOMHTMLDListElement.idl',
-    'nsIDOMHTMLDataListElement.idl',
     'nsIDOMHTMLDirectoryElement.idl',
     'nsIDOMHTMLDivElement.idl',
     'nsIDOMHTMLDocument.idl',
     'nsIDOMHTMLElement.idl',
     'nsIDOMHTMLEmbedElement.idl',
     'nsIDOMHTMLFieldSetElement.idl',
-    'nsIDOMHTMLFontElement.idl',
     'nsIDOMHTMLFormElement.idl',
     'nsIDOMHTMLFrameElement.idl',
     'nsIDOMHTMLFrameSetElement.idl',
     'nsIDOMHTMLHRElement.idl',
     'nsIDOMHTMLHeadElement.idl',
     'nsIDOMHTMLHeadingElement.idl',
     'nsIDOMHTMLHtmlElement.idl',
     'nsIDOMHTMLIFrameElement.idl',
     'nsIDOMHTMLImageElement.idl',
     'nsIDOMHTMLInputElement.idl',
     'nsIDOMHTMLLIElement.idl',
     'nsIDOMHTMLLabelElement.idl',
-    'nsIDOMHTMLLegendElement.idl',
     'nsIDOMHTMLLinkElement.idl',
     'nsIDOMHTMLMapElement.idl',
     'nsIDOMHTMLMediaElement.idl',
     'nsIDOMHTMLMenuElement.idl',
     'nsIDOMHTMLMenuItemElement.idl',
     'nsIDOMHTMLMetaElement.idl',
-    'nsIDOMHTMLMeterElement.idl',
-    'nsIDOMHTMLModElement.idl',
     'nsIDOMHTMLOListElement.idl',
     'nsIDOMHTMLObjectElement.idl',
     'nsIDOMHTMLOptGroupElement.idl',
     'nsIDOMHTMLOptionElement.idl',
     'nsIDOMHTMLOptionsCollection.idl',
-    'nsIDOMHTMLOutputElement.idl',
     'nsIDOMHTMLParagraphElement.idl',
-    'nsIDOMHTMLParamElement.idl',
     'nsIDOMHTMLPreElement.idl',
-    'nsIDOMHTMLProgressElement.idl',
     'nsIDOMHTMLQuoteElement.idl',
     'nsIDOMHTMLScriptElement.idl',
     'nsIDOMHTMLSelectElement.idl',
     'nsIDOMHTMLSourceElement.idl',
     'nsIDOMHTMLStyleElement.idl',
     'nsIDOMHTMLTableCaptionElem.idl',
     'nsIDOMHTMLTableCellElement.idl',
-    'nsIDOMHTMLTableColElement.idl',
     'nsIDOMHTMLTableElement.idl',
-    'nsIDOMHTMLTableRowElement.idl',
-    'nsIDOMHTMLTableSectionElement.idl',
     'nsIDOMHTMLTextAreaElement.idl',
     'nsIDOMHTMLTitleElement.idl',
     'nsIDOMHTMLUListElement.idl',
-    'nsIDOMHTMLUnknownElement.idl',
     'nsIDOMHTMLVideoElement.idl',
     'nsIDOMMediaError.idl',
     'nsIDOMMozBrowserFrame.idl',
     'nsIDOMTimeRanges.idl',
     'nsIDOMValidityState.idl',
     'nsIMozBrowserFrame.idl',
 ]
 
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLDListElement.idl
+++ /dev/null
@@ -1,23 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLDListElement interface is the interface to a [X]HTML
- * dl element.
- *
- * This interface is trying to follow the DOM Level 2 HTML specification:
- * http://www.w3.org/TR/DOM-Level-2-HTML/
- *
- * with changes from the work-in-progress WHATWG HTML specification:
- * http://www.whatwg.org/specs/web-apps/current-work/
- */
-
-[scriptable, uuid(edd9338b-f0d5-4825-97d6-6a49862309cc)]
-interface nsIDOMHTMLDListElement : nsIDOMHTMLElement
-{
-           attribute boolean          compact;
-};
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLDataListElement.idl
+++ /dev/null
@@ -1,25 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLDataListElement interface is the interface to a HTML
- * <datalist> element.
- *
- * For more information on this interface, please see
- * http://www.whatwg.org/specs/web-apps/current-work/#the-datalist-element
- *
- * @status UNDER_DEVELOPMENT
- */
-
-interface nsIDOMHTMLCollection;
-
-[scriptable, uuid(528e6a6b-f957-42e1-8d1b-eeeb2fd0b128)]
-interface nsIDOMHTMLDataListElement : nsIDOMHTMLElement
-{
-  readonly attribute nsIDOMHTMLCollection options;
-};
-
--- a/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl
@@ -11,13 +11,13 @@
  *
  * This interface is trying to follow the DOM Level 2 HTML specification:
  * http://www.w3.org/TR/DOM-Level-2-HTML/
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
+// Exists so that | element instanceof Ci.nsIDOMHTMLDirectoryElement | works.
 [scriptable, uuid(cf50373e-e004-4cec-bc65-be9250d9e4c8)]
 interface nsIDOMHTMLDirectoryElement : nsIDOMHTMLElement
 {
-           attribute boolean          compact;
 };
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLFontElement.idl
+++ /dev/null
@@ -1,25 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLFontElement interface is the interface to a [X]HTML
- * font element.
- *
- * This interface is trying to follow the DOM Level 2 HTML specification:
- * http://www.w3.org/TR/DOM-Level-2-HTML/
- *
- * with changes from the work-in-progress WHATWG HTML specification:
- * http://www.whatwg.org/specs/web-apps/current-work/
- */
-
-[scriptable, uuid(e4d86aad-f245-4901-877e-0ae233c5fd37)]
-interface nsIDOMHTMLFontElement : nsIDOMHTMLElement
-{
-           attribute DOMString        color;
-           attribute DOMString        face;
-           attribute DOMString        size;
-};
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLLegendElement.idl
+++ /dev/null
@@ -1,24 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLLegendElement interface is the interface to a [X]HTML
- * legend element.
- *
- * This interface is trying to follow the DOM Level 2 HTML specification:
- * http://www.w3.org/TR/DOM-Level-2-HTML/
- *
- * with changes from the work-in-progress WHATWG HTML specification:
- * http://www.whatwg.org/specs/web-apps/current-work/
- */
-
-[scriptable, uuid(2e4567be-3d91-4df8-bdf9-f3bd96a6cd06)]
-interface nsIDOMHTMLLegendElement : nsIDOMHTMLElement
-{
-  readonly attribute nsIDOMHTMLFormElement form;
-           attribute DOMString             align;
-};
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLMeterElement.idl
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLMeterElement interface is the interface to a HTML
- * <meter> element.
- *
- * For more information on this interface, please see
- * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-meter-element
- */
-
-[scriptable, uuid(6b1fc313-a7c1-4064-ba24-b72e099b05fa)]
-interface nsIDOMHTMLMeterElement : nsIDOMHTMLElement
-{
-           attribute double value;
-           attribute double min;
-           attribute double max;
-           attribute double low;
-           attribute double high;
-           attribute double optimum;
-
-  /**
-   * The labels attribute will be done with bug 556743.
-   */
-  //readonly attribute NodeList labels;
-};
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLModElement.idl
+++ /dev/null
@@ -1,24 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLModElement interface is the interface to a [X]HTML
- * ins and del element.
- *
- * This interface is trying to follow the DOM Level 2 HTML specification:
- * http://www.w3.org/TR/DOM-Level-2-HTML/
- *
- * with changes from the work-in-progress WHATWG HTML specification:
- * http://www.whatwg.org/specs/web-apps/current-work/
- */
-
-[scriptable, uuid(8a1bdf64-19f3-401b-aaea-8c6a5ef1c66f)]
-interface nsIDOMHTMLModElement : nsIDOMHTMLElement
-{
-           attribute DOMString        cite;
-           attribute DOMString        dateTime;
-};
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLOutputElement.idl
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLOutputElement interface is the interface to a HTML
- * <output> element.
- *
- * For more information on this interface, please see
- * http://www.whatwg.org/specs/web-apps/current-work/#the-output-element
- *
- * @status UNDER_DEVELOPMENT
- */
-
-interface nsIDOMValidityState;
-
-[scriptable, uuid(c4bff576-90b5-44b0-8278-bf4e3010b09a)]
-interface nsIDOMHTMLOutputElement : nsIDOMHTMLElement
-{
-  // DOMSettableTokenList
-  readonly attribute nsISupports                htmlFor;
-  readonly attribute nsIDOMHTMLFormElement      form;
-           attribute DOMString                  name;
-
-  readonly attribute DOMString                  type;
-           attribute DOMString                  defaultValue;
-           attribute DOMString                  value;
-
-  readonly attribute boolean                    willValidate;
-  readonly attribute nsIDOMValidityState        validity;
-  readonly attribute DOMString                  validationMessage;
-  boolean  checkValidity();
-  void     setCustomValidity(in DOMString error);
-
-  /**
-   * The labels IDL attribute will be added with bug 556743.
-   */
-  //readonly attribute nsIDOMNodeList             labels;
-};
-
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLParamElement.idl
+++ /dev/null
@@ -1,26 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLParamElement interface is the interface to a [X]HTML
- * param element.
- *
- * This interface is trying to follow the DOM Level 2 HTML specification:
- * http://www.w3.org/TR/DOM-Level-2-HTML/
- *
- * with changes from the work-in-progress WHATWG HTML specification:
- * http://www.whatwg.org/specs/web-apps/current-work/
- */
-
-[scriptable, uuid(f85e1b05-6dc4-442d-bea8-7cf551f9bc9f)]
-interface nsIDOMHTMLParamElement : nsIDOMHTMLElement
-{
-           attribute DOMString        name;
-           attribute DOMString        type;
-           attribute DOMString        value;
-           attribute DOMString        valueType;
-};
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLProgressElement.idl
+++ /dev/null
@@ -1,29 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLProgressElement interface is the interface to a HTML
- * <progress> element.
- *
- * For more information on this interface, please see
- * http://www.whatwg.org/specs/web-apps/current-work/#the-progress-element
- *
- * @status UNDER_DEVELOPMENT
- */
-
-[scriptable, uuid(4b4bec16-c65f-4a08-97d1-dff624efdca4)]
-interface nsIDOMHTMLProgressElement : nsIDOMHTMLElement
-{
-           attribute double value;
-           attribute double max;
-  readonly attribute double position;
-  /**
-   * The labels attribute will be done with bug 567740.
-   */
-  //readonly attribute NodeList labels;
-};
-
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLTableColElement.idl
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLTableColElement interface is the interface to a
- * [X]HTML col element.
- *
- * This interface is trying to follow the DOM Level 2 HTML specification:
- * http://www.w3.org/TR/DOM-Level-2-HTML/
- *
- * with changes from the work-in-progress WHATWG HTML specification:
- * http://www.whatwg.org/specs/web-apps/current-work/
- */
-
-[scriptable, uuid(cd5a5a33-7101-4d32-987c-337c004fce1a)]
-interface nsIDOMHTMLTableColElement : nsIDOMHTMLElement
-{
-           attribute DOMString        align;
-           attribute DOMString        ch;
-           attribute DOMString        chOff;
-           attribute long             span;
-           attribute DOMString        vAlign;
-           attribute DOMString        width;
-};
--- a/dom/interfaces/html/nsIDOMHTMLTableElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLTableElement.idl
@@ -14,44 +14,9 @@
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
 [scriptable, uuid(1a7bf1f1-5d6c-4200-9ceb-455874322315)]
 interface nsIDOMHTMLTableElement : nsIDOMHTMLElement
 {
-  // Modified in DOM Level 2:
-           attribute nsIDOMHTMLTableCaptionElement caption;
-                                             // raises(DOMException) on setting
-
-  // Modified in DOM Level 2:
-           attribute nsIDOMHTMLTableSectionElement tHead;
-                                             // raises(DOMException) on setting
-
-  // Modified in DOM Level 2:
-           attribute nsIDOMHTMLTableSectionElement tFoot;
-                                             // raises(DOMException) on setting
-
-  readonly attribute nsIDOMHTMLCollection          rows;
-  readonly attribute nsIDOMHTMLCollection          tBodies;
-           attribute DOMString                     align;
-           attribute DOMString                     bgColor;
-           attribute DOMString                     border;
-           attribute DOMString                     cellPadding;
-           attribute DOMString                     cellSpacing;
-           attribute DOMString                     frame;
-           attribute DOMString                     rules;
-           attribute DOMString                     summary;
-           attribute DOMString                     width;
-  nsIDOMHTMLElement         createTHead();
-  void                      deleteTHead();
-  nsIDOMHTMLElement         createTFoot();
-  void                      deleteTFoot();
-  nsIDOMHTMLElement         createCaption();
-  void                      deleteCaption();
-  // Modified in DOM Level 2:
-  nsIDOMHTMLElement         insertRow(in long index)
-                                             raises(DOMException);
-  // Modified in DOM Level 2:
-  void                      deleteRow(in long index)
-                                             raises(DOMException);
 };
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLTableRowElement interface is the interface to a
- * [X]HTML tr element.
- *
- * This interface is trying to follow the DOM Level 2 HTML specification:
- * http://www.w3.org/TR/DOM-Level-2-HTML/
- *
- * with changes from the work-in-progress WHATWG HTML specification:
- * http://www.whatwg.org/specs/web-apps/current-work/
- */
-
-[scriptable, uuid(02094366-0d3d-47e3-949c-89113a9bcc15)]
-interface nsIDOMHTMLTableRowElement : nsIDOMHTMLElement
-{
-  // Modified in DOM Level 2:
-  readonly attribute long                 rowIndex;
-  // Modified in DOM Level 2:
-  readonly attribute long                 sectionRowIndex;
-  // Modified in DOM Level 2:
-  readonly attribute nsIDOMHTMLCollection cells;
-           attribute DOMString            align;
-           attribute DOMString            bgColor;
-           attribute DOMString            ch;
-           attribute DOMString            chOff;
-           attribute DOMString            vAlign;
-  // Modified in DOM Level 2:
-  nsIDOMHTMLElement         insertCell(in long index)
-                                               raises(DOMException);
-  // Modified in DOM Level 2:
-  void                      deleteCell(in long index)
-                                               raises(DOMException);
-};
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLTableSectionElement.idl
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLTableSectionElement interface is the interface to a
- * [X]HTML thead, tbody, and tfoot element.
- *
- * This interface is trying to follow the DOM Level 2 HTML specification:
- * http://www.w3.org/TR/DOM-Level-2-HTML/
- *
- * with changes from the work-in-progress WHATWG HTML specification:
- * http://www.whatwg.org/specs/web-apps/current-work/
- */
-
-[scriptable, builtinclass, uuid(7b91cf4c-5194-4122-bc29-7bbd18ba0020)]
-interface nsIDOMHTMLTableSectionElement : nsIDOMHTMLElement
-{
-           attribute DOMString            align;
-           attribute DOMString            ch;
-           attribute DOMString            chOff;
-           attribute DOMString            vAlign;
-  readonly attribute nsIDOMHTMLCollection rows;
-  // Modified in DOM Level 2:
-  nsIDOMHTMLElement         insertRow(in long index)
-                                               raises(DOMException);
-  // Modified in DOM Level 2:
-  void                      deleteRow(in long index)
-                                               raises(DOMException);
-};
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl
+++ /dev/null
@@ -1,17 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLUnknownElement interface is the interface to an unknown HTML
- * element.
- *
- * @see <http://www.whatwg.org/html/#htmlunknownelement>
- */
-[scriptable, uuid(aa044a2d-4e9b-4fc5-8ad2-666da9062b36)]
-interface nsIDOMHTMLUnknownElement : nsIDOMHTMLElement
-{
-};
--- a/dom/network/src/MobileConnection.cpp
+++ b/dom/network/src/MobileConnection.cpp
@@ -43,16 +43,18 @@ public:
     mMobileConnection = nullptr;
   }
 };
 
 NS_IMPL_ISUPPORTS1(MobileConnection::Listener, nsIMobileConnectionListener)
 
 DOMCI_DATA(MozMobileConnection, MobileConnection)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(MobileConnection)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MobileConnection,
                                                   nsDOMEventTargetHelper)
   // Don't traverse mListener because it doesn't keep any reference to
   // MobileConnection but a raw pointer instead. Neither does mProvider because
   // it's an xpcom service and is only released at shutting down.
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MobileConnection,
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -1,14 +1,21 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: sw=4 ts=4 et :
  * 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/. */
 
+#ifdef MOZ_WIDGET_QT
+// Must be included first to avoid conflicts.
+#include <QtCore/QCoreApplication>
+#include <QtCore/QEventLoop>
+#include "NestedLoopTimer.h"
+#endif
+
 #include "mozilla/plugins/PluginModuleParent.h"
 
 #include "base/process_util.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/PCrashReporterParent.h"
 #include "mozilla/ipc/SyncChannel.h"
 #include "mozilla/plugins/BrowserStreamParent.h"
 #include "mozilla/Preferences.h"
@@ -34,22 +41,16 @@
 
 #ifdef MOZ_WIDGET_GTK
 #include <glib.h>
 #elif XP_MACOSX
 #include "PluginInterposeOSX.h"
 #include "PluginUtilsOSX.h"
 #endif
 
-#ifdef MOZ_WIDGET_QT
-#include <QtCore/QCoreApplication>
-#include <QtCore/QEventLoop>
-#include "NestedLoopTimer.h"
-#endif
-
 using base::KillProcess;
 
 using mozilla::PluginLibrary;
 using mozilla::ipc::SyncChannel;
 using mozilla::dom::PCrashReporterParent;
 using mozilla::dom::CrashReporterParent;
 
 using namespace mozilla;
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -41,16 +41,18 @@ public:
   }
 
 private:
   nsRefPtr<Promise> mPromise;
 };
 
 // Promise
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(Promise)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Promise)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mResolver)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mResolveCallbacks);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRejectCallbacks);
   tmp->mResult = JSVAL_VOID;
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/dom/promise/PromiseCallback.cpp
+++ b/dom/promise/PromiseCallback.cpp
@@ -13,16 +13,18 @@ namespace dom {
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseCallback)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseCallback)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseCallback)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(PromiseCallback)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PromiseCallback)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PromiseCallback)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 PromiseCallback::PromiseCallback()
 {
--- a/dom/src/events/nsJSEventListener.cpp
+++ b/dom/src/events/nsJSEventListener.cpp
@@ -72,16 +72,18 @@ nsJSEventListener::UpdateScopeObject(JS:
     mScopeObject = nullptr;
     NS_DROP_JS_OBJECTS(this, nsJSEventListener);
   } else if (aScopeObject && !mScopeObject) {
     NS_HOLD_JS_OBJECTS(this, nsJSEventListener);
   }
   mScopeObject = aScopeObject;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSEventListener)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSEventListener)
   if (tmp->mScopeObject) {
     tmp->mScopeObject = nullptr;
     NS_DROP_JS_OBJECTS(tmp, nsJSEventListener);
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
   }
   tmp->mHandler.ForgetHandler();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -996,16 +996,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoGeolocation)
   NS_INTERFACE_MAP_ENTRY(nsIDOMGeoGeolocation)
   NS_INTERFACE_MAP_ENTRY(nsIGeolocationUpdate)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Geolocation)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Geolocation)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(Geolocation)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Geolocation)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedPosition)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   tmp->mPendingRequests.Clear();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingCallbacks)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mWatchingCallbacks)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -235,16 +235,18 @@ Telephony::DialInternal(bool isEmergency
       telephony->NoteDialedCallFromOtherInstance(aNumber);
     }
   }
 
   call.forget(aResult);
   return NS_OK;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(Telephony)
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Telephony,
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   for (uint32_t index = 0; index < tmp->mCalls.Length(); index++) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCalls[i]");
     cb.NoteXPCOMChild(tmp->mCalls[index]->ToISupports());
   }
   // Don't traverse mListener because it doesn't keep any reference to
--- a/dom/tests/mochitest/gamepad/Makefile.in
+++ b/dom/tests/mochitest/gamepad/Makefile.in
@@ -7,16 +7,17 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir	= dom/tests/mochitest/gamepad
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_FILES = \
   test_gamepad.html \
+  test_gamepad_connect_events.html \
   test_gamepad_frame_state_sync.html \
   gamepad_frame_state.html \
   test_gamepad_hidden_frame.html \
   gamepad_frame.html \
   test_navigator_gamepads.html \
   mock_gamepad.js \
   $(NULL)
 
--- a/dom/tests/mochitest/gamepad/gamepad_frame.html
+++ b/dom/tests/mochitest/gamepad/gamepad_frame.html
@@ -1,16 +1,20 @@
 <!-- Any copyright is dedicated to the Public Domain.
    - http://creativecommons.org/publicdomain/zero/1.0/ -->
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>frame</title>
   <script type="text/javascript">
+    var connectedEvents = 0;
     var buttonPresses = 0;
+    window.addEventListener("gamepadconnected", function() {
+      connectedEvents++;
+});
     window.addEventListener("gamepadbuttondown", function() {
       buttonPresses++;
 });
   </script>
 </head>
 <body>
 </body>
 </html>
copy from dom/tests/mochitest/gamepad/test_gamepad_hidden_frame.html
copy to dom/tests/mochitest/gamepad/test_gamepad_connect_events.html
--- a/dom/tests/mochitest/gamepad/test_gamepad_hidden_frame.html
+++ b/dom/tests/mochitest/gamepad/test_gamepad_connect_events.html
@@ -1,10 +1,13 @@
 <!-- Any copyright is dedicated to the Public Domain.
    - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<!-- bug 893785 - Test that sending a gamepadconnected event to a new window
+     doesn't result in a gamepadconnected event being sent to existing
+     windows that have already received it. -->
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test hidden frames</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
@@ -16,57 +19,49 @@ var index = GamepadService.addGamepad("t
                                       4, // buttons
                                       2);// axes
 
 function pressButton() {
   GamepadService.newButtonEvent(index, 0, true);
   GamepadService.newButtonEvent(index, 0, false);
 }
 
-function setFrameVisible(f, visible) {
-  var Ci = SpecialPowers.Ci;
-  var docshell = SpecialPowers.wrap(f.contentWindow).QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShell);
-  docshell.isActive = visible;
-}
-
-var frames_loaded = 0;
 var f1, f2;
 function frame_loaded() {
-  frames_loaded++;
- if (frames_loaded == 2) {
-    f1 = document.getElementById('f1');
-    f2 = document.getElementById('f2');
-    pressButton();
-  }
+  f1 = document.getElementById('f1');
+  pressButton();
 }
 
 window.addEventListener("gamepadbuttondown", function() {
   // Wait to ensure that all frames received the button press as well.
- SpecialPowers.executeSoon(tests[testNum++]);
+  SpecialPowers.executeSoon(tests[testNum++]);
 });
 
 var testNum = 0;
 var tests = [
   test1,
   test2,
 ];
 
 function test1() {
-  is(f1.contentWindow.buttonPresses, 1, "right number of button presses in frame 1");
-  is(f2.contentWindow.buttonPresses, 1, "right number of button presses in frame 2");
+  is(f1.contentWindow.connectedEvents, 1, "right number of connection events in frame 1");
 
-  // Now hide the second frame and send another button press.
-  setFrameVisible(f2, false);
-  SpecialPowers.executeSoon(function() { pressButton(); });
+  // Now add another frame.
+  f2 = document.createElement("iframe");
+  f2.addEventListener("load", function() {
+    // When the frame is loaded, press a button again.
+    pressButton();
+  });
+  f2.src = "gamepad_frame.html";
+  document.body.appendChild(f2);
 }
 
 function test2() {
-  is(f1.contentWindow.buttonPresses, 2, "right number of button presses in frame 1");
-  is(f2.contentWindow.buttonPresses, 1, "right number of button presses in frame 2");
+  is(f1.contentWindow.connectedEvents, 1, "right number of connection events in frame 1");
+  is(f2.contentWindow.connectedEvents, 1, "right number of connection events in frame 2");
   GamepadService.removeGamepad(index);
   SimpleTest.finish();
 }
 
 </script>
 <iframe id="f1" src="gamepad_frame.html" onload="frame_loaded()"></iframe>
-<iframe id="f2" src="gamepad_frame.html" onload="frame_loaded()"></iframe>
 </body>
 </html>
--- a/dom/tests/mochitest/webapps/test_install_errors.xul
+++ b/dom/tests/mochitest/webapps/test_install_errors.xul
@@ -19,17 +19,16 @@
 <script>
 
 var steps = [
   noArgs,
   parseError,
   invalidManifest,
   permissionDenied,
   invalidContent,
-  installPackageNotImplemented,
   invalidLaunchPath,
   invalidLaunchPath2,
   invalidEntryPoint,
   invalidLocaleEntryPoint,
   invalidActivityHref,
   invalidActivityHref2,
   invalidMessage,
   fileURL,
@@ -162,22 +161,16 @@ function invalidMessage(next) {
   var url = "http://test/chrome/dom/tests/mochitest/webapps/apps/invalid_message.webapp";
 
   navigator.mozApps.install(url, null).onerror = function onInstallError() {
     is(this.error.name, "INVALID_MANIFEST", "Manifest has absolute message href");
     next();
   };
 }
 
-function installPackageNotImplemented(next) {
-  ok(!("installPackage" in navigator.mozApps),
-     "installPackage not in navigator.mozApps");
-  next();
-}
-
 function fileURL(next) {
   try {
     navigator.mozApps.install("file:///nonexistent");
     ok(false,
        "attempt to install nonexistent file: URL doesn't throw exception");
   } catch(ex) {
     is(ex.message, "INVALID_URL_SCHEME: 'file'; must be 'http' or 'https'",
        "attempt to install nonexistent file: URL throws exception");
--- a/dom/tests/mochitest/webapps/test_list_api.xul
+++ b/dom/tests/mochitest/webapps/test_list_api.xul
@@ -19,16 +19,17 @@
 <script>
 
 var props = {
   QueryInterface: "function",
   checkInstalled: "function",
   getInstalled: "function",
   getSelf: "function",
   install: "function",
+  installPackage: "function",
   mgmt: "object",
 };
 
 isDeeply([p for (p in navigator.mozApps)].sort(), Object.keys(props).sort(),
          "navigator.mozApps has only the expected properties");
 
 for (var p in props) {
   is(typeof navigator.mozApps[p], props[p], "typeof " + p);
--- a/dom/webidl/HTMLLegendElement.webidl
+++ b/dom/webidl/HTMLLegendElement.webidl
@@ -14,10 +14,11 @@
 
 // http://www.whatwg.org/specs/web-apps/current-work/#the-legend-element
 interface HTMLLegendElement : HTMLElement {
   readonly attribute HTMLFormElement? form;
 };
 
 // http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
 partial interface HTMLLegendElement {
+           [SetterThrows]
            attribute DOMString align;
 };
--- a/dom/webidl/HTMLTableColElement.webidl
+++ b/dom/webidl/HTMLTableColElement.webidl
@@ -7,18 +7,24 @@
  * http://www.whatwg.org/specs/web-apps/current-work/
  *
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 
 interface HTMLTableColElement : HTMLElement {
+           [SetterThrows]
            attribute unsigned long span;
 };
 
 partial interface HTMLTableColElement {
+           [SetterThrows]
            attribute DOMString align;
+           [SetterThrows]
            attribute DOMString ch;
+           [SetterThrows]
            attribute DOMString chOff;
+           [SetterThrows]
            attribute DOMString vAlign;
+           [SetterThrows]
            attribute DOMString width;
 };
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -950,17 +950,17 @@ CreateDedicatedWorkerGlobalScope(JSConte
   WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
   JS_ASSERT(worker);
 
   JS::CompartmentOptions options;
   if (worker->IsChromeWorker())
     options.setVersion(JSVERSION_LATEST);
   JS::Rooted<JSObject*> global(aCx,
     JS_NewGlobalObject(aCx, DedicatedWorkerGlobalScope::Class(),
-                       GetWorkerPrincipal(), options));
+                       GetWorkerPrincipal(), JS::DontFireOnNewGlobalHook, options));
   if (!global) {
     return NULL;
   }
 
   JSAutoCompartment ac(aCx, global);
 
   // Make the private slots now so that all our instance checks succeed.
   if (!DedicatedWorkerGlobalScope::InitPrivate(aCx, global, worker)) {
@@ -1028,16 +1028,18 @@ CreateDedicatedWorkerGlobalScope(JSConte
       !WorkerNavigatorBinding_workers::GetConstructorObject(aCx, global)) {
     return NULL;
   }
 
   if (!JS_DefineProfilingFunctions(aCx, global)) {
     return NULL;
   }
 
+  JS_FireOnNewGlobalObject(aCx, global);
+
   return global;
 }
 
 bool
 ClassIsWorkerGlobalScope(JSClass* aClass)
 {
   return WorkerGlobalScope::Class() == aClass ||
          DedicatedWorkerGlobalScope::Class() == aClass;
--- a/editor/libeditor/base/EditTxn.cpp
+++ b/editor/libeditor/base/EditTxn.cpp
@@ -2,16 +2,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "EditTxn.h"
 #include "nsError.h"
 #include "nsISupportsBase.h"
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(EditTxn)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(EditTxn)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditTxn)
   // We don't have anything to traverse, but some of our subclasses do.
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditTxn)
   NS_INTERFACE_MAP_ENTRY(nsITransaction)
   NS_INTERFACE_MAP_ENTRY(nsPIEditorTransaction)
--- a/editor/libeditor/base/PlaceholderTxn.cpp
+++ b/editor/libeditor/base/PlaceholderTxn.cpp
@@ -17,16 +17,18 @@ PlaceholderTxn::PlaceholderTxn() :  Edit
                                     mIMETextTxn(nullptr),
                                     mCommitted(false),
                                     mStartSel(nullptr),
                                     mEndSel(),
                                     mEditor(nullptr)
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(PlaceholderTxn)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PlaceholderTxn,
                                                 EditAggregateTxn)
   tmp->mStartSel->DoUnlink();
   tmp->mEndSel.DoUnlink();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PlaceholderTxn,
                                                   EditAggregateTxn)
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -161,16 +161,18 @@ nsEditor::~nsEditor()
 {
   NS_ASSERTION(!mDocWeak || mDidPreDestroy, "Why PreDestroy hasn't been called?");
 
   mTxnMgr = nullptr;
 
   delete mPhonetic;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsEditor)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsEditor)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootElement)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mInlineSpellChecker)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mTxnMgr)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mIMETextRangeList)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mIMETextNode)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mActionListeners)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorObservers)
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -154,16 +154,18 @@ nsHTMLEditor::HideAnonymousEditingUIs()
   if (mAbsolutelyPositionedObject)
     HideGrabber();
   if (mInlineEditedCell)
     HideInlineTableEditingUI();
   if (mResizedObject)
     HideResizers();
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLEditor)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLEditor, nsPlaintextEditor)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTypeInState)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mStyleSheets)
 
   tmp->HideAnonymousEditingUIs();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLEditor, nsPlaintextEditor)
--- a/editor/libeditor/text/nsPlaintextEditor.cpp
+++ b/editor/libeditor/text/nsPlaintextEditor.cpp
@@ -86,16 +86,18 @@ nsPlaintextEditor::~nsPlaintextEditor()
   // Remove event listeners. Note that if we had an HTML editor,
   //  it installed its own instead of these
   RemoveEventListeners();
 
   if (mRules)
     mRules->DetachEditor();
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsPlaintextEditor)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsPlaintextEditor, nsEditor)
   if (tmp->mRules)
     tmp->mRules->DetachEditor();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRules)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsPlaintextEditor, nsEditor)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRules)
--- a/editor/txmgr/src/nsTransactionItem.cpp
+++ b/editor/txmgr/src/nsTransactionItem.cpp
@@ -38,16 +38,18 @@ nsTransactionItem::CleanUp()
     mUndoStack->DoUnlink();
   }
 }
 
 NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(nsTransactionItem)
 NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE_WITH_LAST_RELEASE(nsTransactionItem,
                                                           CleanUp())
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsTransactionItem)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsTransactionItem)
   tmp->CleanUp();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsTransactionItem)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mData)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction)
   if (tmp->mRedoStack) {
--- a/editor/txmgr/src/nsTransactionManager.cpp
+++ b/editor/txmgr/src/nsTransactionManager.cpp
@@ -27,16 +27,18 @@ nsTransactionManager::nsTransactionManag
   , mRedoStack(nsTransactionStack::FOR_REDO)
 {
 }
 
 nsTransactionManager::~nsTransactionManager()
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsTransactionManager)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsTransactionManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mListeners)
   tmp->mDoStack.DoUnlink();
   tmp->mUndoStack.DoUnlink();
   tmp->mRedoStack.DoUnlink();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsTransactionManager)
--- a/embedding/components/commandhandler/src/nsCommandManager.cpp
+++ b/embedding/components/commandhandler/src/nsCommandManager.cpp
@@ -47,16 +47,18 @@ TraverseCommandObservers(const char* aKe
   int32_t i, numItems = aObservers->Length();
   for (i = 0; i < numItems; ++i) {
     cb->NoteXPCOMChild(aObservers->ElementAt(i));
   }
 
   return PL_DHASH_NEXT;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsCommandManager)
+
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCommandManager)
   tmp->mObserversTable.Clear();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCommandManager)
   tmp->mObserversTable.EnumerateRead(TraverseCommandObservers, &cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCommandManager)
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -288,17 +288,17 @@ GLContext::InitWithPrefix(const char *pr
         { nullptr, { nullptr } },
 
     };
 
     mInitialized = LoadSymbols(&symbols[0], trygl, prefix);
 
     // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
     if (mInitialized) {
-        if (mIsGLES2) {
+        if (IsGLES2()) {
             SymLoadStruct symbols_ES2[] = {
                 { (PRFuncPtr*) &mSymbols.fGetShaderPrecisionFormat, { "GetShaderPrecisionFormat", nullptr } },
                 { (PRFuncPtr*) &mSymbols.fClearDepthf, { "ClearDepthf", nullptr } },
                 { (PRFuncPtr*) &mSymbols.fDepthRangef, { "DepthRangef", nullptr } },
                 { nullptr, { nullptr } },
             };
 
             if (!LoadSymbols(&symbols_ES2[0], trygl, prefix)) {
@@ -1016,47 +1016,47 @@ GLContext::UpdatePixelFormat()
 GLFormats
 GLContext::ChooseGLFormats(const SurfaceCaps& caps) const
 {
     GLFormats formats;
 
     // If we're on ES2 hardware and we have an explicit request for 16 bits of color or less
     // OR we don't support full 8-bit color, return a 4444 or 565 format.
     bool bpp16 = caps.bpp16;
-    if (mIsGLES2) {
+    if (IsGLES2()) {
         if (!IsExtensionSupported(OES_rgb8_rgba8))
             bpp16 = true;
     } else {
         // RGB565 is uncommon on desktop, requiring ARB_ES2_compatibility.
         // Since it's also vanishingly useless there, let's not support it.
         bpp16 = false;
     }
 
     if (bpp16) {
-        MOZ_ASSERT(mIsGLES2);
+        MOZ_ASSERT(IsGLES2());
         if (caps.alpha) {
             formats.color_texInternalFormat = LOCAL_GL_RGBA;
             formats.color_texFormat = LOCAL_GL_RGBA;
             formats.color_texType   = LOCAL_GL_UNSIGNED_SHORT_4_4_4_4;
             formats.color_rbFormat  = LOCAL_GL_RGBA4;
         } else {
             formats.color_texInternalFormat = LOCAL_GL_RGB;
             formats.color_texFormat = LOCAL_GL_RGB;
             formats.color_texType   = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
             formats.color_rbFormat  = LOCAL_GL_RGB565;
         }
     } else {
         formats.color_texType = LOCAL_GL_UNSIGNED_BYTE;
 
         if (caps.alpha) {
-            formats.color_texInternalFormat = mIsGLES2 ? LOCAL_GL_RGBA : LOCAL_GL_RGBA8;
+            formats.color_texInternalFormat = IsGLES2() ? LOCAL_GL_RGBA : LOCAL_GL_RGBA8;
             formats.color_texFormat = LOCAL_GL_RGBA;
             formats.color_rbFormat  = LOCAL_GL_RGBA8;
         } else {
-            formats.color_texInternalFormat = mIsGLES2 ? LOCAL_GL_RGB : LOCAL_GL_RGB8;
+            formats.color_texInternalFormat = IsGLES2() ? LOCAL_GL_RGB : LOCAL_GL_RGB8;
             formats.color_texFormat = LOCAL_GL_RGB;
             formats.color_rbFormat  = LOCAL_GL_RGB8;
         }
     }
 
     uint32_t msaaLevel = Preferences::GetUint("gl.msaa-level", 2);
     GLsizei samples = msaaLevel * msaaLevel;
     samples = std::min(samples, mMaxSamples);
@@ -1065,22 +1065,22 @@ GLContext::ChooseGLFormats(const Surface
     if (WorkAroundDriverBugs() && samples == 1) {
         samples = 0;
     }
     formats.samples = samples;
 
 
     // Be clear that these are 0 if unavailable.
     formats.depthStencil = 0;
-    if (!mIsGLES2 || IsExtensionSupported(OES_packed_depth_stencil)) {
+    if (!IsGLES2() || IsExtensionSupported(OES_packed_depth_stencil)) {
         formats.depthStencil = LOCAL_GL_DEPTH24_STENCIL8;
     }
 
     formats.depth = 0;
-    if (mIsGLES2) {
+    if (IsGLES2()) {
         if (IsExtensionSupported(OES_depth24)) {
             formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
         } else {
             formats.depth = LOCAL_GL_DEPTH_COMPONENT16;
         }
     } else {
         formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
     }
@@ -2318,17 +2318,17 @@ static GLint GetAddressAlignment(ptrdiff
 }
 
 void
 GLContext::TexImage2D(GLenum target, GLint level, GLint internalformat,
                       GLsizei width, GLsizei height, GLsizei stride,
                       GLint pixelsize, GLint border, GLenum format,
                       GLenum type, const GLvoid *pixels)
 {
-    if (mIsGLES2) {
+    if (IsGLES2()) {
 
         NS_ASSERTION(format == (GLenum)internalformat,
                     "format and internalformat not the same for glTexImage2D on GLES2");
 
         if (!CanUploadNonPowerOfTwo()
             && (stride != width * pixelsize
             || !IsPowerOfTwo(width)
             || !IsPowerOfTwo(height))) {
@@ -2425,17 +2425,17 @@ GLContext::TexImage2D(GLenum target, GLi
 
 void
 GLContext::TexSubImage2D(GLenum target, GLint level,
                          GLint xoffset, GLint yoffset,
                          GLsizei width, GLsizei height, GLsizei stride,
                          GLint pixelsize, GLenum format,
                          GLenum type, const GLvoid* pixels)
 {
-    if (mIsGLES2) {
+    if (IsGLES2()) {
         if (stride == width * pixelsize) {
             fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
                     std::min(GetAddressAlignment((ptrdiff_t)pixels),
                             GetAddressAlignment((ptrdiff_t)stride)));
             fTexSubImage2D(target,
                           level,
                           xoffset,
                           yoffset,
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -79,16 +79,25 @@ namespace mozilla {
         class LayerManagerOGL;
     }
 }
 
 namespace mozilla {
 namespace gl {
 typedef uintptr_t SharedTextureHandle;
 
+MOZ_BEGIN_ENUM_CLASS(ContextProfile, uint8_t)
+    Unknown = 0,
+    OpenGL, // only for IsAtLeast's <profile> parameter
+    OpenGLCore,
+    OpenGLCompatibility,
+    OpenGLES
+MOZ_END_ENUM_CLASS(ContextProfile)
+
+
 class GLContext
     : public GLLibraryLoader
     , public GenericAtomicRefCounted
 {
 // -----------------------------------------------------------------------------
 // basic enums
 public:
 
@@ -135,16 +144,95 @@ public:
     /**
      * Returns true if the context is using ANGLE. This should only be overridden
      * for an ANGLE implementation.
      */
     virtual bool IsANGLE() {
         return false;
     }
 
+    /**
+     * Return true if we are running on a OpenGL core profile context
+     */
+    inline bool IsCoreProfile() const {
+        MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
+
+        return mProfile == ContextProfile::OpenGLCore;
+    }
+
+    /**
+     * Return true if we are running on a OpenGL compatibility profile context
+     * (legacy profile 2.1 on Max OS X)
+     */
+    inline bool IsCompatibilityProfile() const {
+        MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
+
+        return mProfile == ContextProfile::OpenGLCompatibility;
+    }
+
+    /**
+     * Return true if the context is a true OpenGL ES context or an ANGLE context
+     */
+    inline bool IsGLES() const {
+        MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
+
+        return mProfile == ContextProfile::OpenGLES;
+    }
+
+    static const char* GetProfileName(ContextProfile profile)
+    {
+        switch (profile)
+        {
+            case ContextProfile::OpenGL:
+                return "OpenGL";
+            case ContextProfile::OpenGLCore:
+                return "OpenGL Core";
+            case ContextProfile::OpenGLCompatibility:
+                return "OpenGL Compatibility";
+            case ContextProfile::OpenGLES:
+                return "OpenGL ES";
+            default:
+                break;
+        }
+
+        MOZ_ASSERT(profile != ContextProfile::Unknown, "unknown context profile");
+        return "OpenGL unknown profile";
+    }
+
+    /**
+     * Return true if the context is compatible with given parameters
+     *
+     * IsAtLeast(ContextProfile::OpenGL, N) is exactly same as
+     * IsAtLeast(ContextProfile::OpenGLCore, N) || IsAtLeast(ContextProfile::OpenGLCompatibility, N)
+     */
+    inline bool IsAtLeast(ContextProfile profile, unsigned int version) const
+    {
+        MOZ_ASSERT(profile != ContextProfile::Unknown, "IsAtLeast: bad <profile> parameter");
+        MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
+        MOZ_ASSERT(mVersion != 0, "unknown context version");
+
+        if (profile == ContextProfile::OpenGL) {
+            return (profile == ContextProfile::OpenGLCore ||
+                    profile == ContextProfile::OpenGLCompatibility) &&
+                   version >= mVersion;
+        }
+
+        return profile == mProfile &&
+               version >= mVersion;
+    }
+
+    /**
+     * Return the version of the context.
+     * Example :
+     *   If this a OpenGL 2.1, that will return 210
+     */
+    inline unsigned int Version() const {
+        return mVersion;
+    }
+
     int Vendor() const {
         return mVendor;
     }
 
     int Renderer() const {
         return mRenderer;
     }
 
@@ -166,17 +254,17 @@ public:
     virtual bool IsCurrent() = 0;
 
     /**
      * If this context is the GLES2 API, returns TRUE.
      * This means that various GLES2 restrictions might be in effect (modulo
      * extensions).
      */
     inline bool IsGLES2() const {
-        return mIsGLES2;
+        return IsAtLeast(ContextProfile::OpenGLES, 200);
     }
 
     /**
      * Returns true if either this is the GLES2 API, or had the GL_ARB_ES2_compatibility extension
      * We would like to introduce a XXX_ES2_compatibility
      */
     bool HasES2Compatibility() const {
         return IsGLES2() || IsExtensionSupported(ARB_ES2_compatibility);
@@ -184,24 +272,34 @@ public:
 
 
 protected:
 
     bool mInitialized;
     bool mIsOffscreen;
     bool mIsGlobalSharedContext;
     bool mContextLost;
-    bool mIsGLES2;
+
+    /**
+     * mVersion store the OpenGL's version, multiplied by 100. For example, if
+     * the context is an OpenGL 2.1 context, mVersion value will be 210.
+     */
+    unsigned int mVersion;
+    ContextProfile mProfile;
 
     int32_t mVendor;
     int32_t mRenderer;
 
-    inline void SetIsGLES2(bool isGLES2) {
-        MOZ_ASSERT(!mInitialized, "SetIsGLES2 can only be called before initialization!");
-        mIsGLES2 = isGLES2;
+    inline void SetProfileVersion(ContextProfile profile, unsigned int version) {
+        MOZ_ASSERT(!mInitialized, "SetProfileVersion can only be called before initialization!");
+        MOZ_ASSERT(profile != ContextProfile::Unknown && profile != ContextProfile::OpenGL, "Invalid `profile` for SetProfileVersion");
+        MOZ_ASSERT(version >= 100, "Invalid `version` for SetProfileVersion");
+
+        mVersion = version;
+        mProfile = profile;
     }
 
 
 // -----------------------------------------------------------------------------
 // Extensions management
 /**
  * This mechanism is designed to know if an extension is supported. In the long
  * term, we would like to only use the extension group queries XXX_* to have
@@ -2010,28 +2108,32 @@ public:
     }
 
 
 // -----------------------------------------------------------------------------
 // Package XXX_draw_instanced
 public:
     void fDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
     {
+        BeforeGLDrawCall();
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fDrawArraysInstanced);
         mSymbols.fDrawArraysInstanced(mode, first, count, primcount);
         AFTER_GL_CALL;
+        AfterGLDrawCall();
     }
 
     void fDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei primcount)
     {
+        BeforeGLDrawCall();
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fDrawElementsInstanced);
         mSymbols.fDrawElementsInstanced(mode, count, type, indices, primcount);
         AFTER_GL_CALL;
+        AfterGLDrawCall();
     }
 
 
 // -----------------------------------------------------------------------------
 // Package XXX_framebuffer_blit
 public:
     // Draw/Read
     void fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
@@ -2110,17 +2212,18 @@ public:
 protected:
     GLContext(const SurfaceCaps& caps,
               GLContext* sharedContext = nullptr,
               bool isOffscreen = false)
       : mInitialized(false),
         mIsOffscreen(isOffscreen),
         mIsGlobalSharedContext(false),
         mContextLost(false),
-        mIsGLES2(false),
+        mVersion(0),
+        mProfile(ContextProfile::Unknown),
         mVendor(-1),
         mRenderer(-1),
         mHasRobustness(false),
 #ifdef DEBUG
         mGLError(LOCAL_GL_NO_ERROR),
 #endif
         mTexBlit_Buffer(0),
         mTexBlit_VertShader(0),
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -89,17 +89,19 @@ class GLContextCGL : public GLContext
 public:
     GLContextCGL(const SurfaceCaps& caps,
                  GLContext *shareContext,
                  NSOpenGLContext *context,
                  bool isOffscreen = false)
         : GLContext(caps, shareContext, isOffscreen),
           mContext(context),
           mTempTextureName(0)
-    {}
+    {
+        SetProfileVersion(ContextProfile::OpenGLCompatibility, 210);
+    }
 
     ~GLContextCGL()
     {
         MarkDestroyed();
 
         if (mContext)
             [mContext release];
     }
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -265,17 +265,17 @@ public:
         , mBound(false)
         , mIsPBuffer(false)
         , mIsDoubleBuffered(false)
         , mCanBindToTexture(false)
         , mShareWithEGLImage(false)
         , mTemporaryEGLImageTexture(0)
     {
         // any EGL contexts will always be GLESv2
-        SetIsGLES2(true);
+        SetProfileVersion(ContextProfile::OpenGLES, 200);
 
 #ifdef DEBUG
         printf_stderr("Initializing context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
 #endif
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION <= 15
         if (!mIsOffscreen) {
             mHwc = HwcComposer2D::GetInstance();
             MOZ_ASSERT(!mHwc->Initialized());
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -961,16 +961,18 @@ private:
           mDrawable(aDrawable),
           mDeleteDrawable(aDeleteDrawable),
           mDoubleBuffered(aDoubleBuffered),
           mLibType(libType),
           mGLX(&sGLXLibrary[libType]),
           mPixmap(aPixmap)
     {
         MOZ_ASSERT(mGLX);
+        // See 899855
+        SetProfileVersion(ContextProfile::OpenGLCompatibility, 200);
     }
 
     GLXContext mContext;
     Display *mDisplay;
     GLXDrawable mDrawable;
     bool mDeleteDrawable;
     bool mDoubleBuffered;
 
--- a/gfx/gl/GLContextProviderWGL.cpp
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -267,16 +267,18 @@ public:
           mDC(aDC),
           mContext(aContext),
           mWnd(aWindow),
           mPBuffer(nullptr),
           mPixelFormat(0),
           mLibType(aLibUsed),
           mIsDoubleBuffered(false)
     {
+        // See 899855
+        SetProfileVersion(ContextProfile::OpenGLCompatibility, 200);
     }
 
     // From PBuffer
     GLContextWGL(const SurfaceCaps& caps,
                  GLContext* sharedContext,
                  bool isOffscreen,
                  HANDLE aPbuffer,
                  HDC aDC,
@@ -287,16 +289,18 @@ public:
           mDC(aDC),
           mContext(aContext),
           mWnd(nullptr),
           mPBuffer(aPbuffer),
           mPixelFormat(aPixelFormat),
           mLibType(aLibUsed),
           mIsDoubleBuffered(false)
     {
+        // See 899855
+        SetProfileVersion(ContextProfile::OpenGLCompatibility, 200);
     }
 
     ~GLContextWGL()
     {
         MarkDestroyed();
 
         sWGLLib[mLibType].fDeleteContext(mContext);
 
--- a/gfx/gl/GLTextureImage.cpp
+++ b/gfx/gl/GLTextureImage.cpp
@@ -216,17 +216,17 @@ TiledTextureImage::TiledTextureImage(GLC
     , mCurrentImage(0)
     , mIterationCallback(nullptr)
     , mInUpdate(false)
     , mRows(0)
     , mColumns(0)
     , mGL(aGL)
     , mTextureState(Created)
 {
-    if (!(aFlags & TextureImage::ForceSingleTile) && mGL->WantsSmallTiles()) {
+    if (!(aFlags & TextureImage::DisallowBigImage) && mGL->WantsSmallTiles()) {
       mTileSize = 256;
     } else {
       mGL->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, (GLint*) &mTileSize);
     }
     if (aSize.width != 0 && aSize.height != 0) {
         Resize(aSize);
     }
 }
--- a/gfx/gl/GLTextureImage.h
+++ b/gfx/gl/GLTextureImage.h
@@ -52,17