Merge latest green b2g-inbound changeset and mozilla-central
authorEd Morley <emorley@mozilla.com>
Fri, 02 Aug 2013 13:30:22 +0100
changeset 153396 d3a0ac52d5d44452afc354567dc4ed527dd9d393
parent 153395 73dcf35e07cf2e2a3b2e76c3985a9c78093181bf (current diff)
parent 153361 04dd60bdbc04f803c06235d3668bc0c3bd3a5fea (diff)
child 153401 09a8e6c3e1e294f880198e25fbb76718ed74bcb0
child 153413 f06052c0986b0a9b392ede7d9a067e65653d7d71
child 153489 bcbc5a0ed405aa33a5c0eaff4e4f71c808ebeeea
child 170191 9b1850fb1f616bf42df7ea4311dbe3579829254f
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge latest green b2g-inbound changeset and mozilla-central
browser/components/sessionstore/src/Makefile.in
browser/metro/components/Makefile.in
dom/apps/src/Makefile.in
dom/identity/Makefile.in
dom/indexedDB/nsIIDBKeyRange.idl
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
dom/payment/Makefile.in
dom/phonenumberutils/Makefile.in
dom/telephony/Telephony.cpp
dom/wappush/src/Makefile.in
layout/tools/recording/Makefile.in
media/libsoundtouch/Makefile.in
netwerk/base/src/nsIOThreadPool.cpp
netwerk/base/src/nsIOThreadPool.h
netwerk/protocol/app/Makefile.in
security/patches/bug-658222-false-start.patch
toolkit/components/captivedetect/Makefile.in
toolkit/components/jsdownloads/src/Makefile.in
toolkit/components/osfile/_PromiseWorker.jsm
toolkit/components/osfile/osfile_async_front.jsm
toolkit/components/osfile/osfile_async_worker.js
toolkit/components/osfile/osfile_shared_allthreads.jsm
toolkit/components/osfile/osfile_shared_front.jsm
toolkit/components/osfile/osfile_unix_allthreads.jsm
toolkit/components/osfile/osfile_unix_back.jsm
toolkit/components/osfile/osfile_unix_front.jsm
toolkit/components/osfile/osfile_win_allthreads.jsm
toolkit/components/osfile/osfile_win_back.jsm
toolkit/components/osfile/osfile_win_front.jsm
toolkit/components/osfile/ospath_unix_back.jsm
toolkit/components/osfile/ospath_win_back.jsm
toolkit/devtools/apps/Makefile.in
toolkit/mozapps/downloads/Makefile.in
toolkit/mozapps/plugins/Makefile.in
toolkit/webapps/Makefile.in
--- 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/public/msaa/Makefile.in
+++ b/accessible/public/msaa/Makefile.in
@@ -34,18 +34,16 @@ MIDL_GENERATED_FILES = \
 	ISimpleDOMDocument.h \
 	ISimpleDOMDocument_p.c \
 	ISimpleDOMDocument_i.c \
 	ISimpleDOMText.h \
 	ISimpleDOMText_p.c \
 	ISimpleDOMText_i.c \
 	$(NULL)
 
-SRCDIR_CSRCS	= $(addprefix $(srcdir)/,$(CSRCS))
-
 OS_LIBS = $(call EXPAND_LIBNAME,kernel32 rpcns4 rpcrt4 oleaut32)
 
 $(MIDL_GENERATED_FILES): done_gen
 
 done_gen: ISimpleDOMNode.idl \
           ISimpleDOMDocument.idl \
           ISimpleDOMText.idl
 
--- 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/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -36,16 +36,18 @@
 
 #include "nsComponentManagerUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "mozilla/dom/Element.h"
 
 #include "nsITreeBoxObject.h"
 #include "nsITreeColumns.h"
 
+using namespace mozilla;
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsCoreUtils
 ////////////////////////////////////////////////////////////////////////////////
 
 bool
 nsCoreUtils::HasClickListener(nsIContent *aContent)
 {
   NS_ENSURE_TRUE(aContent, false);
@@ -125,17 +127,17 @@ nsCoreUtils::DispatchClickEvent(nsITreeB
 void
 nsCoreUtils::DispatchMouseEvent(uint32_t aEventType, int32_t aX, int32_t aY,
                                 nsIContent *aContent, nsIFrame *aFrame,
                                 nsIPresShell *aPresShell, nsIWidget *aRootWidget)
 {
   nsMouseEvent event(true, aEventType, aRootWidget,
                      nsMouseEvent::eReal, nsMouseEvent::eNormal);
 
-  event.refPoint = nsIntPoint(aX, aY);
+  event.refPoint = LayoutDeviceIntPoint(aX, aY);
 
   event.clickCount = 1;
   event.button = nsMouseEvent::eLeftButton;
   event.time = PR_IntervalNow();
   event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
 
   nsEventStatus status = nsEventStatus_eIgnore;
   aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -835,17 +835,17 @@ Accessible::ChildAtPoint(int32_t aX, int
   nsIWidget* rootWidget = rootFrame->GetView()->GetNearestWidget(nullptr);
   NS_ENSURE_TRUE(rootWidget, nullptr);
 
   nsIntRect rootRect;
   rootWidget->GetScreenBounds(rootRect);
 
   nsMouseEvent dummyEvent(true, NS_MOUSE_MOVE, rootWidget,
                           nsMouseEvent::eSynthesized);
-  dummyEvent.refPoint = nsIntPoint(aX - rootRect.x, aY - rootRect.y);
+  dummyEvent.refPoint = LayoutDeviceIntPoint(aX - rootRect.x, aY - rootRect.y);
 
   nsIFrame* popupFrame = nsLayoutUtils::
     GetPopupFrameForEventCoordinates(accDocument->PresContext()->GetRootPresContext(),
                                      &dummyEvent);
   if (popupFrame) {
     // If 'this' accessible is not inside the popup then ignore the popup when
     // searching an accessible at point.
     DocAccessible* popupDoc =
--- 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/components/migration/src/Makefile.in
+++ b/browser/components/migration/src/Makefile.in
@@ -17,14 +17,10 @@ ifeq ($(OS_ARCH),WINNT)
 
 DEFINES += -DHAS_IE_MIGRATOR -DHAS_SAFARI_MIGRATOR
 endif
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 DEFINES += -DHAS_SAFARI_MIGRATOR
 endif
 
-EXTRA_PP_JS_MODULES = \
-	MigrationUtils.jsm \
-	$(NULL)
-
 include $(topsrcdir)/config/rules.mk
 
--- a/browser/components/migration/src/moz.build
+++ b/browser/components/migration/src/moz.build
@@ -33,8 +33,12 @@ if CONFIG['OS_ARCH'] == 'WINNT':
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     EXTRA_PP_COMPONENTS += [
         'SafariProfileMigrator.js',
     ]
 
 LIBRARY_NAME = 'migration_s'
 
+EXTRA_PP_JS_MODULES += [
+    'MigrationUtils.jsm',
+]
+
deleted file mode 100644
--- a/browser/components/sessionstore/src/Makefile.in
+++ /dev/null
@@ -1,17 +0,0 @@
-# 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/.
-
-DEPTH     = @DEPTH@
-topsrcdir = @top_srcdir@
-srcdir    = @srcdir@
-VPATH     = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-include $(topsrcdir)/config/config.mk
-
-EXTRA_PP_JS_MODULES := \
-	SessionStore.jsm \
-	$(NULL)
-
-include $(topsrcdir)/config/rules.mk
--- a/browser/components/sessionstore/src/moz.build
+++ b/browser/components/sessionstore/src/moz.build
@@ -15,8 +15,13 @@ JS_MODULES_PATH = 'modules/sessionstore'
 EXTRA_JS_MODULES = [
     'DocumentUtils.jsm',
     'SessionMigration.jsm',
     'SessionStorage.jsm',
     'SessionWorker.js',
     'XPathGenerator.jsm',
     '_SessionFile.jsm',
 ]
+
+EXTRA_PP_JS_MODULES += [
+    'SessionStore.jsm',
+]
+
--- 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);
   }
 });
deleted file mode 100644
--- a/browser/metro/components/Makefile.in
+++ /dev/null
@@ -1,27 +0,0 @@
-# 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/.
-
-DEPTH      = @DEPTH@
-topsrcdir  = @top_srcdir@
-srcdir     = @srcdir@
-VPATH      = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-include $(topsrcdir)/config/config.mk
-
-# metro/components.manifest
-EXTRA_COMPONENTS = \
-        AlertsService.js \
-        ContentPermissionPrompt.js \
-        DownloadManagerUI.js \
-        PromptService.js \
-        ContentDispatchChooser.js \
-        LoginManagerPrompter.js \
-        $(NULL)
-
-ifdef MOZ_SAFE_BROWSING
-EXTRA_COMPONENTS += SafeBrowsing.js
-endif
-
-include $(topsrcdir)/config/rules.mk
--- a/browser/metro/components/moz.build
+++ b/browser/metro/components/moz.build
@@ -6,16 +6,30 @@
 
 XPIDL_SOURCES += [
     'SessionStore.idl',
 ]
 
 MODULE = 'components'
 
 # metro/components.manifest
+EXTRA_COMPONENTS += [
+    'AlertsService.js',
+    'ContentDispatchChooser.js',
+    'ContentPermissionPrompt.js',
+    'DownloadManagerUI.js',
+    'LoginManagerPrompter.js',
+    'PromptService.js',
+]
+
+if CONFIG['MOZ_SAFE_BROWSING']:
+    EXTRA_COMPONENTS += [
+        'SafeBrowsing.js',
+    ]
+
 EXTRA_PP_COMPONENTS += [
     'AboutRedirector.js',
     'BrowserCLH.js',
     'BrowserStartup.js',
     'DirectoryProvider.js',
     'HelperAppDialog.js',
     'SessionStore.js',
     'Sidebar.js',
--- 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/Makefile.in
+++ b/browser/modules/Makefile.in
@@ -6,18 +6,13 @@ DEPTH   = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH   = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 include $(topsrcdir)/config/config.mk
 
-EXTRA_PP_JS_MODULES = \
-	AboutHomeUtils.jsm \
-	RecentWindow.jsm \
-	$(NULL)
-
 ifdef MOZILLA_OFFICIAL
 DEFINES += -DMOZILLA_OFFICIAL=1
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/modules/moz.build
+++ b/browser/modules/moz.build
@@ -19,8 +19,14 @@ EXTRA_JS_MODULES += [
     'webrtcUI.jsm',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     EXTRA_JS_MODULES += [
         'WindowsJumpLists.jsm',
         'WindowsPreviewPerTab.jsm',
     ]
+
+EXTRA_PP_JS_MODULES += [
+    'AboutHomeUtils.jsm',
+    'RecentWindow.jsm',
+]
+
--- 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/config/rules.mk
+++ b/config/rules.mk
@@ -13,16 +13,17 @@ endif
 # Integrate with mozbuild-generated make files. We first verify that no
 # variables provided by the automatically generated .mk files are
 # present. If they are, this is a violation of the separation of
 # responsibility between Makefile.in and mozbuild files.
 _MOZBUILD_EXTERNAL_VARIABLES := \
   CPP_UNIT_TESTS \
   DIRS \
   EXTRA_PP_COMPONENTS \
+  EXTRA_PP_JS_MODULES \
   GTEST_CMMSRCS \
   GTEST_CPPSRCS \
   GTEST_CSRCS \
   HOST_CSRCS \
   HOST_LIBRARY_NAME \
   MODULE \
   NO_DIST_INSTALL \
   PARALLEL_DIRS \
--- a/configure.in
+++ b/configure.in
@@ -5900,16 +5900,20 @@ MOZ_ARG_DISABLE_BOOL(webgl,
     MOZ_WEBGL_DISABLED=1,
     MOZ_WEBGL_DISABLED=)
 
 if test -n "$MOZ_WEBGL_DISABLED"; then
   MOZ_WEBGL=
   MOZ_ANGLE_RENDERER=
 fi
 
+if test -n "$MOZ_WEBGL"; then
+  AC_DEFINE(MOZ_WEBGL)
+fi
+
 if test -n "$MOZ_WEBGL_CONFORMANT"; then
   AC_DEFINE(MOZ_WEBGL_CONFORMANT)
 fi
 
 # Locate a DirectX SDK here so we can use it for both ANGLE and
 # Joystick support.
 if test "$OS_TARGET" = "WINNT" -a -z "$CROSS_COMPILE"; then
   # Get the SDK path from the registry.
@@ -8744,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/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -745,17 +745,17 @@ public:
    *   @param [aLineNumber=0] (Optional) Line number within resource
               containing error.
    *   @param [aColumnNumber=0] (Optional) Column number within resource
               containing error.
               If aURI is null, then aDocument->GetDocumentURI() is used.
    */
   static nsresult ReportToConsoleNonLocalized(const nsAString& aErrorText,
                                               uint32_t aErrorFlags,
-                                              const char *aCategory,
+                                              const nsACString& aCategory,
                                               nsIDocument* aDocument,
                                               nsIURI* aURI = nullptr,
                                               const nsAFlatString& aSourceLine
                                                 = EmptyString(),
                                               uint32_t aLineNumber = 0,
                                               uint32_t aColumnNumber = 0);
 
   /**
@@ -789,27 +789,47 @@ public:
     eSVG_PROPERTIES,
     eBRAND_PROPERTIES,
     eCOMMON_DIALOG_PROPERTIES,
     eMATHML_PROPERTIES,
     eSECURITY_PROPERTIES,
     PropertiesFile_COUNT
   };
   static nsresult ReportToConsole(uint32_t aErrorFlags,
-                                  const char *aCategory,
+                                  const nsACString& aCategory,
                                   nsIDocument* aDocument,
                                   PropertiesFile aFile,
                                   const char *aMessageName,
                                   const PRUnichar **aParams = nullptr,
                                   uint32_t aParamsLength = 0,
                                   nsIURI* aURI = nullptr,
                                   const nsAFlatString& aSourceLine
                                     = EmptyString(),
                                   uint32_t aLineNumber = 0,
                                   uint32_t aColumnNumber = 0);
+  // This overload allows passing a literal string for aCategory.
+  template<uint32_t N>
+  static nsresult ReportToConsole(uint32_t aErrorFlags,
+                                  const char (&aCategory)[N],
+                                  nsIDocument* aDocument,
+                                  PropertiesFile aFile,
+                                  const char *aMessageName,
+                                  const PRUnichar **aParams = nullptr,
+                                  uint32_t aParamsLength = 0,
+                                  nsIURI* aURI = nullptr,
+                                  const nsAFlatString& aSourceLine
+                                    = EmptyString(),
+                                  uint32_t aLineNumber = 0,
+                                  uint32_t aColumnNumber = 0)
+  {
+      nsDependentCString category(aCategory, N - 1);
+      return ReportToConsole(aErrorFlags, category, aDocument, aFile,
+                             aMessageName, aParams, aParamsLength, aURI,
+                             aSourceLine, aLineNumber, aColumnNumber);
+  }
 
   /**
    * Get the localized string named |aKey| in properties file |aFile|.
    */
   static nsresult GetLocalizedString(PropertiesFile aFile,
                                      const char* aKey,
                                      nsXPIDLString& aResult);
 
@@ -1273,19 +1293,16 @@ public:
   static bool AreJSObjectsHeld(void* aScriptObjectHolder); 
 #endif
 
   static void DeferredFinalize(nsISupports* aSupports);
   static void DeferredFinalize(mozilla::DeferredFinalizeAppendFunction aAppendFunc,
                                mozilla::DeferredFinalizeFunction aFunc,
                                void* aThing);
 
-  static void ReleaseWrapper(void* aScriptObjectHolder,
-                             nsWrapperCache* aCache);
-
   /*
    * Notify when the first XUL menu is opened and when the all XUL menus are
    * closed. At opening, aInstalling should be TRUE, otherwise, it should be
    * FALSE.
    */
   static void NotifyInstalledMenuKeyboardListener(bool aInstalling);
 
   /**
--- 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
@@ -984,17 +984,17 @@ void
 FragmentOrElement::DestroyContent()
 {
   nsIDocument *document = OwnerDoc();
   document->BindingManager()->RemovedFromDocument(this, document);
   document->ClearBoxObjectFor(this);
 
   // XXX We really should let cycle collection do this, but that currently still
   //     leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
-  nsContentUtils::ReleaseWrapper(this, this);
+  ReleaseWrapper(this);
 
   uint32_t i, count = mAttrsAndChildren.ChildCount();
   for (i = 0; i < count; ++i) {
     // The child can remove itself from the parent in BindToTree.
     mAttrsAndChildren.ChildAt(i)->DestroyContent();
   }
 }
 
@@ -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/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -17,24 +17,16 @@ LIBXUL_LIBRARY	= 1
 ifdef MOZ_WEBRTC
 LOCAL_INCLUDES += \
 		-I$(topsrcdir)/netwerk/sctp/datachannel \
 		$(NULL)
 endif
 
 GQI_SRCS = contentbase.gqi
 
-EXTRA_COMPONENTS = \
-		contentSecurityPolicy.manifest \
-		contentAreaDropListener.js \
-		contentAreaDropListener.manifest \
-		messageWakeupService.js \
-		messageWakeupService.manifest \
-		$(NULL)
-
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/config/rules.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 LOCAL_INCLUDES += \
   -I$(topsrcdir)/caps/include \
   -I$(topsrcdir)/content/events/src \
   -I$(topsrcdir)/content/html/content/src \
--- 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/moz.build
+++ b/content/base/src/moz.build
@@ -149,15 +149,23 @@ CPP_SOURCES += [
     'nsTreeSanitizer.cpp',
     'nsViewportInfo.cpp',
     'nsXHTMLContentSerializer.cpp',
     'nsXMLContentSerializer.cpp',
     'nsXMLHttpRequest.cpp',
     'nsXMLNameSpaceMap.cpp',
 ]
 
+EXTRA_COMPONENTS += [
+    'contentAreaDropListener.js',
+    'contentAreaDropListener.manifest',
+    'contentSecurityPolicy.manifest',
+    'messageWakeupService.js',
+    'messageWakeupService.manifest',
+]
+
 EXTRA_PP_COMPONENTS += [
     'contentSecurityPolicy.js',
 ]
 
 EXTRA_JS_MODULES += [
     'CSPUtils.jsm',
 ]
--- 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/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -2962,17 +2962,17 @@ nsresult nsContentUtils::FormatLocalized
 
   return bundle->FormatStringFromName(NS_ConvertASCIItoUTF16(aKey).get(),
                                       aParams, aParamsLength,
                                       getter_Copies(aResult));
 }
 
 /* static */ nsresult
 nsContentUtils::ReportToConsole(uint32_t aErrorFlags,
-                                const char *aCategory,
+                                const nsACString& aCategory,
                                 nsIDocument* aDocument,
                                 PropertiesFile aFile,
                                 const char *aMessageName,
                                 const PRUnichar **aParams,
                                 uint32_t aParamsLength,
                                 nsIURI* aURI,
                                 const nsAFlatString& aSourceLine,
                                 uint32_t aLineNumber,
@@ -2997,17 +2997,17 @@ nsContentUtils::ReportToConsole(uint32_t
                                      aDocument, aURI, aSourceLine,
                                      aLineNumber, aColumnNumber);
 }
 
 
 /* static */ nsresult
 nsContentUtils::ReportToConsoleNonLocalized(const nsAString& aErrorText,
                                             uint32_t aErrorFlags,
-                                            const char *aCategory,
+                                            const nsACString& aCategory,
                                             nsIDocument* aDocument,
                                             nsIURI* aURI,
                                             const nsAFlatString& aSourceLine,
                                             uint32_t aLineNumber,
                                             uint32_t aColumnNumber)
 {
   uint64_t innerWindowID = 0;
   if (aDocument) {
@@ -6286,34 +6286,16 @@ nsContentUtils::IsInPointerLockContext(n
 
   nsCOMPtr<nsIDOMWindow> top;
   aWin->GetScriptableTop(getter_AddRefs(top));
 
   return top == lockTop;
 }
 
 // static
-void
-nsContentUtils::ReleaseWrapper(void* aScriptObjectHolder,
-                               nsWrapperCache* aCache)
-{
-  if (aCache->PreservingWrapper()) {
-    // PreserveWrapper puts new DOM bindings in the JS holders hash, but they
-    // can also be in the DOM expando hash, so we need to try to remove them
-    // from both here.
-    JSObject* obj = aCache->GetWrapperPreserveColor();
-    if (aCache->IsDOMBinding() && obj && js::IsProxy(obj)) {
-        DOMProxyHandler::GetAndClearExpandoObject(obj);
-    }
-    aCache->SetPreservingWrapper(false);
-    DropJSObjects(aScriptObjectHolder);
-  }
-}
-
-// static
 int32_t
 nsContentUtils::GetAdjustedOffsetInTextControl(nsIFrame* aOffsetFrame,
                                                int32_t aOffset)
 {
   // The structure of the anonymous frames within a text control frame is
   // an optional block frame, followed by an optional br frame.
 
   // If the offset frame has a child, then this frame is the block which
--- 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
@@ -2475,17 +2476,17 @@ nsDocument::SendToConsole(nsCOMArray<nsI
   for (uint32_t i = 0; i < aMessages.Length(); ++i) {
     nsAutoString messageTag;
     aMessages[i]->GetTag(messageTag);
 
     nsAutoString category;
     aMessages[i]->GetCategory(category);
 
     nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
-                                    NS_ConvertUTF16toUTF8(category).get(),
+                                    NS_ConvertUTF16toUTF8(category),
                                     this, nsContentUtils::eSECURITY_PROPERTIES,
                                     NS_ConvertUTF16toUTF8(messageTag).get());
   }
 }
 
 nsresult
 nsDocument::InitCSP(nsIChannel* aChannel)
 {
@@ -7783,17 +7784,17 @@ nsDocument::Destroy()
   // leak-fixing if we fix nsDocumentViewer to do cycle-collection, but
   // tearing down all those frame trees right now is the right thing to do.
   mExternalResourceMap.Shutdown();
 
   mCustomPrototypes.Clear();
 
   // XXX We really should let cycle collection do this, but that currently still
   //     leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
-  nsContentUtils::ReleaseWrapper(static_cast<nsINode*>(this), this);
+  ReleaseWrapper(static_cast<nsINode*>(this));
 }
 
 void
 nsDocument::RemovedFromDocShell()
 {
   if (mRemovedFromDocShell)
     return;
 
--- 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);
@@ -689,17 +691,17 @@ nsGenericDOMDataNode::SaveSubtreeState()
 {
 }
 
 void
 nsGenericDOMDataNode::DestroyContent()
 {
   // XXX We really should let cycle collection do this, but that currently still
   //     leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
-  nsContentUtils::ReleaseWrapper(this, this);
+  ReleaseWrapper(this);
 }
 
 #ifdef DEBUG
 void
 nsGenericDOMDataNode::List(FILE* out, int32_t aIndent) const
 {
 }
 
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -1249,19 +1249,19 @@ nsINode::Traverse(nsINode *tmp, nsCycleC
     nsContentUtils::TraverseListenerManager(tmp, cb);
   }
 
   return true;
 }
 
 /* static */
 void
-nsINode::Unlink(nsINode *tmp)
+nsINode::Unlink(nsINode* tmp)
 {
-  nsContentUtils::ReleaseWrapper(tmp, tmp);
+  tmp->ReleaseWrapper(tmp);
 
   nsSlots *slots = tmp->GetExistingSlots();
   if (slots) {
     slots->Unlink();
   }
 
   if (tmp->NodeType() != nsIDOMNode::DOCUMENT_NODE &&
       tmp->HasFlag(NODE_HAS_LISTENERMANAGER)) {
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -255,17 +255,17 @@ nsInProcessTabChildGlobal::DelayedDiscon
     static_cast<nsFrameMessageManager*>(mMessageManager.get())->Disconnect();
     mMessageManager = nullptr;
   }
   if (mListenerManager) {
     mListenerManager->Disconnect();
   }
 
   if (!mLoadingScript) {
-    nsContentUtils::ReleaseWrapper(static_cast<EventTarget*>(this), this);
+    ReleaseWrapper(static_cast<EventTarget*>(this));
     mGlobal = nullptr;
   } else {
     mDelayedDisconnect = true;
   }
 }
 
 NS_IMETHODIMP_(nsIContent *)
 nsInProcessTabChildGlobal::GetOwnerContent()
--- 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/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -255,17 +255,17 @@ nsNodeUtils::LastRelease(nsINode* aNode)
     // if NODE_FORCE_XBL_BINDINGS is set, the node might still have a binding
     // attached
     if (aNode->HasFlag(NODE_FORCE_XBL_BINDINGS) &&
         ownerDoc->BindingManager()) {
       ownerDoc->BindingManager()->RemovedFromDocument(elem, ownerDoc);
     }
   }
 
-  nsContentUtils::ReleaseWrapper(aNode, aNode);
+  aNode->ReleaseWrapper(aNode);
 }
 
 struct MOZ_STACK_CLASS nsHandlerData
 {
   uint16_t mOperation;
   nsCOMPtr<nsIDOMNode> mSource;
   nsCOMPtr<nsIDOMNode> mDest;
   nsCxPusher mPusher;
--- 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/Touch.cpp
+++ b/content/events/src/Touch.cpp
@@ -129,42 +129,35 @@ Touch::GetForce(float* aForce)
 }
 
 void
 Touch::InitializePoints(nsPresContext* aPresContext, nsEvent* aEvent)
 {
   if (mPointsInitialized) {
     return;
   }
-  mClientPoint = nsDOMEvent::GetClientCoords(aPresContext,
-                                             aEvent,
-                                             mRefPoint,
-                                             mClientPoint);
-  mPagePoint = nsDOMEvent::GetPageCoords(aPresContext,
-                                         aEvent,
-                                         mRefPoint,
-                                         mClientPoint);
-  mScreenPoint = nsDOMEvent::GetScreenCoords(aPresContext, aEvent, mRefPoint);
+  mClientPoint = nsDOMEvent::GetClientCoords(
+    aPresContext, aEvent, LayoutDeviceIntPoint::FromUntyped(mRefPoint),
+    mClientPoint);
+  mPagePoint = nsDOMEvent::GetPageCoords(
+    aPresContext, aEvent, LayoutDeviceIntPoint::FromUntyped(mRefPoint),
+    mClientPoint);
+  mScreenPoint = nsDOMEvent::GetScreenCoords(aPresContext, aEvent,
+    LayoutDeviceIntPoint::FromUntyped(mRefPoint));
   mPointsInitialized = true;
 }
 
 bool
-Touch::Equals(nsIDOMTouch* aTouch)
+Touch::Equals(Touch* aTouch)
 {
-  float force;
-  float orientation;
-  int32_t radiusX, radiusY;
-  aTouch->GetForce(&force);
-  aTouch->GetRotationAngle(&orientation);
-  aTouch->GetRadiusX(&radiusX);
-  aTouch->GetRadiusY(&radiusY);
-  return mRefPoint != aTouch->mRefPoint ||
-         (mForce != force) ||
-         (mRotationAngle != orientation) ||
-         (mRadius.x != radiusX) || (mRadius.y != radiusY);
+  return mRefPoint == aTouch->mRefPoint &&
+         mForce == aTouch->Force() &&
+         mRotationAngle == aTouch->RotationAngle() &&
+         mRadius.x == aTouch->RadiusX() &&
+         mRadius.y == aTouch->RadiusY();
 }
 
 /* virtual */ JSObject*
 Touch::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return TouchBinding::Wrap(aCx, aScope, this);
 }
 
--- a/content/events/src/Touch.h
+++ b/content/events/src/Touch.h
@@ -80,17 +80,17 @@ public:
   NS_DECL_NSIDOMTOUCH
 
   void InitializePoints(nsPresContext* aPresContext, nsEvent* aEvent);
 
   void SetTarget(mozilla::dom::EventTarget *aTarget)
   {
     mTarget = aTarget;
   }
-  bool Equals(nsIDOMTouch* aTouch);
+  bool Equals(Touch* aTouch);
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
   EventTarget* GetParentObject() { return mTarget; }
 
   // WebIDL
   int32_t Identifier() const { return mIdentifier; }
   EventTarget* Target() const;
@@ -100,16 +100,20 @@ public:
   int32_t ClientY() const { return mClientPoint.y; }
   int32_t PageX() const { return mPagePoint.x; }
   int32_t PageY() const { return mPagePoint.y; }
   int32_t RadiusX() const { return mRadius.x; }
   int32_t RadiusY() const { return mRadius.y; }
   float RotationAngle() const { return mRotationAngle; }
   float Force() const { return mForce; }
 
+  nsCOMPtr<EventTarget> mTarget;
+  nsIntPoint mRefPoint;
+  bool mChanged;
+  uint32_t mMessage;
   int32_t mIdentifier;
   CSSIntPoint mPagePoint;
   CSSIntPoint mClientPoint;
   nsIntPoint mScreenPoint;
   nsIntPoint mRadius;
   float mRotationAngle;
   float mForce;
 protected:
--- a/content/events/src/nsContentEventHandler.cpp
+++ b/content/events/src/nsContentEventHandler.cpp
@@ -24,16 +24,17 @@
 #include "nsISelectionPrivate.h"
 #include "nsContentUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsIMEStateManager.h"
 #include "nsIObjectFrame.h"
 #include "mozilla/dom/Element.h"
 #include <algorithm>
 
+using namespace mozilla;
 using namespace mozilla::dom;
 
 /******************************************************************/
 /* nsContentEventHandler                                          */
 /******************************************************************/
 
 nsContentEventHandler::nsContentEventHandler(
                               nsPresContext* aPresContext) :
@@ -827,18 +828,18 @@ nsContentEventHandler::OnQueryCharacterA
     rootWidget = rootFrame->GetNearestWidget();
     NS_ENSURE_TRUE(rootWidget, NS_ERROR_FAILURE);
   }
 
   nsQueryContentEvent eventOnRoot(true, NS_QUERY_CHARACTER_AT_POINT,
                                   rootWidget);
   eventOnRoot.refPoint = aEvent->refPoint;
   if (rootWidget != aEvent->widget) {
-    eventOnRoot.refPoint += aEvent->widget->WidgetToScreenOffset();
-    eventOnRoot.refPoint -= rootWidget->WidgetToScreenOffset();
+    eventOnRoot.refPoint += LayoutDeviceIntPoint::FromUntyped(
+      aEvent->widget->WidgetToScreenOffset() - rootWidget->WidgetToScreenOffset());
   }
   nsPoint ptInRoot =
     nsLayoutUtils::GetEventCoordinatesRelativeTo(&eventOnRoot, rootFrame);
 
   nsIFrame* targetFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, ptInRoot);
   if (!targetFrame || targetFrame->GetType() != nsGkAtoms::textFrame ||
       !targetFrame->GetContent() ||
       !nsContentUtils::ContentIsDescendantOf(targetFrame->GetContent(),
@@ -886,26 +887,25 @@ nsContentEventHandler::OnQueryDOMWidgetH
 
   NS_ENSURE_TRUE(aEvent->widget, NS_ERROR_FAILURE);
 
   nsIDocument* doc = mPresShell->GetDocument();
   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
   nsIFrame* docFrame = mPresShell->GetRootFrame();
   NS_ENSURE_TRUE(docFrame, NS_ERROR_FAILURE);
 
-  nsIntPoint eventLoc =
-    aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
+  LayoutDeviceIntPoint eventLoc = aEvent->refPoint +
+    LayoutDeviceIntPoint::FromUntyped(aEvent->widget->WidgetToScreenOffset());
   nsIntRect docFrameRect = docFrame->GetScreenRect(); // Returns CSS pixels
-  eventLoc.x = mPresContext->DevPixelsToIntCSSPixels(eventLoc.x);
-  eventLoc.y = mPresContext->DevPixelsToIntCSSPixels(eventLoc.y);
-  eventLoc.x -= docFrameRect.x;
-  eventLoc.y -= docFrameRect.y;
+  CSSIntPoint eventLocCSS(
+    mPresContext->DevPixelsToIntCSSPixels(eventLoc.x) - docFrameRect.x,
+    mPresContext->DevPixelsToIntCSSPixels(eventLoc.y) - docFrameRect.y);
 
   Element* contentUnderMouse =
-    doc->ElementFromPointHelper(eventLoc.x, eventLoc.y, false, false);
+    doc->ElementFromPointHelper(eventLocCSS.x, eventLocCSS.y, false, false);
   if (contentUnderMouse) {
     nsIWidget* targetWidget = nullptr;
     nsIFrame* targetFrame = contentUnderMouse->GetPrimaryFrame();
     nsIObjectFrame* pluginFrame = do_QueryFrame(targetFrame);
     if (pluginFrame) {
       targetWidget = pluginFrame->GetWidget();
     } else if (targetFrame) {
       targetWidget = targetFrame->GetNearestWidget();
--- 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;
@@ -1058,17 +1060,17 @@ nsDOMEvent::Shutdown()
   if (sPopupAllowedEvents) {
     nsMemory::Free(sPopupAllowedEvents);
   }
 }
 
 nsIntPoint
 nsDOMEvent::GetScreenCoords(nsPresContext* aPresContext,
                             nsEvent* aEvent,
-                            nsIntPoint aPoint)
+                            LayoutDeviceIntPoint aPoint)
 {
   if (nsEventStateManager::sIsPointerLocked) {
     return nsEventStateManager::sLastScreenPoint;
   }
 
   if (!aEvent || 
        (aEvent->eventStructType != NS_MOUSE_EVENT &&
         aEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
@@ -1076,30 +1078,31 @@ nsDOMEvent::GetScreenCoords(nsPresContex
         aEvent->eventStructType != NS_TOUCH_EVENT &&
         aEvent->eventStructType != NS_DRAG_EVENT &&
         aEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT)) {
     return nsIntPoint(0, 0);
   }
 
   nsGUIEvent* guiEvent = static_cast<nsGUIEvent*>(aEvent);
   if (!guiEvent->widget) {
-    return aPoint;
+    return LayoutDeviceIntPoint::ToUntyped(aPoint);
   }
 
-  nsIntPoint offset = aPoint + guiEvent->widget->WidgetToScreenOffset();
+  LayoutDeviceIntPoint offset = aPoint +
+    LayoutDeviceIntPoint::FromUntyped(guiEvent->widget->WidgetToScreenOffset());
   nscoord factor = aPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel();
   return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(offset.x * factor),
                     nsPresContext::AppUnitsToIntCSSPixels(offset.y * factor));
 }
 
 //static
 CSSIntPoint
 nsDOMEvent::GetPageCoords(nsPresContext* aPresContext,
                           nsEvent* aEvent,
-                          nsIntPoint aPoint,
+                          LayoutDeviceIntPoint aPoint,
                           CSSIntPoint aDefaultPoint)
 {
   CSSIntPoint pagePoint = nsDOMEvent::GetClientCoords(aPresContext,
                                                       aEvent,
                                                       aPoint,
                                                       aDefaultPoint);
 
   // If there is some scrolling, add scroll info to client point.
@@ -1113,17 +1116,17 @@ nsDOMEvent::GetPageCoords(nsPresContext*
 
   return pagePoint;
 }
 
 // static
 CSSIntPoint
 nsDOMEvent::GetClientCoords(nsPresContext* aPresContext,
                             nsEvent* aEvent,
-                            nsIntPoint aPoint,
+                            LayoutDeviceIntPoint aPoint,
                             CSSIntPoint aDefaultPoint)
 {
   if (nsEventStateManager::sIsPointerLocked) {
     return nsEventStateManager::sLastClientPoint;
   }
 
   if (!aEvent ||
       (aEvent->eventStructType != NS_MOUSE_EVENT &&
@@ -1142,17 +1145,18 @@ nsDOMEvent::GetClientCoords(nsPresContex
     return CSSIntPoint(0, 0);
   }
 
   nsIFrame* rootFrame = shell->GetRootFrame();
   if (!rootFrame) {
     return CSSIntPoint(0, 0);
   }
   nsPoint pt =
-    nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, aPoint, rootFrame);
+    nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent,
+      LayoutDeviceIntPoint::ToUntyped(aPoint), rootFrame);
 
   return CSSIntPoint::FromAppUnitsRounded(pt);
 }
 
 // To be called ONLY by nsDOMEvent::GetType (which has the additional
 // logic for handling user-defined events).
 // static
 const char* nsDOMEvent::GetEventName(uint32_t aEventType)
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -97,23 +97,25 @@ public:
 
   static void PopupAllowedEventsChanged();
 
   static void Shutdown();
 
   static const char* GetEventName(uint32_t aEventType);
   static mozilla::CSSIntPoint
   GetClientCoords(nsPresContext* aPresContext, nsEvent* aEvent,
-                  nsIntPoint aPoint, mozilla::CSSIntPoint aDefaultPoint);
+                  mozilla::LayoutDeviceIntPoint aPoint,
+                  mozilla::CSSIntPoint aDefaultPoint);
   static mozilla::CSSIntPoint
-  GetPageCoords(nsPresContext* aPresContext, nsEvent* aEvent, nsIntPoint aPoint,
+  GetPageCoords(nsPresContext* aPresContext, nsEvent* aEvent,
+                mozilla::LayoutDeviceIntPoint aPoint,
                 mozilla::CSSIntPoint aDefaultPoint);
-  static nsIntPoint GetScreenCoords(nsPresContext* aPresContext,
-                                    nsEvent* aEvent,
-                                    nsIntPoint aPoint);
+  static nsIntPoint
+  GetScreenCoords(nsPresContext* aPresContext, nsEvent* aEvent,
+                  mozilla::LayoutDeviceIntPoint aPoint);
 
   static already_AddRefed<nsDOMEvent> Constructor(const mozilla::dom::GlobalObject& aGlobal,
                                                   const nsAString& aType,
                                                   const mozilla::dom::EventInit& aParam,
                                                   mozilla::ErrorResult& aRv);
 
   // Implemented as xpidl method
   // void GetType(nsString& aRetval) {}
--- 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;
@@ -78,17 +80,17 @@ NS_IMPL_DOMTARGET_DEFAULTS(nsDOMEventTar
 nsDOMEventTargetHelper::~nsDOMEventTargetHelper()
 {
   if (nsPIDOMWindow* owner = GetOwner()) {
     static_cast<nsGlobalWindow*>(owner)->RemoveEventTargetObject(this);
   }
   if (mListenerManager) {
     mListenerManager->Disconnect();
   }
-  nsContentUtils::ReleaseWrapper(this, this);
+  ReleaseWrapper(this);
 }
 
 void
 nsDOMEventTargetHelper::BindToOwner(nsPIDOMWindow* aOwner)
 {
   nsCOMPtr<nsIGlobalObject> glob = do_QueryInterface(aOwner);
   BindToOwner(glob);
 }
--- 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/nsDOMTouchEvent.cpp
+++ b/content/events/src/nsDOMTouchEvent.cpp
@@ -80,19 +80,18 @@ nsDOMTouchEvent::nsDOMTouchEvent(mozilla
                                  nsTouchEvent* aEvent)
   : nsDOMUIEvent(aOwner, aPresContext,
                  aEvent ? aEvent : new nsTouchEvent(false, 0, nullptr))
 {
   if (aEvent) {
     mEventIsInternal = false;
 
     for (uint32_t i = 0; i < aEvent->touches.Length(); ++i) {
-      nsIDOMTouch *touch = aEvent->touches[i];
-      dom::Touch *domtouch = static_cast<dom::Touch*>(touch);
-      domtouch->InitializePoints(mPresContext, aEvent);
+      Touch* touch = aEvent->touches[i];
+      touch->InitializePoints(mPresContext, aEvent);
     }
   } else {
     mEventIsInternal = true;
     mEvent->time = PR_Now();
   }
 }
 
 nsDOMTouchEvent::~nsDOMTouchEvent()
--- a/content/events/src/nsDOMUIEvent.cpp
+++ b/content/events/src/nsDOMUIEvent.cpp
@@ -97,17 +97,18 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED_1(nsD
 NS_IMPL_ADDREF_INHERITED(nsDOMUIEvent, nsDOMEvent)
 NS_IMPL_RELEASE_INHERITED(nsDOMUIEvent, nsDOMEvent)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMUIEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMUIEvent)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
 
 static nsIntPoint
-DevPixelsToCSSPixels(const nsIntPoint& aPoint, nsPresContext* aContext)
+DevPixelsToCSSPixels(const LayoutDeviceIntPoint& aPoint,
+                     nsPresContext* aContext)
 {
   return nsIntPoint(aContext->DevPixelsToIntCSSPixels(aPoint.x),
                     aContext->DevPixelsToIntCSSPixels(aPoint.y));
 }
 
 nsIntPoint
 nsDOMUIEvent::GetMovementPoint()
 {
@@ -370,17 +371,17 @@ nsDOMUIEvent::DuplicatePrivateData()
                                          mEvent->refPoint,
                                          mClientPoint);
   // GetScreenPoint converts mEvent->refPoint to right coordinates.
   nsIntPoint screenPoint = nsDOMEvent::GetScreenCoords(mPresContext,
                                                        mEvent,
                                                        mEvent->refPoint);
   nsresult rv = nsDOMEvent::DuplicatePrivateData();
   if (NS_SUCCEEDED(rv)) {
-    mEvent->refPoint = screenPoint;
+    mEvent->refPoint = LayoutDeviceIntPoint::FromUntyped(screenPoint);
   }
   return rv;
 }
 
 NS_IMETHODIMP_(void)
 nsDOMUIEvent::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType)
 {
   if (aSerializeInterfaceType) {
--- a/content/events/src/nsDOMUIEvent.h
+++ b/content/events/src/nsDOMUIEvent.h
@@ -29,34 +29,35 @@ public:
   NS_DECL_NSIDOMUIEVENT
   
   // Forward to nsDOMEvent
   NS_FORWARD_TO_NSDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION
   NS_IMETHOD DuplicatePrivateData() MOZ_OVERRIDE;
   NS_IMETHOD_(void) Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) MOZ_OVERRIDE;
   NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, void** aIter) MOZ_OVERRIDE;
 
-  static nsIntPoint CalculateScreenPoint(nsPresContext* aPresContext,
-                                         nsEvent* aEvent)
+  static nsIntPoint
+  CalculateScreenPoint(nsPresContext* aPresContext, nsEvent* aEvent)
   {
     if (!aEvent ||
         (aEvent->eventStructType != NS_MOUSE_EVENT &&
          aEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
          aEvent->eventStructType != NS_WHEEL_EVENT &&
          aEvent->eventStructType != NS_DRAG_EVENT &&
          aEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT)) {
       return nsIntPoint(0, 0);
     }
 
-    if (!((nsGUIEvent*)aEvent)->widget ) {
-      return aEvent->refPoint;
+    nsGUIEvent* event = static_cast<nsGUIEvent*>(aEvent);
+    if (!event->widget) {
+      return mozilla::LayoutDeviceIntPoint::ToUntyped(aEvent->refPoint);
     }
 
-    nsIntPoint offset = aEvent->refPoint +
-                        ((nsGUIEvent*)aEvent)->widget->WidgetToScreenOffset();
+    mozilla::LayoutDeviceIntPoint offset = aEvent->refPoint +
+      mozilla::LayoutDeviceIntPoint::FromUntyped(event->widget->WidgetToScreenOffset());
     nscoord factor = aPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel();
     return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(offset.x * factor),
                       nsPresContext::AppUnitsToIntCSSPixels(offset.y * factor));
   }
 
   static CSSIntPoint CalculateClientPoint(nsPresContext* aPresContext,
                                           nsEvent* aEvent,
                                           CSSIntPoint* aDefaultClientPoint)
--- 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/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -104,30 +104,30 @@
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //#define DEBUG_DOCSHELL_FOCUS
 
 #define NS_USER_INTERACTION_INTERVAL 5000 // ms
 
-static const nsIntPoint kInvalidRefPoint = nsIntPoint(-1,-1);
+static const LayoutDeviceIntPoint kInvalidRefPoint = LayoutDeviceIntPoint(-1,-1);
 
 static bool sLeftClickOnly = true;
 static bool sKeyCausesActivation = true;
 static uint32_t sESMInstanceCount = 0;
 static int32_t sChromeAccessModifier = 0, sContentAccessModifier = 0;
 int32_t nsEventStateManager::sUserInputEventDepth = 0;
 bool nsEventStateManager::sNormalLMouseEventInProcess = false;
 nsEventStateManager* nsEventStateManager::sActiveESM = nullptr;
 nsIDocument* nsEventStateManager::sMouseOverDocument = nullptr;
 nsWeakFrame nsEventStateManager::sLastDragOverFrame = nullptr;
-nsIntPoint nsEventStateManager::sLastRefPoint = kInvalidRefPoint;
-nsIntPoint nsEventStateManager::sLastScreenPoint = nsIntPoint(0,0);
-nsIntPoint nsEventStateManager::sSynthCenteringPoint = kInvalidRefPoint;
+LayoutDeviceIntPoint nsEventStateManager::sLastRefPoint = kInvalidRefPoint;
+nsIntPoint nsEventStateManager::sLastScreenPoint = nsIntPoint(0, 0);
+LayoutDeviceIntPoint nsEventStateManager::sSynthCenteringPoint = kInvalidRefPoint;
 CSSIntPoint nsEventStateManager::sLastClientPoint = CSSIntPoint(0, 0);
 bool nsEventStateManager::sIsPointerLocked = false;
 // Reference to the pointer locked element.
 nsWeakPtr nsEventStateManager::sPointerLockedElement;
 // Reference to the document which requested pointer lock.
 nsWeakPtr nsEventStateManager::sPointerLockedDoc;
 nsCOMPtr<nsIContent> nsEventStateManager::sDragOverContent = nullptr;
 
@@ -562,17 +562,18 @@ nsMouseWheelTransaction::SetTimeout()
   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "nsITimer::InitWithFuncCallback failed");
 }
 
 nsIntPoint
 nsMouseWheelTransaction::GetScreenPoint(nsGUIEvent* aEvent)
 {
   NS_ASSERTION(aEvent, "aEvent is null");
   NS_ASSERTION(aEvent->widget, "aEvent-widget is null");
-  return aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
+  return LayoutDeviceIntPoint::ToUntyped(aEvent->refPoint) +
+         aEvent->widget->WidgetToScreenOffset();
 }
 
 uint32_t
 nsMouseWheelTransaction::GetTimeoutTime()
 {
   return Preferences::GetUint("mousewheel.transaction.timeout", 1500);
 }
 
@@ -1542,29 +1543,28 @@ nsEventStateManager::GetChildProcessOffs
                                                             targetFrame);
   return LayoutDeviceIntPoint::FromAppUnitsToNearest(pt, presContext->AppUnitsPerDevPixel());
 }
 
 /*static*/ void
 nsEventStateManager::MapEventCoordinatesForChildProcess(
   const LayoutDeviceIntPoint& aOffset, nsEvent* aEvent)
 {
-  nsIntPoint aOffsetIntPoint(aOffset.x, aOffset.y);
   if (aEvent->eventStructType != NS_TOUCH_EVENT) {
-    aEvent->refPoint = aOffsetIntPoint;
+    aEvent->refPoint = aOffset;
   } else {
-    aEvent->refPoint = nsIntPoint();
+    aEvent->refPoint = LayoutDeviceIntPoint();
     nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
     // Then offset all the touch points by that distance, to put them
     // in the space where top-left is 0,0.
     const nsTArray< nsRefPtr<Touch> >& touches = touchEvent->touches;
     for (uint32_t i = 0; i < touches.Length(); ++i) {
-      nsIDOMTouch* touch = touches[i];
+      Touch* touch = touches[i];
       if (touch) {
-        touch->mRefPoint += aOffsetIntPoint;
+        touch->mRefPoint += LayoutDeviceIntPoint::ToUntyped(aOffset);
       }
     }
   }
 }
 
 /*static*/ void
 nsEventStateManager::MapEventCoordinatesForChildProcess(nsFrameLoader* aFrameLoader,
                                                         nsEvent* aEvent)
@@ -1636,25 +1636,25 @@ nsEventStateManager::HandleCrossProcessE
     // all of them and collect the unique set of targets for event
     // forwarding.
     //
     // This loop is similar to the one used in
     // PresShell::DispatchTouchEvent().
     nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
     const nsTArray< nsRefPtr<Touch> >& touches = touchEvent->touches;
     for (uint32_t i = 0; i < touches.Length(); ++i) {
-      nsIDOMTouch* touch = touches[i];
+      Touch* touch = touches[i];
       // NB: the |mChanged| check is an optimization, subprocesses can
       // compute this for themselves.  If the touch hasn't changed, we
       // may be able to avoid forwarding the event entirely (which is
       // not free).
       if (!touch || !touch->mChanged) {
         continue;
       }
-      nsCOMPtr<EventTarget> targetPtr = touch->GetTarget();
+      nsCOMPtr<EventTarget> targetPtr = touch->mTarget;
       if (!targetPtr) {
         continue;
       }
       nsCOMPtr<nsIContent> target = do_QueryInterface(targetPtr);
       if (IsRemoteTarget(target) && !targets.Contains(target)) {
         targets.AppendElement(target);
       }
     }
@@ -1916,17 +1916,17 @@ nsEventStateManager::BeginTrackingDragGe
                                               nsIFrame* inDownFrame)
 {
   if (!inDownEvent->widget)
     return;
 
   // Note that |inDownEvent| could be either a mouse down event or a
   // synthesized mouse move event.
   mGestureDownPoint = inDownEvent->refPoint +
-    inDownEvent->widget->WidgetToScreenOffset();
+    LayoutDeviceIntPoint::FromUntyped(inDownEvent->widget->WidgetToScreenOffset());
 
   inDownFrame->GetContentForEvent(inDownEvent,
                                   getter_AddRefs(mGestureDownContent));
 
   mGestureDownFrameOwner = inDownFrame->GetContent();
   mGestureModifiers = inDownEvent->modifiers;
   mGestureDownButtons = inDownEvent->buttons;
 
@@ -1954,18 +1954,18 @@ void
 nsEventStateManager::FillInEventFromGestureDown(nsMouseEvent* aEvent)
 {
   NS_ASSERTION(aEvent->widget == mCurrentTarget->GetNearestWidget(),
                "Incorrect widget in event");
 
   // Set the coordinates in the new event to the coordinates of
   // the old event, adjusted for the fact that the widget might be
   // different
-  nsIntPoint tmpPoint = aEvent->widget->WidgetToScreenOffset();
-  aEvent->refPoint = mGestureDownPoint - tmpPoint;
+  aEvent->refPoint = mGestureDownPoint -
+    LayoutDeviceIntPoint::FromUntyped(aEvent->widget->WidgetToScreenOffset());
   aEvent->modifiers = mGestureModifiers;
   aEvent->buttons = mGestureDownButtons;
 }
 
 //
 // GenerateDragGesture
 //
 // If we're in the TRACKING state of the d&d gesture tracker, check the current position
@@ -2011,17 +2011,18 @@ nsEventStateManager::GenerateDragGesture
         LookAndFeel::GetInt(LookAndFeel::eIntID_DragThresholdY, 0);
       if (!pixelThresholdX)
         pixelThresholdX = 5;
       if (!pixelThresholdY)
         pixelThresholdY = 5;
     }
 
     // fire drag gesture if mouse has moved enough
-    nsIntPoint pt = aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
+    LayoutDeviceIntPoint pt = aEvent->refPoint +
+      LayoutDeviceIntPoint::FromUntyped(aEvent->widget->WidgetToScreenOffset());
     if (DeprecatedAbs(pt.x - mGestureDownPoint.x) > pixelThresholdX ||
         DeprecatedAbs(pt.y - mGestureDownPoint.y) > pixelThresholdY) {
       if (mClickHoldContextMenu) {
         // stop the click-hold before we fire off the drag gesture, in case
         // it takes a long time
         KillClickHoldTimer();
       }
 
@@ -3481,19 +3482,19 @@ nsEventStateManager::PostHandleEvent(nsP
 
         nsCOMPtr<nsIWidget> widget = mCurrentTarget->GetNearestWidget();
         nsDragEvent event(aEvent->mFlags.mIsTrusted,
                           NS_DRAGDROP_DRAGDROP, widget);
 
         nsMouseEvent* mouseEvent = static_cast<nsMouseEvent*>(aEvent);
         event.refPoint = mouseEvent->refPoint;
         if (mouseEvent->widget) {
-          event.refPoint += mouseEvent->widget->WidgetToScreenOffset();
+          event.refPoint += LayoutDeviceIntPoint::FromUntyped(mouseEvent->widget->WidgetToScreenOffset());
         }
-        event.refPoint -= widget->WidgetToScreenOffset();
+        event.refPoint -= LayoutDeviceIntPoint::FromUntyped(widget->WidgetToScreenOffset());
         event.modifiers = mouseEvent->modifiers;
         event.buttons = mouseEvent->buttons;
         event.inputSource = mouseEvent->inputSource;
 
         nsEventStatus status = nsEventStatus_eIgnore;
         nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
         if (presShell) {
           presShell->HandleEventWithTarget(&event, mCurrentTarget,
@@ -4140,22 +4141,22 @@ nsEventStateManager::NotifyMouseOver(nsG
 // nsDOMUIEvent::refPoint is in.
 //
 // XXX Hack alert: XXX
 // However, we do the computation in integer CSS pixels, NOT device pix,
 // in order to fudge around the one-pixel error in innerHeight in fullscreen
 // mode (see bug 799523 comment 35, and bug 729011). Using integer CSS pix
 // makes us throw away the fractional error that results, rather than having
 // it manifest as a potential one-device-pix discrepancy.
-static nsIntPoint
+static LayoutDeviceIntPoint
 GetWindowInnerRectCenter(nsPIDOMWindow* aWindow,
                          nsIWidget* aWidget,
                          nsPresContext* aContext)
 {
-  NS_ENSURE_TRUE(aWindow && aWidget && aContext, nsIntPoint(0,0));
+  NS_ENSURE_TRUE(aWindow && aWidget && aContext, LayoutDeviceIntPoint(0, 0));
 
   float cssInnerX = 0.0;
   aWindow->GetMozInnerScreenX(&cssInnerX);
   int32_t innerX = int32_t(NS_round(cssInnerX));
 
   float cssInnerY = 0.0;
   aWindow->GetMozInnerScreenY(&cssInnerY);
   int32_t innerY = int32_t(NS_round(cssInnerY));
@@ -4167,17 +4168,17 @@ GetWindowInnerRectCenter(nsPIDOMWindow* 
   aWindow->GetInnerHeight(&innerHeight);
 
   nsIntRect screen;
   aWidget->GetScreenBounds(screen);
 
   int32_t cssScreenX = aContext->DevPixelsToIntCSSPixels(screen.x);
   int32_t cssScreenY = aContext->DevPixelsToIntCSSPixels(screen.y);
 
-  return nsIntPoint(
+  return LayoutDeviceIntPoint(
     aContext->CSSPixelsToDevPixels(innerX - cssScreenX + innerWidth / 2),
     aContext->CSSPixelsToDevPixels(innerY - cssScreenY + innerHeight / 2));
 }
 
 void
 nsEventStateManager::GenerateMouseEnterExit(nsGUIEvent* aEvent)
 {
   EnsureDocument(mPresContext);
@@ -4195,29 +4196,29 @@ nsEventStateManager::GenerateMouseEnterE
       //   previous_mousemove_refPoint - current_mousemove_refPoint.
       if (sIsPointerLocked && aEvent->widget) {
         // The pointer is locked. If the pointer is not located at the center of
         // the window, dispatch a synthetic mousemove to return the pointer there.
         // Doing this between "real" pointer moves gives the impression that the
         // (locked) pointer can continue moving and won't stop at the screen
         // boundary. We cancel the synthetic event so that we don't end up
         // dispatching the centering move event to content.
-        nsIntPoint center = GetWindowInnerRectCenter(mDocument->GetWindow(),
-                                                     aEvent->widget,
-                                                     mPresContext);
+        LayoutDeviceIntPoint center =
+          GetWindowInnerRectCenter(mDocument->GetWindow(), aEvent->widget,
+                                   mPresContext);
         aEvent->lastRefPoint = center;
         if (aEvent->refPoint != center) {
           // Mouse move doesn't finish at the center of the window. Dispatch a
           // synthetic native mouse event to move the pointer back to the center
           // of the window, to faciliate more movement. But first, record that
           // we've dispatched a synthetic mouse movement, so we can cancel it
           // in the other branch here.
           sSynthCenteringPoint = center;
           aEvent->widget->SynthesizeNativeMouseMove(
-            center + aEvent->widget->WidgetToScreenOffset());
+            LayoutDeviceIntPoint::ToUntyped(center) + aEvent->widget->WidgetToScreenOffset());
         } else if (aEvent->refPoint == sSynthCenteringPoint) {
           // This is the "synthetic native" event we dispatched to re-center the
           // pointer. Cancel it so we don't expose the centering move to content.
           aEvent->mFlags.mPropagationStopped = true;
           // Clear sSynthCenteringPoint so we don't cancel other events
           // targeted at the center.
           sSynthCenteringPoint = kInvalidRefPoint;
         }
@@ -4297,33 +4298,33 @@ nsEventStateManager::SetPointerLock(nsIW
 
     // Fire a synthetic mouse move to ensure event state is updated. We first
     // set the mouse to the center of the window, so that the mouse event
     // doesn't report any movement.
     sLastRefPoint = GetWindowInnerRectCenter(aElement->OwnerDoc()->GetWindow(),
                                              aWidget,
                                              mPresContext);
     aWidget->SynthesizeNativeMouseMove(
-      sLastRefPoint + aWidget->WidgetToScreenOffset());
+      LayoutDeviceIntPoint::ToUntyped(sLastRefPoint) + aWidget->WidgetToScreenOffset());
 
     // Retarget all events to this element via capture.
     nsIPresShell::SetCapturingContent(aElement, CAPTURE_POINTERLOCK);
 
     // Suppress DnD
     if (dragService) {
       dragService->Suppress();
     }
   } else {
     // Unlocking, so return pointer to the original position by firing a
     // synthetic mouse event. We first reset sLastRefPoint to its
     // pre-pointerlock position, so that the synthetic mouse event reports
     // no movement.
     sLastRefPoint = mPreLockPoint;
     aWidget->SynthesizeNativeMouseMove(
-      mPreLockPoint + aWidget->WidgetToScreenOffset());
+      LayoutDeviceIntPoint::ToUntyped(mPreLockPoint) + aWidget->WidgetToScreenOffset());
 
     // Don't retarget events to this element any more.
     nsIPresShell::SetCapturingContent(nullptr, CAPTURE_POINTERLOCK);
 
     // Unsuppress DnD
     if (dragService) {
       dragService->Unsuppress();
     }
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -708,37 +708,37 @@ private:
                                   nsEventStates aState,
                                   bool aAddState);
 
   int32_t     mLockCursor;
 
   // Last mouse event refPoint (the offset from the widget's origin in
   // device pixels) when mouse was locked, used to restore mouse position
   // after unlocking.
-  nsIntPoint  mPreLockPoint;
+  mozilla::LayoutDeviceIntPoint mPreLockPoint;
 
   // Stores the refPoint of the last synthetic mouse move we dispatched
   // to re-center the mouse when we were pointer locked. If this is (-1,-1) it
   // means we've not recently dispatched a centering event. We use this to
   // detect when we receive the synth event, so we can cancel and not send it
   // to content.
-  static nsIntPoint sSynthCenteringPoint;
+  static mozilla::LayoutDeviceIntPoint sSynthCenteringPoint;
 
   nsWeakFrame mCurrentTarget;
   nsCOMPtr<nsIContent> mCurrentTargetContent;
   nsWeakFrame mLastMouseOverFrame;
   nsCOMPtr<nsIContent> mLastMouseOverElement;
   static nsWeakFrame sLastDragOverFrame;
 
   // Stores the refPoint (the offset from the widget's origin in device
   // pixels) of the last mouse event.
-  static nsIntPoint sLastRefPoint;
+  static mozilla::LayoutDeviceIntPoint sLastRefPoint;
 
   // member variables for the d&d gesture state machine
-  nsIntPoint mGestureDownPoint; // screen coordinates
+  mozilla::LayoutDeviceIntPoint mGestureDownPoint; // screen coordinates
   // The content to use as target if we start a d&d (what we drag).
   nsCOMPtr<nsIContent> mGestureDownContent;
   // The content of the frame where the mouse-down event occurred. It's the same
   // as the target in most cases but not always - for example when dragging
   // an <area> of an image map this is the image. (bug 289667)
   nsCOMPtr<nsIContent> mGestureDownFrameOwner;
   // State of keys when the original gesture-down happened
   mozilla::widget::Modifiers mGestureModifiers;
--- 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/HTMLLabelElement.cpp
+++ b/content/html/content/src/HTMLLabelElement.cpp
@@ -110,17 +110,17 @@ EventTargetIn(nsEvent *aEvent, nsIConten
 }
 
 static void
 DestroyMouseDownPoint(void *    /*aObject*/,
                       nsIAtom * /*aPropertyName*/,
                       void *    aPropertyValue,
                       void *    /*aData*/)
 {
-  nsIntPoint* pt = static_cast<nsIntPoint*>(aPropertyValue);
+  LayoutDeviceIntPoint* pt = static_cast<LayoutDeviceIntPoint*>(aPropertyValue);
   delete pt;
 }
 
 nsresult
 HTMLLabelElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
   if (mHandlingEvent ||
       (!NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) &&
@@ -140,33 +140,35 @@ HTMLLabelElement::PostHandleEvent(nsEven
     switch (aVisitor.mEvent->message) {
       case NS_MOUSE_BUTTON_DOWN:
         NS_ASSERTION(aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT,
                      "wrong event struct for event");
         if (static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
             nsMouseEvent::eLeftButton) {
           // We reset the mouse-down point on every event because there is
           // no guarantee we will reach the NS_MOUSE_CLICK code below.
-          nsIntPoint *curPoint = new nsIntPoint(aVisitor.mEvent->refPoint);
+          LayoutDeviceIntPoint* curPoint =
+            new LayoutDeviceIntPoint(aVisitor.mEvent->refPoint);
           SetProperty(nsGkAtoms::labelMouseDownPtProperty,
-                      static_cast<void *>(curPoint),
+                      static_cast<void*>(curPoint),
                       DestroyMouseDownPoint);
         }
         break;
 
       case NS_MOUSE_CLICK:
         if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent)) {
           const nsMouseEvent* event =
             static_cast<const nsMouseEvent*>(aVisitor.mEvent);
-          nsIntPoint *mouseDownPoint = static_cast<nsIntPoint *>
-            (GetProperty(nsGkAtoms::labelMouseDownPtProperty));
+          LayoutDeviceIntPoint* mouseDownPoint =
+            static_cast<LayoutDeviceIntPoint*>(
+              GetProperty(nsGkAtoms::labelMouseDownPtProperty));
 
           bool dragSelect = false;
           if (mouseDownPoint) {
-            nsIntPoint dragDistance = *mouseDownPoint;
+            LayoutDeviceIntPoint dragDistance = *mouseDownPoint;
             DeleteProperty(nsGkAtoms::labelMouseDownPtProperty);
 
             dragDistance -= aVisitor.mEvent->refPoint;
             const int CLICK_DISTANCE = 2;
             dragSelect = dragDistance.x > CLICK_DISTANCE ||
                          dragDistance.x < -CLICK_DISTANCE ||
                          dragDistance.y > CLICK_DISTANCE ||
                          dragDistance.y < -CLICK_DISTANCE;
--- 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/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -37,12 +37,8 @@ INCLUDES	+= \
 		-I$(srcdir) \
 		-I$(topsrcdir)/xpcom/ds \
 		-I$(topsrcdir)/content/media/ \
 		$(NULL)
 
 DEFINES		+= \
 		-D_IMPL_NS_LAYOUT \
 		$(NULL)
-
-ifdef MOZ_WEBGL
-DEFINES += -DMOZ_WEBGL
-endif
--- 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/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -978,39 +978,51 @@ MediaStreamGraphImpl::EnsureNextIteratio
     return;
   mNeedAnotherIteration = true;
   if (mWaitState == WAITSTATE_WAITING_INDEFINITELY) {
     mWaitState = WAITSTATE_WAKING_UP;
     aLock.Notify();
   }
 }
 
+/**
+ * Returns smallest value of t such that
+ * TimeToTicksRoundUp(aSampleRate, t) is a multiple of WEBAUDIO_BLOCK_SIZE
+ * and floor(TimeToTicksRoundUp(aSampleRate, t)/WEBAUDIO_BLOCK_SIZE) >
+ * floor(TimeToTicksRoundUp(aSampleRate, aTime)/WEBAUDIO_BLOCK_SIZE).
+ */
 static GraphTime
-RoundUpToAudioBlock(TrackRate aSampleRate, GraphTime aTime)
+RoundUpToNextAudioBlock(TrackRate aSampleRate, GraphTime aTime)
 {
-  int64_t ticksAtIdealaSampleRate = (aTime*aSampleRate) >> MEDIA_TIME_FRAC_BITS;
-  // Round up to nearest block boundary
-  int64_t blocksAtIdealaSampleRate =
-    (ticksAtIdealaSampleRate + (WEBAUDIO_BLOCK_SIZE - 1)) >>
-    WEBAUDIO_BLOCK_SIZE_BITS;
-  // Round up to nearest MediaTime unit
-  return
-    ((((blocksAtIdealaSampleRate + 1)*WEBAUDIO_BLOCK_SIZE) << MEDIA_TIME_FRAC_BITS)
-     + aSampleRate - 1)/aSampleRate;
+  TrackTicks ticks = TimeToTicksRoundUp(aSampleRate, aTime);
+  uint64_t block = ticks >> WEBAUDIO_BLOCK_SIZE_BITS;
+  uint64_t nextBlock = block + 1;
+  TrackTicks nextTicks = nextBlock << WEBAUDIO_BLOCK_SIZE_BITS;
+  // Find the smallest time t such that TimeToTicksRoundUp(aSampleRate,t) == nextTicks
+  // That's the smallest integer t such that
+  //   t*aSampleRate > ((nextTicks - 1) << MEDIA_TIME_FRAC_BITS)
+  // Both sides are integers, so this is equivalent to
+  //   t*aSampleRate >= ((nextTicks - 1) << MEDIA_TIME_FRAC_BITS) + 1
+  //   t >= (((nextTicks - 1) << MEDIA_TIME_FRAC_BITS) + 1)/aSampleRate
+  //   t = ceil((((nextTicks - 1) << MEDIA_TIME_FRAC_BITS) + 1)/aSampleRate)
+  // Using integer division, that's
+  //   t = (((nextTicks - 1) << MEDIA_TIME_FRAC_BITS) + 1 + aSampleRate - 1)/aSampleRate
+  //     = ((nextTicks - 1) << MEDIA_TIME_FRAC_BITS)/aSampleRate + 1
+  return ((nextTicks - 1) << MEDIA_TIME_FRAC_BITS)/aSampleRate + 1;
 }
 
 void
 MediaStreamGraphImpl::ProduceDataForStreamsBlockByBlock(uint32_t aStreamIndex,
                                                         TrackRate aSampleRate,
                                                         GraphTime aFrom,
                                                         GraphTime aTo)
 {
   GraphTime t = aFrom;
   while (t < aTo) {
-    GraphTime next = RoundUpToAudioBlock(aSampleRate, t + 1);
+    GraphTime next = RoundUpToNextAudioBlock(aSampleRate, t);
     for (uint32_t i = aStreamIndex; i < mStreams.Length(); ++i) {
       nsRefPtr<ProcessedMediaStream> ps = mStreams[i]->AsProcessedStream();
       if (ps) {
         ps->ProduceOutput(t, next);
       }
     }
     t = next;
   }
@@ -1064,17 +1076,17 @@ MediaStreamGraphImpl::RunThread()
           // We know that the rest of the streams will run at the same rate.
           sampleRate = n->SampleRate();
           break;
         }
       }
     }
 
     GraphTime endBlockingDecisions =
-      RoundUpToAudioBlock(sampleRate, mCurrentTime + MillisecondsToMediaTime(AUDIO_TARGET_MS));
+      RoundUpToNextAudioBlock(sampleRate, mCurrentTime + MillisecondsToMediaTime(AUDIO_TARGET_MS));
     bool ensureNextIteration = false;
 
     // Grab pending stream input.
     for (uint32_t i = 0; i < mStreams.Length(); ++i) {
       SourceMediaStream* is = mStreams[i]->AsSourceStream();
       if (is) {
         UpdateConsumptionState(is);
         ExtractPendingInput(is, endBlockingDecisions, &ensureNextIteration);
--- 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/SVGPathElement.cpp
+++ b/content/svg/content/src/SVGPathElement.cpp
@@ -1,22 +1,25 @@
 /* -*- 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 "nsGkAtoms.h"
+#include "mozilla/dom/SVGPathElement.h"
+
+#include <algorithm>
+
 #include "DOMSVGPathSeg.h"
 #include "DOMSVGPathSegList.h"
+#include "DOMSVGPoint.h"
+#include "gfxPath.h"
+#include "mozilla/dom/SVGPathElementBinding.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
-#include "mozilla/dom/SVGPathElement.h"
-#include "DOMSVGPoint.h"
-#include <algorithm>
-#include "mozilla/dom/SVGPathElementBinding.h"
+#include "nsGkAtoms.h"
 
 class gfxContext;
 
 NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Path)
 
 namespace mozilla {
 namespace dom {
 
--- 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/svg/content/src/nsSVGPathGeometryElement.h
+++ b/content/svg/content/src/nsSVGPathGeometryElement.h
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __NS_SVGPATHGEOMETRYELEMENT_H__
 #define __NS_SVGPATHGEOMETRYELEMENT_H__
 
 #include "SVGGraphicsElement.h"
 
+class gfxFlattenedPath;
 struct gfxMatrix;
 template <class E> class nsTArray;
 
 struct nsSVGMark {
   enum Type {
     eStart,
     eMid,
     eEnd,
--- 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/xbl/src/nsXBLService.cpp
+++ b/content/xbl/src/nsXBLService.cpp
@@ -896,16 +896,20 @@ nsXBLService::LoadBindingDocumentInfo(ns
 
   if (!info) {
     // The second line of defense is the binding manager's document table.
     nsBindingManager *bindingManager = nullptr;
 
     if (aBoundDocument) {
       bindingManager = aBoundDocument->BindingManager();
       info = bindingManager->GetXBLDocumentInfo(documentURI);
+      if (aBoundDocument->IsStaticDocument() &&
+          IsChromeOrResourceURI(aBindingURI)) {
+        aForceSyncLoad = true;
+      }
     }
 
     nsINodeInfo *ni = nullptr;
     if (aBoundElement)
       ni = aBoundElement->NodeInfo();
 
     if (!info && bindingManager &&
         (!ni || !(ni->Equals(nsGkAtoms::scrollbar, kNameSpaceID_XUL) ||
--- 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/Makefile.in
+++ b/content/xslt/src/xslt/Makefile.in
@@ -12,21 +12,16 @@ include $(DEPTH)/config/autoconf.mk
 LIBXUL_LIBRARY = 1
 FAIL_ON_WARNINGS = 1
 
 # For nsDependentJSString
 LOCAL_INCLUDES += \
   -I$(topsrcdir)/dom/base \
   $(NULL)
 
-EXTRA_COMPONENTS = \
-  txEXSLTRegExFunctions.js \
-  txEXSLTRegExFunctions.manifest \
-  $(NULL)
-
 include $(topsrcdir)/config/rules.mk
 
 INCLUDES += \
 	-I$(srcdir) \
 	-I$(srcdir)/../base \
 	-I$(srcdir)/../xml \
 	-I$(srcdir)/../xpath \
 	-I$(srcdir)/../../../base/src \
--- a/content/xslt/src/xslt/moz.build
+++ b/content/xslt/src/xslt/moz.build
@@ -34,10 +34,15 @@ CPP_SOURCES += [
     'txXPathResultComparator.cpp',
     'txXSLTEnvironmentFunctionCall.cpp',
     'txXSLTNumber.cpp',
     'txXSLTNumberCounters.cpp',
     'txXSLTPatterns.cpp',
     'txXSLTProcessor.cpp',
 ]
 
+EXTRA_COMPONENTS += [
+    'txEXSLTRegExFunctions.js',
+    'txEXSLTRegExFunctions.manifest',
+]
+
 LIBRARY_NAME = 'txxslt_s'
 
--- 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/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2123,17 +2123,17 @@ nsDocShell::GetUsePrivateBrowsing(bool* 
 }
 
 NS_IMETHODIMP
 nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing)
 {
     nsContentUtils::ReportToConsoleNonLocalized(
         NS_LITERAL_STRING("Only internal code is allowed to set the usePrivateBrowsing attribute"),
         nsIScriptError::warningFlag,
-        "Internal API Used",
+        NS_LITERAL_CSTRING("Internal API Used"),
         mContentViewer ? mContentViewer->GetDocument() : nullptr);
 
     return SetPrivateBrowsing(aUsePrivateBrowsing);
 }
 
 NS_IMETHODIMP
 nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing)
 {
--- 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;
deleted file mode 100644
--- a/dom/apps/src/Makefile.in
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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/.
-
-DEPTH     = @DEPTH@
-topsrcdir = @top_srcdir@
-srcdir    = @srcdir@
-VPATH     = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-
-EXTRA_PP_JS_MODULES += \
-  Webapps.jsm \
-  AppsUtils.jsm \
-  $(NULL)
-
-include $(topsrcdir)/config/rules.mk
--- 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,26 @@
 # 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',
 ]
+
+EXTRA_PP_JS_MODULES += [
+    'AppsUtils.jsm',
+    'Webapps.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/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -615,24 +615,23 @@ nsDOMWindowUtils::SendMouseEventToWindow
                                          unsigned short aInputSourceArg)
 {
   PROFILER_LABEL("nsDOMWindowUtils", "SendMouseEventToWindow");
   return SendMouseEventCommon(aType, aX, aY, aButton, aClickCount, aModifiers,
                               aIgnoreRootScrollFrame, aPressure,
                               aInputSourceArg, true, nullptr);
 }
 
-static nsIntPoint
-ToWidgetPoint(float aX, float aY, const nsPoint& aOffset,
+static LayoutDeviceIntPoint
+ToWidgetPoint(const CSSPoint& aPoint, const nsPoint& aOffset,
               nsPresContext* aPresContext)
 {
-  double appPerDev = aPresContext->AppUnitsPerDevPixel();
-  nscoord appPerCSS = nsPresContext::AppUnitsPerCSSPixel();
-  return nsIntPoint(NSToIntRound((aX*appPerCSS + aOffset.x)/appPerDev),
-                    NSToIntRound((aY*appPerCSS + aOffset.y)/appPerDev));
+  return LayoutDeviceIntPoint::FromAppUnits(
+    CSSPoint::ToAppUnits(aPoint) + aOffset,
+    aPresContext->AppUnitsPerDevPixel());
 }
 
 static inline int16_t
 GetButtonsFlagForButton(int32_t aButton)
 {
   switch (aButton) {
     case nsMouseEvent::eLeftButton:
       return nsMouseEvent::eLeftButtonFlag;
@@ -709,17 +708,17 @@ nsDOMWindowUtils::SendMouseEventCommon(c
   event.clickCount = aClickCount;
   event.time = PR_IntervalNow();
   event.mFlags.mIsSynthesizedForTests = true;
 
   nsPresContext* presContext = GetPresContext();
   if (!presContext)
     return NS_ERROR_FAILURE;
 
-  event.refPoint = ToWidgetPoint(aX, aY, offset, presContext);
+  event.refPoint = ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
   event.ignoreRootScrollFrame = aIgnoreRootScrollFrame;
 
   nsEventStatus status;
   if (aToWindow) {
     nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
     if (!presShell)
       return NS_ERROR_FAILURE;
     nsViewManager* viewManager = presShell->GetViewManager();
@@ -781,17 +780,17 @@ nsDOMWindowUtils::SendWheelEvent(float a
   wheelEvent.lineOrPageDeltaY = aLineOrPageDeltaY;
   wheelEvent.widget = widget;
 
   wheelEvent.time = PR_Now() / 1000;
 
   nsPresContext* presContext = GetPresContext();
   NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
 
-  wheelEvent.refPoint = ToWidgetPoint(aX, aY, offset, presContext);
+  wheelEvent.refPoint = ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
 
   nsEventStatus status;
   nsresult rv = widget->DispatchEvent(&wheelEvent, status);
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool failedX = false;
   if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_ZERO) &&
       wheelEvent.overflowDeltaX != 0) {
@@ -877,19 +876,20 @@ nsDOMWindowUtils::SendTouchEvent(const n
   event.time = PR_Now();
 
   nsPresContext* presContext = GetPresContext();
   if (!presContext) {
     return NS_ERROR_FAILURE;
   }
   event.touches.SetCapacity(aCount);
   for (uint32_t i = 0; i < aCount; ++i) {
-    nsIntPoint pt = ToWidgetPoint(aXs[i], aYs[i], offset, presContext);
+    LayoutDeviceIntPoint pt =
+      ToWidgetPoint(CSSPoint(aXs[i], aYs[i]), offset, presContext);
     nsRefPtr<Touch> t = new Touch(aIdentifiers[i],
-                                  pt,
+                                  LayoutDeviceIntPoint::ToUntyped(pt),
                                   nsIntPoint(aRxs[i], aRys[i]),
                                   aRotationAngles[i],
                                   aForces[i]);
     event.touches.AppendElement(t);
   }
 
   nsEventStatus status;
   nsresult rv = widget->DispatchEvent(&event, status);
@@ -1261,17 +1261,17 @@ nsDOMWindowUtils::SendSimpleGestureEvent
   event.modifiers = GetWidgetModifiers(aModifiers);
   event.clickCount = aClickCount;
   event.time = PR_IntervalNow();
 
   nsPresContext* presContext = GetPresContext();
   if (!presContext)
     return NS_ERROR_FAILURE;
 
-  event.refPoint = ToWidgetPoint(aX, aY, offset, presContext);
+  event.refPoint = ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
 
   nsEventStatus status;
   return widget->DispatchEvent(&event, status);
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::ElementFromPoint(float aX, float aY,
                                    bool aIgnoreRootScrollFrame,
@@ -1751,17 +1751,17 @@ nsDOMWindowUtils::DispatchDOMEventViaPre
 
   nsEventStatus status = nsEventStatus_eIgnore;
   targetShell->HandleEventWithTarget(internalEvent, nullptr, content, &status);
   *aRetVal = (status != nsEventStatus_eConsumeNoDefault);
   return NS_OK;
 }
 
 static void
-InitEvent(nsGUIEvent &aEvent, nsIntPoint *aPt = nullptr)
+InitEvent(nsGUIEvent& aEvent, LayoutDeviceIntPoint* aPt = nullptr)
 {
   if (aPt) {
     aEvent.refPoint = *aPt;
   }
   aEvent.time = PR_IntervalNow();
 }
 
 NS_IMETHODIMP
@@ -1919,42 +1919,44 @@ nsDOMWindowUtils::SendQueryContentEvent(
       aType != NS_QUERY_CARET_RECT &&
       aType != NS_QUERY_TEXT_RECT &&
       aType != NS_QUERY_EDITOR_RECT &&
       aType != NS_QUERY_CHARACTER_AT_POINT) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsCOMPtr<nsIWidget> targetWidget = widget;
-  nsIntPoint pt(aX, aY);
+  LayoutDeviceIntPoint pt(aX, aY);
 
   if (aType == QUERY_CHARACTER_AT_POINT) {
     // Looking for the widget at the point.
     nsQueryContentEvent dummyEvent(true, NS_QUERY_CONTENT_STATE, widget);
     InitEvent(dummyEvent, &pt);
     nsIFrame* popupFrame =
       nsLayoutUtils::GetPopupFrameForEventCoordinates(presContext->GetRootPresContext(), &dummyEvent);
 
     nsIntRect widgetBounds;
     nsresult rv = widget->GetClientBounds(widgetBounds);
     NS_ENSURE_SUCCESS(rv, rv);
     widgetBounds.MoveTo(0, 0);
 
     // There is no popup frame at the point and the point isn't in our widget,
     // we cannot process this request.
-    NS_ENSURE_TRUE(popupFrame || widgetBounds.Contains(pt),
+    NS_ENSURE_TRUE(popupFrame ||
+                   widgetBounds.Contains(LayoutDeviceIntPoint::ToUntyped(pt)),
                    NS_ERROR_FAILURE);
 
     // Fire the event on the widget at the point
     if (popupFrame) {
       targetWidget = popupFrame->GetNearestWidget();
     }
   }
 
-  pt += widget->WidgetToScreenOffset() - targetWidget->WidgetToScreenOffset();
+  pt += LayoutDeviceIntPoint::FromUntyped(
+    widget->WidgetToScreenOffset() - targetWidget->WidgetToScreenOffset());
 
   nsQueryContentEvent queryEvent(true, aType, targetWidget);
   InitEvent(queryEvent, &pt);
 
   switch (aType) {
     case NS_QUERY_TEXT_CONTENT:
       queryEvent.InitForQueryTextContent(aOffset, aLength);
       break;
@@ -3154,17 +3156,18 @@ nsDOMWindowUtils::SelectAtPoint(float aX
   nsIFrame* rootFrame = presShell->FrameManager()->GetRootFrame();
   if (!rootFrame) {
     return NS_ERROR_UNEXPECTED;
   }
 
   // Get the target frame at the client coordinates passed to us
   nsPoint offset;
   nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
-  nsIntPoint pt = ToWidgetPoint(aX, aY, offset, GetPresContext());
+  nsIntPoint pt = LayoutDeviceIntPoint::ToUntyped(
+    ToWidgetPoint(CSSPoint(aX, aY), offset, GetPresContext()));
   nsPoint ptInRoot =
     nsLayoutUtils::GetEventCoordinatesRelativeTo(widget, pt, rootFrame);
   nsIFrame* targetFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, ptInRoot);
   // This can happen if the page hasn't loaded yet or if the point
   // is outside the frame.
   if (!targetFrame) {
     return NS_ERROR_INVALID_ARG;
   }
--- 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
@@ -415,20 +415,20 @@ public:
 
         // Set category to chrome or content
         nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
           do_QueryInterface(mScriptGlobal);
         NS_ASSERTION(scriptPrincipal, "Global objects must implement "
                      "nsIScriptObjectPrincipal");
         nsCOMPtr<nsIPrincipal> systemPrincipal;
         sSecurityManager->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
-        const char * category =
+        const nsACString& category =
           scriptPrincipal->GetPrincipal() == systemPrincipal
-          ? "chrome javascript"
-          : "content javascript";
+          ? NS_LITERAL_CSTRING("chrome javascript")
+          : NS_LITERAL_CSTRING("content javascript");
 
         rv = errorObject->InitWithWindowID(mErrorMsg, mFileName,
                                            mSourceLine,
                                            mLineNr, mColumn, mFlags,
                                            category, mInnerWindowID);
 
         if (NS_SUCCEEDED(rv)) {
           nsCOMPtr<nsIConsoleService> consoleService =
@@ -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.cpp
+++ b/dom/base/nsWrapperCache.cpp
@@ -1,29 +1,47 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsWrapperCacheInlines.h"
 
+#include "jsproxy.h"
+#include "mozilla/dom/DOMJSProxyHandler.h"
 #include "nsCycleCollectionTraversalCallback.h"
 #include "nsCycleCollector.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 /* static */ void
 nsWrapperCache::HoldJSObjects(void* aScriptObjectHolder,
                               nsScriptObjectTracer* aTracer)
 {
   cyclecollector::AddJSHolder(aScriptObjectHolder, aTracer);
 }
 
+void
+nsWrapperCache::ReleaseWrapper(void* aScriptObjectHolder)
+{
+  if (PreservingWrapper()) {
+    // PreserveWrapper puts new DOM bindings in the JS holders hash, but they
+    // can also be in the DOM expando hash, so we need to try to remove them
+    // from both here.
+    JSObject* obj = GetWrapperPreserveColor();
+    if (IsDOMBinding() && obj && js::IsProxy(obj)) {
+      DOMProxyHandler::GetAndClearExpandoObject(obj);
+    }
+    SetPreservingWrapper(false);
+    cyclecollector::RemoveJSHolder(aScriptObjectHolder);
+  }
+}
+
 #ifdef DEBUG
 
 class DebugWrapperTraversalCallback : public nsCycleCollectionTraversalCallback
 {
 public:
   DebugWrapperTraversalCallback(void* aWrapper)
     : mFound(false)
     , mWrapper(aWrapper)
--- a/dom/base/nsWrapperCache.h
+++ b/dom/base/nsWrapperCache.h
@@ -239,16 +239,18 @@ public:
     HoldJSObjects(aScriptObjectHolder, aTracer);
     SetPreservingWrapper(true);
 #ifdef DEBUG
     // Make sure the cycle collector will be able to traverse to the wrapper.
     CheckCCWrapperTraversal(aScriptObjectHolder, aTracer);
 #endif
   }
 
+  void ReleaseWrapper(void* aScriptObjectHolder);
+
 private:
   JSObject *GetWrapperJSObject() const
   {
     return mWrapper;
   }
 
   void SetWrapperJSObject(JSObject* aWrapper)
   {
@@ -334,60 +336,64 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperC
 
 
 // Cycle collector macros for wrapper caches.
 
 #define NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER \
   tmp->TraceWrapper(aCallbacks, aClosure);
 
 #define NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \
-  nsContentUtils::ReleaseWrapper(p, tmp);
+  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)                  \
@@ -396,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)               \
@@ -417,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                           \
@@ -441,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           \
@@ -468,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)                    \
@@ -498,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)                    \
@@ -531,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)                    \
@@ -567,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)